import { Type } from "@sinclair/typebox"; import type { ExtensionAPI } from "../_shared/pi-api.js"; import { getCommandText, setTextWidget, textResult } from "../_shared/pi-api.js"; import { validateParams } from "../_shared/validation.js"; import { sharedState } from "../_shared/state.js"; const RouterParams = Type.Object({ preset: Type.Union([Type.Literal("minimal"), Type.Literal("dev"), Type.Literal("agentic-dev")], { description: "Activation preset" }), }); const PRESETS = { minimal: ["read", "search", "find", "ask"], dev: ["read", "search", "find", "bash", "ast_grep", "lsp", "todo_write"], "agentic-dev": ["read", "search", "find", "bash", "ast_grep", "lsp", "todo_write", "task", "loopControl", "planMode"], } satisfies Record; function presetTools(preset: string): string[] { return Object.prototype.hasOwnProperty.call(PRESETS, preset) ? PRESETS[preset as keyof typeof PRESETS] : PRESETS.minimal; } export default function toolRouter(pi: ExtensionAPI): void { pi.registerTool({ name: "toolRouter", description: "Activate audited tool presets so rare/high-risk tools stay disabled until needed.", parameters: RouterParams, execute(_toolCallId, params) { const valid = validateParams(RouterParams, params); if (!valid.ok) return valid.result; const tools = presetTools(valid.value.preset); sharedState.toolPreset = valid.value.preset; pi.setActiveTools(tools); return textResult(`Activated ${valid.value.preset}: ${tools.join(", ")}`, { preset: valid.value.preset, tools }); }, }); pi.registerCommand("tools", { description: "Show current tool preset or explicitly switch with /tools use .", handler: async (args, ctx) => { const text = getCommandText(args).trim(); if (!text || text === "status" || text === "list") { setTextWidget(ctx, "tools", formatToolStatus()); return; } const requested = text.replace(/^(use|switch)\s+/u, "").trim(); const preset = Object.prototype.hasOwnProperty.call(PRESETS, requested) ? requested : "minimal"; const tools = presetTools(preset); sharedState.toolPreset = preset; pi.setActiveTools(tools); const suffix = preset === requested ? "" : ` (unknown preset ${requested}; using minimal)`; setTextWidget(ctx, "tools", `${preset}: ${tools.join(", ")}${suffix}`); }, }); } function formatToolStatus(): string { const currentPreset = sharedState.toolPreset; const currentTools = presetTools(currentPreset); return [ `currentPreset: ${currentPreset}`, `currentPresetTools: ${currentTools.join(", ")}`, `availablePresets: ${Object.keys(PRESETS).join(", ")}`, "switch: /tools use ", ].join("\n"); } export { PRESETS };