slow tool settings
This commit is contained in:
@@ -7,5 +7,9 @@
|
|||||||
"lsp": {
|
"lsp": {
|
||||||
"hookMode": "edit_write"
|
"hookMode": "edit_write"
|
||||||
},
|
},
|
||||||
"hideThinkingBlock": false
|
"hideThinkingBlock": false,
|
||||||
|
"slowtool": {
|
||||||
|
"timeoutSeconds": 120,
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ExtensionAPI, ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
|
import type { ExtensionAPI, ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
|
||||||
|
import * as fs from "node:fs";
|
||||||
|
import * as path from "node:path";
|
||||||
|
import * as os from "node:os";
|
||||||
|
|
||||||
interface ToolTimeout {
|
interface ToolTimeout {
|
||||||
toolCallId: string;
|
toolCallId: string;
|
||||||
@@ -28,6 +31,8 @@ interface ToolTimeout {
|
|||||||
// Configuration
|
// Configuration
|
||||||
let timeoutSeconds = 30;
|
let timeoutSeconds = 30;
|
||||||
let enabled = true;
|
let enabled = true;
|
||||||
|
const SETTINGS_NAMESPACE = "slowtool";
|
||||||
|
const globalSettingsPath = path.join(os.homedir(), ".pi", "agent", "settings.json");
|
||||||
|
|
||||||
// Track running tools
|
// Track running tools
|
||||||
const runningTools: Map<string, ToolTimeout> = new Map();
|
const runningTools: Map<string, ToolTimeout> = new Map();
|
||||||
@@ -43,6 +48,55 @@ function formatDuration(ms: number): string {
|
|||||||
return `${minutes}m ${remainingSeconds}s`;
|
return `${minutes}m ${remainingSeconds}s`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function asRecord(value: unknown): Record<string, unknown> | undefined {
|
||||||
|
if (!value || typeof value !== "object") return undefined;
|
||||||
|
return value as Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readSettingsFile(filePath: string): Record<string, unknown> {
|
||||||
|
try {
|
||||||
|
if (!fs.existsSync(filePath)) return {};
|
||||||
|
const raw = fs.readFileSync(filePath, "utf-8");
|
||||||
|
const parsed = JSON.parse(raw) as unknown;
|
||||||
|
return asRecord(parsed) ?? {};
|
||||||
|
} catch {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadGlobalConfig(): { timeoutSeconds: number; enabled: boolean } {
|
||||||
|
const settings = readSettingsFile(globalSettingsPath);
|
||||||
|
const slowtoolSettings = asRecord(settings[SETTINGS_NAMESPACE]);
|
||||||
|
|
||||||
|
const configuredTimeout = slowtoolSettings?.timeoutSeconds;
|
||||||
|
const nextTimeout =
|
||||||
|
typeof configuredTimeout === "number" && Number.isFinite(configuredTimeout) && configuredTimeout >= 1
|
||||||
|
? Math.floor(configuredTimeout)
|
||||||
|
: 30;
|
||||||
|
|
||||||
|
const configuredEnabled = slowtoolSettings?.enabled;
|
||||||
|
const nextEnabled = typeof configuredEnabled === "boolean" ? configuredEnabled : true;
|
||||||
|
|
||||||
|
return { timeoutSeconds: nextTimeout, enabled: nextEnabled };
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveGlobalConfig(next: { timeoutSeconds: number; enabled: boolean }): boolean {
|
||||||
|
try {
|
||||||
|
const settings = readSettingsFile(globalSettingsPath);
|
||||||
|
const existing = asRecord(settings[SETTINGS_NAMESPACE]) ?? {};
|
||||||
|
settings[SETTINGS_NAMESPACE] = {
|
||||||
|
...existing,
|
||||||
|
timeoutSeconds: next.timeoutSeconds,
|
||||||
|
enabled: next.enabled,
|
||||||
|
};
|
||||||
|
fs.mkdirSync(path.dirname(globalSettingsPath), { recursive: true });
|
||||||
|
fs.writeFileSync(globalSettingsPath, `${JSON.stringify(settings, null, 2)}\n`, "utf-8");
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getCommandPreview(args: unknown): string | undefined {
|
function getCommandPreview(args: unknown): string | undefined {
|
||||||
if (!args) return undefined;
|
if (!args) return undefined;
|
||||||
const anyArgs = args as Record<string, unknown>;
|
const anyArgs = args as Record<string, unknown>;
|
||||||
@@ -77,6 +131,29 @@ function notifyTimeout(pi: ExtensionAPI, tool: ToolTimeout): void {
|
|||||||
// ============ EVENT HANDLERS ============
|
// ============ EVENT HANDLERS ============
|
||||||
|
|
||||||
export default function(pi: ExtensionAPI) {
|
export default function(pi: ExtensionAPI) {
|
||||||
|
const applyPersistedConfig = () => {
|
||||||
|
const persisted = loadGlobalConfig();
|
||||||
|
timeoutSeconds = persisted.timeoutSeconds;
|
||||||
|
enabled = persisted.enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
const persistCurrentConfig = (ctx: ExtensionCommandContext): void => {
|
||||||
|
const ok = saveGlobalConfig({ timeoutSeconds, enabled });
|
||||||
|
if (!ok) {
|
||||||
|
ctx.ui.notify("Failed to persist slowtool settings", "warning");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
applyPersistedConfig();
|
||||||
|
|
||||||
|
pi.on("session_start", async (_event, _ctx) => {
|
||||||
|
applyPersistedConfig();
|
||||||
|
});
|
||||||
|
|
||||||
|
pi.on("session_switch", async (_event, _ctx) => {
|
||||||
|
applyPersistedConfig();
|
||||||
|
});
|
||||||
|
|
||||||
// Register commands
|
// Register commands
|
||||||
pi.registerCommand("slowtool:timeout", {
|
pi.registerCommand("slowtool:timeout", {
|
||||||
description: "Set timeout threshold in seconds (default: 30)",
|
description: "Set timeout threshold in seconds (default: 30)",
|
||||||
@@ -91,6 +168,7 @@ export default function(pi: ExtensionAPI) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
timeoutSeconds = newTimeout;
|
timeoutSeconds = newTimeout;
|
||||||
|
persistCurrentConfig(ctx);
|
||||||
ctx.ui.notify(`Timeout set to ${timeoutSeconds}s`, "info");
|
ctx.ui.notify(`Timeout set to ${timeoutSeconds}s`, "info");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -99,6 +177,7 @@ export default function(pi: ExtensionAPI) {
|
|||||||
description: "Enable slow tool notifications",
|
description: "Enable slow tool notifications",
|
||||||
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
|
persistCurrentConfig(ctx);
|
||||||
ctx.ui.notify("Slow tool notifications enabled", "info");
|
ctx.ui.notify("Slow tool notifications enabled", "info");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -107,6 +186,7 @@ export default function(pi: ExtensionAPI) {
|
|||||||
description: "Disable slow tool notifications",
|
description: "Disable slow tool notifications",
|
||||||
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
||||||
enabled = false;
|
enabled = false;
|
||||||
|
persistCurrentConfig(ctx);
|
||||||
ctx.ui.notify("Slow tool notifications disabled", "info");
|
ctx.ui.notify("Slow tool notifications disabled", "info");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user