my-pi 0.0.13 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{api-CWEizv2k.js → api-1ZXLxSgP.js} +223 -43
- package/dist/api-1ZXLxSgP.js.map +1 -0
- package/dist/api.js +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/extensions/config.test.ts +3 -0
- package/src/extensions/config.ts +12 -2
- package/src/extensions/handoff.ts +152 -66
- package/src/extensions/session-name.ts +234 -0
- package/dist/api-CWEizv2k.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-1ZXLxSgP.js","names":["DEFAULT_CONFIG","ENABLED","DISABLED","to_setting_item","sets_equal","SYSTEM_PROMPT","#options","#proc","#emit_error","#initialized","#pending","#buffer","#drain_buffer","#request","#notify","#open_docs","#diagnostics_by_uri","#diagnostic_waiters","#next_id","#send","#handle_message","#config","#connect_stdio","#request","#send","#disconnect_http","#proc","#pending","#buffer","#handle_message","#nextId","#send_http","#sessionId","#consume_sse_response","#dispatch_message","ENABLED","DISABLED","sets_equal","DEFAULT_CONFIG","mcp_extension","skills_extension","chain_extension","filter_output_extension","handoff_extension","recall_extension","prompt_presets_extension","lsp_extension","session_name_extension"],"sources":["../src/extensions/chain.ts","../src/extensions/config.ts","../src/extensions/extensions.ts","../src/extensions/filter-output.ts","../src/extensions/handoff.ts","../src/lsp/client.ts","../src/lsp/servers.ts","../src/extensions/lsp.ts","../src/mcp/client.ts","../src/mcp/config.ts","../src/extensions/mcp.ts","../src/extensions/prompt-presets.ts","../src/extensions/recall.ts","../src/extensions/session-name.ts","../src/skills/config.ts","../src/skills/scanner.ts","../src/skills/importer.ts","../src/skills/manager.ts","../src/extensions/skills.ts","../src/extensions/telemetry-config.ts","../src/extensions/telemetry.ts","../src/api.ts"],"sourcesContent":["// Agent chain extension — sequential pipeline orchestrator\n// Inspired by https://github.com/disler/pi-vs-claude-code/blob/main/extensions/agent-chain.ts\n\nimport {\n\ttype ExtensionAPI,\n\tdefineTool,\n\tparseFrontmatter,\n} from '@mariozechner/pi-coding-agent';\nimport { Type } from '@sinclair/typebox';\nimport { spawn } from 'node:child_process';\nimport { existsSync, readFileSync, readdirSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n// ── Types ───────────────────────────────────────\n\ninterface ChainStep {\n\tagent: string;\n\tprompt: string;\n}\n\ninterface ChainDef {\n\tname: string;\n\tdescription: string;\n\tsteps: ChainStep[];\n}\n\ninterface AgentDef {\n\tname: string;\n\tdescription: string;\n\ttools: string;\n\tsystemPrompt: string;\n}\n\n// ── YAML parser (minimal, no dep) ──────────────\n\nfunction parse_chain_yaml(raw: string): ChainDef[] {\n\tconst chains: ChainDef[] = [];\n\tlet current: ChainDef | null = null;\n\tlet current_step: ChainStep | null = null;\n\n\tfor (const line of raw.split('\\n')) {\n\t\tconst chain_match = line.match(/^(\\S[^:]*):$/);\n\t\tif (chain_match) {\n\t\t\tif (current && current_step) {\n\t\t\t\tcurrent.steps.push(current_step);\n\t\t\t\tcurrent_step = null;\n\t\t\t}\n\t\t\tcurrent = {\n\t\t\t\tname: chain_match[1].trim(),\n\t\t\t\tdescription: '',\n\t\t\t\tsteps: [],\n\t\t\t};\n\t\t\tchains.push(current);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst desc_match = line.match(/^\\s+description:\\s+(.+)$/);\n\t\tif (desc_match && current && !current_step) {\n\t\t\tlet desc = desc_match[1].trim();\n\t\t\tif (\n\t\t\t\t(desc.startsWith('\"') && desc.endsWith('\"')) ||\n\t\t\t\t(desc.startsWith(\"'\") && desc.endsWith(\"'\"))\n\t\t\t) {\n\t\t\t\tdesc = desc.slice(1, -1);\n\t\t\t}\n\t\t\tcurrent.description = desc;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (line.match(/^\\s+steps:\\s*$/) && current) continue;\n\n\t\tconst agent_match = line.match(/^\\s+-\\s+agent:\\s+(.+)$/);\n\t\tif (agent_match && current) {\n\t\t\tif (current_step) current.steps.push(current_step);\n\t\t\tcurrent_step = {\n\t\t\t\tagent: agent_match[1].trim(),\n\t\t\t\tprompt: '',\n\t\t\t};\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst prompt_match = line.match(/^\\s+prompt:\\s+(.+)$/);\n\t\tif (prompt_match && current_step) {\n\t\t\tlet prompt = prompt_match[1].trim();\n\t\t\tif (\n\t\t\t\t(prompt.startsWith('\"') && prompt.endsWith('\"')) ||\n\t\t\t\t(prompt.startsWith(\"'\") && prompt.endsWith(\"'\"))\n\t\t\t) {\n\t\t\t\tprompt = prompt.slice(1, -1);\n\t\t\t}\n\t\t\tprompt = prompt.replace(/\\\\n/g, '\\n');\n\t\t\tcurrent_step.prompt = prompt;\n\t\t\tcontinue;\n\t\t}\n\t}\n\n\tif (current && current_step) {\n\t\tcurrent.steps.push(current_step);\n\t}\n\n\treturn chains;\n}\n\n// ── Agent file parser ──────────────────────────\n\nfunction parse_agent_file(filePath: string): AgentDef | null {\n\ttry {\n\t\tconst raw = readFileSync(filePath, 'utf-8');\n\t\tconst { frontmatter, body } = parseFrontmatter<{\n\t\t\tname?: string;\n\t\t\tdescription?: string;\n\t\t\ttools?: string;\n\t\t}>(raw);\n\n\t\tif (!frontmatter?.name) return null;\n\n\t\treturn {\n\t\t\tname: frontmatter.name,\n\t\t\tdescription: frontmatter.description || '',\n\t\t\ttools: frontmatter.tools || 'read,grep,find,ls',\n\t\t\tsystemPrompt: body.trim(),\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction scan_agent_dirs(cwd: string): Map<string, AgentDef> {\n\tconst dirs = [\n\t\tjoin(cwd, 'agents'),\n\t\tjoin(cwd, '.claude', 'agents'),\n\t\tjoin(cwd, '.pi', 'agents'),\n\t];\n\n\tconst agents = new Map<string, AgentDef>();\n\n\tfor (const dir of dirs) {\n\t\tif (!existsSync(dir)) continue;\n\t\ttry {\n\t\t\tfor (const file of readdirSync(dir)) {\n\t\t\t\tif (!file.endsWith('.md')) continue;\n\t\t\t\tconst def = parse_agent_file(resolve(dir, file));\n\t\t\t\tif (def && !agents.has(def.name.toLowerCase())) {\n\t\t\t\t\tagents.set(def.name.toLowerCase(), def);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// skip inaccessible dirs\n\t\t}\n\t}\n\n\treturn agents;\n}\n\n// ── Run a single agent step via my-pi print mode ─\n\nconst AGENT_STEP_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\n\nfunction run_agent_step(\n\tagent_def: AgentDef,\n\ttask: string,\n\tmodel?: string,\n): Promise<{ output: string; exitCode: number }> {\n\t// Resolve bin path: prefer known dist location over process.argv[1]\n\t// (process.argv[1] may point to a wrapper like codex, not my-pi)\n\tconst bin = join(__dirname, '..', 'index.js');\n\tconst args = ['--no-builtin', '--json', '--prompt', task];\n\tif (model) {\n\t\targs.push('--model', model);\n\t}\n\n\tconst chunks: string[] = [];\n\n\treturn new Promise((res) => {\n\t\tlet settled = false;\n\t\tconst resolve_once = (result: {\n\t\t\toutput: string;\n\t\t\texitCode: number;\n\t\t}) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timer);\n\t\t\tres(result);\n\t\t};\n\n\t\tconst proc = spawn(process.execPath, [bin, ...args], {\n\t\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\tMY_PI_AGENT_SYSTEM_PROMPT: agent_def.systemPrompt,\n\t\t\t},\n\t\t});\n\n\t\tconst timer = setTimeout(() => {\n\t\t\tproc.kill('SIGTERM');\n\t\t\tresolve_once({\n\t\t\t\toutput: `Agent step timed out after ${AGENT_STEP_TIMEOUT_MS / 1000}s`,\n\t\t\t\texitCode: 1,\n\t\t\t});\n\t\t}, AGENT_STEP_TIMEOUT_MS);\n\n\t\tproc.stdout!.setEncoding('utf-8');\n\t\tproc.stdout!.on('data', (chunk: string) => {\n\t\t\tchunks.push(chunk);\n\t\t});\n\n\t\tproc.stderr!.setEncoding('utf-8');\n\t\tproc.stderr!.on('data', () => {});\n\n\t\tproc.on('close', (code) => {\n\t\t\t// Parse NDJSON events to extract assistant text content\n\t\t\tconst raw = chunks.join('');\n\t\t\tconst text_parts: string[] = [];\n\t\t\tfor (const line of raw.split('\\n')) {\n\t\t\t\tif (!line.trim()) continue;\n\t\t\t\ttry {\n\t\t\t\t\tconst event = JSON.parse(line);\n\t\t\t\t\tif (\n\t\t\t\t\t\tevent?.role === 'assistant' &&\n\t\t\t\t\t\tArray.isArray(event?.content)\n\t\t\t\t\t) {\n\t\t\t\t\t\tfor (const c of event.content) {\n\t\t\t\t\t\t\tif (c.type === 'text' && c.text) {\n\t\t\t\t\t\t\t\ttext_parts.push(c.text);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// not JSON — use raw line\n\t\t\t\t\ttext_parts.push(line);\n\t\t\t\t}\n\t\t\t}\n\t\t\tresolve_once({\n\t\t\t\toutput: text_parts.join('\\n').trim() || raw.trim(),\n\t\t\t\texitCode: code ?? 1,\n\t\t\t});\n\t\t});\n\n\t\tproc.on('error', (err) => {\n\t\t\tresolve_once({\n\t\t\t\toutput: `Error spawning agent: ${err.message}`,\n\t\t\t\texitCode: 1,\n\t\t\t});\n\t\t});\n\t});\n}\n\n// ── Extension ──────────────────────────────────\n\n// Default export for Pi Package / additionalExtensionPaths loading\nfunction parse_model_from_argv(): string | undefined {\n\tconst argv = process.argv;\n\tfor (let i = 0; i < argv.length; i++) {\n\t\tif (\n\t\t\t(argv[i] === '--model' || argv[i] === '-m') &&\n\t\t\ti + 1 < argv.length\n\t\t) {\n\t\t\treturn argv[i + 1];\n\t\t}\n\t\tif (argv[i]?.startsWith('--model=')) {\n\t\t\treturn argv[i].slice('--model='.length);\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport default async function chain(pi: ExtensionAPI) {\n\tconst cwd = process.cwd();\n\tconst agents = scan_agent_dirs(cwd);\n\tconst current_model = parse_model_from_argv();\n\tlet chains: ChainDef[] = [];\n\tlet active_chain: ChainDef | null = null;\n\n\t// Load chain definitions\n\tconst chain_paths = [\n\t\tjoin(cwd, '.pi', 'agents', 'agent-chain.yaml'),\n\t\tjoin(cwd, '.pi', 'agents', 'chains.yaml'),\n\t\tjoin(cwd, '.claude', 'agents', 'chains.yaml'),\n\t];\n\n\tfor (const path of chain_paths) {\n\t\tif (existsSync(path)) {\n\t\t\ttry {\n\t\t\t\tchains = parse_chain_yaml(readFileSync(path, 'utf-8'));\n\t\t\t\tbreak;\n\t\t\t} catch {\n\t\t\t\t// try next\n\t\t\t}\n\t\t}\n\t}\n\n\tif (chains.length > 0) {\n\t\tactive_chain = chains[0];\n\t}\n\n\t// ── run_chain tool ─────────────────────────\n\n\tpi.registerTool(\n\t\tdefineTool({\n\t\t\tname: 'run_chain',\n\t\t\tlabel: 'Run Chain',\n\t\t\tdescription:\n\t\t\t\t\"Execute the active agent chain pipeline. Each step runs sequentially — output from one step feeds into the next as $INPUT. $ORIGINAL is always the user's initial prompt.\",\n\t\t\tparameters: Type.Object({\n\t\t\t\ttask: Type.String({\n\t\t\t\t\tdescription: 'The task/prompt for the chain to process',\n\t\t\t\t}),\n\t\t\t}),\n\t\t\texecute: async (\n\t\t\t\t_id: string,\n\t\t\t\tparams: unknown,\n\t\t\t): Promise<{\n\t\t\t\tcontent: Array<{ type: 'text'; text: string }>;\n\t\t\t\tdetails: { chain: string; steps: number };\n\t\t\t}> => {\n\t\t\t\tconst { task } = params as { task: string };\n\n\t\t\t\tif (!active_chain) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'text' as const,\n\t\t\t\t\t\t\t\ttext: 'No chain active. Use /chain to select one.',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\tchain: '',\n\t\t\t\t\t\t\tsteps: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tlet input = task;\n\t\t\t\tconst original = task;\n\t\t\t\tconst results: string[] = [];\n\n\t\t\t\tfor (let i = 0; i < active_chain.steps.length; i++) {\n\t\t\t\t\tconst step = active_chain.steps[i];\n\t\t\t\t\tconst agent_def = agents.get(step.agent.toLowerCase());\n\n\t\t\t\t\tif (!agent_def) {\n\t\t\t\t\t\tconst msg = `Step ${i + 1}: agent \"${step.agent}\" not found. Available: ${Array.from(agents.keys()).join(', ')}`;\n\t\t\t\t\t\tresults.push(msg);\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcontent: [{ type: 'text' as const, text: msg }],\n\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\tchain: active_chain.name,\n\t\t\t\t\t\t\t\tsteps: i,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\tconst resolved_prompt = step.prompt\n\t\t\t\t\t\t.replace(/\\$INPUT/g, input)\n\t\t\t\t\t\t.replace(/\\$ORIGINAL/g, original);\n\n\t\t\t\t\tconst result = await run_agent_step(\n\t\t\t\t\t\tagent_def,\n\t\t\t\t\t\tresolved_prompt,\n\t\t\t\t\t\tcurrent_model,\n\t\t\t\t\t);\n\n\t\t\t\t\tif (result.exitCode !== 0) {\n\t\t\t\t\t\tconst msg = `Step ${i + 1} (${step.agent}) failed:\\n${result.output}`;\n\t\t\t\t\t\tresults.push(msg);\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcontent: [{ type: 'text' as const, text: msg }],\n\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\tchain: active_chain.name,\n\t\t\t\t\t\t\t\tsteps: i + 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\tresults.push(\n\t\t\t\t\t\t`## Step ${i + 1}: ${step.agent}\\n${result.output}`,\n\t\t\t\t\t);\n\t\t\t\t\tinput = result.output;\n\t\t\t\t}\n\n\t\t\t\tconst summary = results.join('\\n\\n---\\n\\n');\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: 'text' as const, text: summary }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tchain: active_chain.name,\n\t\t\t\t\t\tsteps: active_chain.steps.length,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t}),\n\t);\n\n\t// ── /chain command ─────────────────────────\n\n\tpi.registerCommand('chain', {\n\t\tdescription: 'Switch active chain or list chains (chain list)',\n\t\tgetArgumentCompletions: (prefix) => {\n\t\t\tconst parts = prefix.trim().split(/\\s+/);\n\t\t\tif (parts.length <= 1) {\n\t\t\t\tconst subs = ['list', ...chains.map((c) => c.name)];\n\t\t\t\treturn subs\n\t\t\t\t\t.filter((s) => s.startsWith(parts[0] || ''))\n\t\t\t\t\t.map((s) => ({ value: s, label: s }));\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\thandler: async (args, ctx) => {\n\t\t\tconst sub = args.trim();\n\n\t\t\tif (!sub || sub === 'list') {\n\t\t\t\tif (chains.length === 0) {\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t'No chains found. Add chains to .pi/agents/agent-chain.yaml',\n\t\t\t\t\t\t'warning',\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst lines = chains.map((c) => {\n\t\t\t\t\tconst active = c.name === active_chain?.name ? ' *' : '';\n\t\t\t\t\tconst steps = c.steps.map((s) => s.agent).join(' -> ');\n\t\t\t\t\treturn `${c.name}${active}: ${c.description || steps}`;\n\t\t\t\t});\n\t\t\t\tctx.ui.notify(lines.join('\\n'));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst found_chain = chains.find(\n\t\t\t\t(c) => c.name.toLowerCase() === sub.toLowerCase(),\n\t\t\t);\n\t\t\tif (!found_chain) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Unknown chain: ${sub}. Use /chain list.`,\n\t\t\t\t\t'warning',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tactive_chain = found_chain;\n\t\t\tconst flow = found_chain.steps.map((s) => s.agent).join(' -> ');\n\t\t\tctx.ui.notify(`Active chain: ${found_chain.name} (${flow})`);\n\t\t},\n\t});\n\n\t// ── System prompt injection ────────────────\n\n\tpi.on(\n\t\t'before_agent_start',\n\t\tasync (event: { systemPrompt: string }) => {\n\t\t\tif (!active_chain || chains.length === 0) return {};\n\n\t\t\tconst flow = active_chain.steps\n\t\t\t\t.map((s) => s.agent)\n\t\t\t\t.join(' -> ');\n\n\t\t\tconst step_list = active_chain.steps\n\t\t\t\t.map((s, i) => {\n\t\t\t\t\tconst def = agents.get(s.agent.toLowerCase());\n\t\t\t\t\tconst desc = def?.description || 'unknown';\n\t\t\t\t\treturn `${i + 1}. **${s.agent}** — ${desc}`;\n\t\t\t\t})\n\t\t\t\t.join('\\n');\n\n\t\t\tconst chain_list = chains\n\t\t\t\t.map((c) => {\n\t\t\t\t\tconst active =\n\t\t\t\t\t\tc.name === active_chain?.name ? ' (active)' : '';\n\t\t\t\t\treturn `- ${c.name}${active}: ${c.description}`;\n\t\t\t\t})\n\t\t\t\t.join('\\n');\n\n\t\t\t// Append chain context to the existing system prompt\n\t\t\treturn {\n\t\t\t\tsystemPrompt:\n\t\t\t\t\tevent.systemPrompt +\n\t\t\t\t\t`\n\n## Agent Chains\n\nYou have a run_chain tool that executes sequential agent pipelines.\n\n### Active Chain: ${active_chain.name}\n${active_chain.description}\nFlow: ${flow}\n\n${step_list}\n\n### Available Chains\n${chain_list}\n\n### When to use run_chain\n- Non-trivial work: features, refactors, multi-file changes\n- Tasks that benefit from planning then building then reviewing\n- When structured multi-agent collaboration helps\n\n### When to work directly\n- Simple reads, quick lookups, small edits\n- Answering questions about the codebase\n- Anything you can handle in one step\n\nSwitch chains with /chain <name>.`,\n\t\t\t};\n\t\t},\n\t);\n\n\t// ── /agents command ────────────────────────\n\n\tpi.registerCommand('agents', {\n\t\tdescription: 'List discovered agent definitions',\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (agents.size === 0) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t'No agents found in agents/, .pi/agents/, or .claude/agents/',\n\t\t\t\t\t'warning',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst lines = Array.from(agents.values()).map(\n\t\t\t\t(a) =>\n\t\t\t\t\t`${a.name}: ${a.description || '(no description)'} [${a.tools}]`,\n\t\t\t);\n\t\t\tctx.ui.notify(lines.join('\\n'));\n\t\t},\n\t});\n}\n","import {\n\texistsSync,\n\tmkdirSync,\n\treadFileSync,\n\trenameSync,\n\twriteFileSync,\n} from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\nexport type BuiltinExtensionKey =\n\t| 'mcp'\n\t| 'skills'\n\t| 'chain'\n\t| 'filter-output'\n\t| 'handoff'\n\t| 'recall'\n\t| 'prompt-presets'\n\t| 'lsp'\n\t| 'session-name';\n\nexport interface BuiltinExtensionInfo {\n\tkey: BuiltinExtensionKey;\n\tlabel: string;\n\tdescription: string;\n\tcli_flag: string;\n\taliases: string[];\n}\n\nexport interface BuiltinExtensionsConfig {\n\tversion: number;\n\tenabled: Partial<Record<BuiltinExtensionKey, boolean>>;\n}\n\nexport interface BuiltinExtensionState extends BuiltinExtensionInfo {\n\tsaved_enabled: boolean;\n\teffective_enabled: boolean;\n\tforced_disabled: boolean;\n}\n\nconst DEFAULT_CONFIG: BuiltinExtensionsConfig = {\n\tversion: 1,\n\tenabled: {},\n};\n\nexport const BUILTIN_EXTENSIONS: BuiltinExtensionInfo[] = [\n\t{\n\t\tkey: 'mcp',\n\t\tlabel: 'MCP',\n\t\tdescription: 'MCP server integration and /mcp command',\n\t\tcli_flag: '--no-mcp',\n\t\taliases: ['mcp'],\n\t},\n\t{\n\t\tkey: 'skills',\n\t\tlabel: 'Skills',\n\t\tdescription: 'Managed pi-native skills and /skills command',\n\t\tcli_flag: '--no-skills',\n\t\taliases: ['skills', 'skill'],\n\t},\n\t{\n\t\tkey: 'chain',\n\t\tlabel: 'Chain',\n\t\tdescription: 'Agent chain orchestration and /chain command',\n\t\tcli_flag: '--no-chain',\n\t\taliases: ['chain', 'chains'],\n\t},\n\t{\n\t\tkey: 'filter-output',\n\t\tlabel: 'Filter output',\n\t\tdescription: 'Secret redaction for tool output',\n\t\tcli_flag: '--no-filter',\n\t\taliases: [\n\t\t\t'filter-output',\n\t\t\t'filter_output',\n\t\t\t'filter',\n\t\t\t'redaction',\n\t\t],\n\t},\n\t{\n\t\tkey: 'handoff',\n\t\tlabel: 'Handoff',\n\t\tdescription:\n\t\t\t'AI-generated session handoff with editor review and new-session prefill',\n\t\tcli_flag: '--no-handoff',\n\t\taliases: ['handoff'],\n\t},\n\t{\n\t\tkey: 'recall',\n\t\tlabel: 'Recall',\n\t\tdescription: 'Past session recall guidance and /recall command',\n\t\tcli_flag: '--no-recall',\n\t\taliases: ['recall'],\n\t},\n\t{\n\t\tkey: 'prompt-presets',\n\t\tlabel: 'Prompt presets',\n\t\tdescription:\n\t\t\t'Runtime prompt preset selection and /preset command',\n\t\tcli_flag: '--no-prompt-presets',\n\t\taliases: ['prompt-presets', 'preset', 'presets'],\n\t},\n\t{\n\t\tkey: 'lsp',\n\t\tlabel: 'LSP',\n\t\tdescription:\n\t\t\t'Language Server Protocol tools (diagnostics, hover, definition, references)',\n\t\tcli_flag: '--no-lsp',\n\t\taliases: ['lsp', 'language-server'],\n\t},\n\t{\n\t\tkey: 'session-name',\n\t\tlabel: 'Session name',\n\t\tdescription:\n\t\t\t'AI-powered session auto-naming and /session-name command',\n\t\tcli_flag: '--no-session-name',\n\t\taliases: ['session-name', 'session', 'auto-name'],\n\t},\n];\n\nexport function get_builtin_extensions_config_path(): string {\n\tconst xdg =\n\t\tprocess.env.XDG_CONFIG_HOME || join(homedir(), '.config');\n\treturn join(xdg, 'my-pi', 'extensions.json');\n}\n\nexport function load_builtin_extensions_config(): BuiltinExtensionsConfig {\n\tconst path = get_builtin_extensions_config_path();\n\tif (!existsSync(path)) return { ...DEFAULT_CONFIG };\n\n\ttry {\n\t\tconst raw = readFileSync(path, 'utf-8');\n\t\tconst parsed = JSON.parse(\n\t\t\traw,\n\t\t) as Partial<BuiltinExtensionsConfig>;\n\t\tconst enabled: BuiltinExtensionsConfig['enabled'] = {};\n\t\tfor (const extension of BUILTIN_EXTENSIONS) {\n\t\t\tconst value = parsed.enabled?.[extension.key];\n\t\t\tif (typeof value === 'boolean') {\n\t\t\t\tenabled[extension.key] = value;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tversion: parsed.version ?? 1,\n\t\t\tenabled,\n\t\t};\n\t} catch {\n\t\treturn { ...DEFAULT_CONFIG };\n\t}\n}\n\nexport function save_builtin_extensions_config(\n\tconfig: BuiltinExtensionsConfig,\n): void {\n\tconst path = get_builtin_extensions_config_path();\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n\n\tconst tmp = `${path}.tmp-${Date.now()}`;\n\twriteFileSync(tmp, JSON.stringify(config, null, '\\t') + '\\n', {\n\t\tmode: 0o600,\n\t});\n\trenameSync(tmp, path);\n}\n\nexport function is_builtin_extension_enabled(\n\tconfig: BuiltinExtensionsConfig,\n\tkey: BuiltinExtensionKey,\n): boolean {\n\treturn config.enabled[key] ?? true;\n}\n\nexport function is_builtin_extension_active(\n\tconfig: BuiltinExtensionsConfig,\n\tkey: BuiltinExtensionKey,\n\tforce_disabled: ReadonlySet<BuiltinExtensionKey> = new Set(),\n): boolean {\n\treturn (\n\t\tis_builtin_extension_enabled(config, key) &&\n\t\t!force_disabled.has(key)\n\t);\n}\n\nexport function resolve_builtin_extension_states(\n\tforce_disabled: ReadonlySet<BuiltinExtensionKey> = new Set(),\n\tconfig: BuiltinExtensionsConfig = load_builtin_extensions_config(),\n): BuiltinExtensionState[] {\n\treturn BUILTIN_EXTENSIONS.map((extension) => {\n\t\tconst saved_enabled = is_builtin_extension_enabled(\n\t\t\tconfig,\n\t\t\textension.key,\n\t\t);\n\t\tconst forced = force_disabled.has(extension.key);\n\t\treturn {\n\t\t\t...extension,\n\t\t\tsaved_enabled,\n\t\t\teffective_enabled: saved_enabled && !forced,\n\t\t\tforced_disabled: forced,\n\t\t};\n\t});\n}\n\nexport function find_builtin_extension(\n\tquery: string,\n): BuiltinExtensionInfo | undefined {\n\tconst normalized = query.trim().toLowerCase();\n\tif (!normalized) return undefined;\n\n\treturn BUILTIN_EXTENSIONS.find((extension) =>\n\t\t[extension.key, extension.label, ...extension.aliases].some(\n\t\t\t(value) => value.toLowerCase() === normalized,\n\t\t),\n\t);\n}\n","import type { ExtensionAPI } from '@mariozechner/pi-coding-agent';\nimport {\n\tContainer,\n\tSettingsList,\n\tText,\n\ttype SettingItem,\n} from '@mariozechner/pi-tui';\nimport {\n\tBUILTIN_EXTENSIONS,\n\tfind_builtin_extension,\n\tload_builtin_extensions_config,\n\tresolve_builtin_extension_states,\n\tsave_builtin_extensions_config,\n\ttype BuiltinExtensionKey,\n\ttype BuiltinExtensionState,\n} from './config.js';\n\nconst ENABLED = '[x]';\nconst DISABLED = '[ ]';\n\nexport interface ExtensionsManagerOptions {\n\tforce_disabled?: Iterable<BuiltinExtensionKey>;\n}\n\nfunction to_force_disabled_set(\n\tforce_disabled?: Iterable<BuiltinExtensionKey>,\n): ReadonlySet<BuiltinExtensionKey> {\n\treturn new Set(force_disabled ?? []);\n}\n\nfunction format_effective_state(\n\tstate: BuiltinExtensionState,\n): string {\n\tif (state.effective_enabled) {\n\t\treturn 'enabled';\n\t}\n\tif (state.forced_disabled) {\n\t\treturn `disabled in this process by ${state.cli_flag}`;\n\t}\n\treturn 'disabled';\n}\n\nfunction format_extension_lines(\n\tstates: BuiltinExtensionState[],\n\toptions?: { heading?: string },\n): string {\n\tconst lines: string[] = [];\n\tif (options?.heading) {\n\t\tlines.push(options.heading, '');\n\t}\n\n\tconst enabled_now = states.filter(\n\t\t(state) => state.effective_enabled,\n\t).length;\n\tconst disabled_now = states.length - enabled_now;\n\tlines.push(\n\t\t`${states.length} built-in extensions (${enabled_now} enabled now, ${disabled_now} disabled now)`,\n\t\t'',\n\t);\n\n\tfor (const state of states) {\n\t\tlines.push(\n\t\t\t`${state.saved_enabled ? ENABLED : DISABLED} ${state.label}`,\n\t\t);\n\t\tlines.push(` key: ${state.key}`);\n\t\tlines.push(\n\t\t\t` saved config: ${state.saved_enabled ? 'enabled' : 'disabled'}`,\n\t\t);\n\t\tlines.push(\n\t\t\t` current process: ${format_effective_state(state)}`,\n\t\t);\n\t\tlines.push(` ${state.description}`);\n\t}\n\n\treturn lines.join('\\n');\n}\n\nfunction to_setting_item(state: BuiltinExtensionState): SettingItem {\n\tconst detail_lines = [\n\t\tstate.key,\n\t\tstate.description,\n\t\t`current process: ${format_effective_state(state)}`,\n\t\t`startup override: ${state.cli_flag}`,\n\t];\n\n\treturn {\n\t\tid: state.key,\n\t\tlabel: state.label,\n\t\tdescription: detail_lines.join('\\n'),\n\t\tcurrentValue: state.saved_enabled ? ENABLED : DISABLED,\n\t\tvalues: [ENABLED, DISABLED],\n\t};\n}\n\nfunction sets_equal(\n\ta: ReadonlySet<string>,\n\tb: ReadonlySet<string>,\n): boolean {\n\tif (a.size !== b.size) return false;\n\tfor (const value of a) {\n\t\tif (!b.has(value)) return false;\n\t}\n\treturn true;\n}\n\nfunction search_states(\n\tstates: BuiltinExtensionState[],\n\tquery: string,\n): BuiltinExtensionState[] {\n\tconst normalized = query.trim().toLowerCase();\n\tif (!normalized) return states;\n\n\treturn states.filter((state) =>\n\t\t[\n\t\t\tstate.key,\n\t\t\tstate.label,\n\t\t\tstate.description,\n\t\t\t...state.aliases,\n\t\t].some((value) => value.toLowerCase().includes(normalized)),\n\t);\n}\n\nfunction save_extension_enabled(\n\tkey: BuiltinExtensionKey,\n\tenabled: boolean,\n): void {\n\tconst config = load_builtin_extensions_config();\n\tconfig.enabled[key] = enabled;\n\tsave_builtin_extensions_config(config);\n}\n\nexport function create_extensions_extension(\n\toptions: ExtensionsManagerOptions = {},\n) {\n\tconst force_disabled = to_force_disabled_set(\n\t\toptions.force_disabled,\n\t);\n\n\treturn async function extensions(pi: ExtensionAPI) {\n\t\tconst subs = ['list', 'enable', 'disable', 'toggle', 'search'];\n\n\t\tpi.registerCommand('extensions', {\n\t\t\tdescription: 'Manage built-in my-pi extensions',\n\t\t\tgetArgumentCompletions: (prefix) => {\n\t\t\t\tconst parts = prefix.trim().split(/\\s+/);\n\t\t\t\tif (parts.length <= 1) {\n\t\t\t\t\treturn subs\n\t\t\t\t\t\t.filter((sub) => sub.startsWith(parts[0] || ''))\n\t\t\t\t\t\t.map((sub) => ({ value: sub, label: sub }));\n\t\t\t\t}\n\n\t\t\t\tif (['enable', 'disable', 'toggle'].includes(parts[0])) {\n\t\t\t\t\tconst q = parts.slice(1).join(' ').toLowerCase();\n\t\t\t\t\treturn resolve_builtin_extension_states(force_disabled)\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t(state) =>\n\t\t\t\t\t\t\t\tstate.key.toLowerCase().includes(q) ||\n\t\t\t\t\t\t\t\tstate.label.toLowerCase().includes(q),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.slice(0, 20)\n\t\t\t\t\t\t.map((state) => ({\n\t\t\t\t\t\t\tvalue: `${parts[0]} ${state.key}`,\n\t\t\t\t\t\t\tlabel: `${state.key} ${state.saved_enabled ? ENABLED : DISABLED}`,\n\t\t\t\t\t\t}));\n\t\t\t\t}\n\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\thandler: async (args, ctx) => {\n\t\t\t\tconst trimmed = args.trim();\n\n\t\t\t\tif (!trimmed && ctx.hasUI) {\n\t\t\t\t\tconst states =\n\t\t\t\t\t\tresolve_builtin_extension_states(force_disabled);\n\t\t\t\t\tconst initial_enabled = new Set(\n\t\t\t\t\t\tstates\n\t\t\t\t\t\t\t.filter((state) => state.saved_enabled)\n\t\t\t\t\t\t\t.map((state) => state.key),\n\t\t\t\t\t);\n\t\t\t\t\tconst current_enabled = new Set(initial_enabled);\n\n\t\t\t\t\tawait ctx.ui.custom((tui, theme, _kb, done) => {\n\t\t\t\t\t\tconst items = states.map(to_setting_item);\n\t\t\t\t\t\tconst container = new Container();\n\n\t\t\t\t\t\tcontainer.addChild({\n\t\t\t\t\t\t\trender: () => {\n\t\t\t\t\t\t\t\tconst saved_enabled = current_enabled.size;\n\t\t\t\t\t\t\t\tconst saved_disabled = states.length - saved_enabled;\n\t\t\t\t\t\t\t\tconst enabled_now = [...current_enabled].filter(\n\t\t\t\t\t\t\t\t\t(key) =>\n\t\t\t\t\t\t\t\t\t\t!force_disabled.has(key as BuiltinExtensionKey),\n\t\t\t\t\t\t\t\t).length;\n\t\t\t\t\t\t\t\tconst disabled_now = states.length - enabled_now;\n\t\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\t\t\t\t'accent',\n\t\t\t\t\t\t\t\t\t\ttheme.bold('Built-in extensions'),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\t\t\t\t'muted',\n\t\t\t\t\t\t\t\t\t\t`${saved_enabled} saved enabled • ${saved_disabled} saved disabled • ${enabled_now} enabled now • ${disabled_now} disabled now`,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t'',\n\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tinvalidate: () => {},\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst settings_list = new SettingsList(\n\t\t\t\t\t\t\titems,\n\t\t\t\t\t\t\tMath.min(Math.max(items.length + 4, 8), 16),\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcursor: theme.fg('accent', '›'),\n\t\t\t\t\t\t\t\tlabel: (text, selected) =>\n\t\t\t\t\t\t\t\t\tselected ? theme.fg('accent', text) : text,\n\t\t\t\t\t\t\t\tvalue: (text, selected) => {\n\t\t\t\t\t\t\t\t\tconst color = text === ENABLED ? 'success' : 'dim';\n\t\t\t\t\t\t\t\t\tconst rendered = theme.fg(color, text);\n\t\t\t\t\t\t\t\t\treturn selected\n\t\t\t\t\t\t\t\t\t\t? theme.bold(theme.fg('accent', rendered))\n\t\t\t\t\t\t\t\t\t\t: rendered;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tdescription: (text) => theme.fg('muted', text),\n\t\t\t\t\t\t\t\thint: (text) => theme.fg('dim', text),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t(id, new_value) => {\n\t\t\t\t\t\t\t\tconst key = id as BuiltinExtensionKey;\n\t\t\t\t\t\t\t\tconst enabled = new_value === ENABLED;\n\t\t\t\t\t\t\t\tif (enabled) {\n\t\t\t\t\t\t\t\t\tcurrent_enabled.add(key);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurrent_enabled.delete(key);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tsave_extension_enabled(key, enabled);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t() => done(undefined),\n\t\t\t\t\t\t\t{ enableSearch: true },\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tcontainer.addChild(settings_list);\n\t\t\t\t\t\tcontainer.addChild(\n\t\t\t\t\t\t\tnew Text(\n\t\t\t\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\t\t\t'dim',\n\t\t\t\t\t\t\t\t\t'esc close • search filters • changes save immediately • CLI --no-* flags still win in this process',\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\trender(width: number) {\n\t\t\t\t\t\t\t\treturn container.render(width);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tinvalidate() {\n\t\t\t\t\t\t\t\tcontainer.invalidate();\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\thandleInput(data: string) {\n\t\t\t\t\t\t\t\tsettings_list.handleInput(data);\n\t\t\t\t\t\t\t\ttui.requestRender();\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!sets_equal(initial_enabled, current_enabled)) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\tforce_disabled.size > 0\n\t\t\t\t\t\t\t\t? 'Reloading to apply updated built-in extensions. CLI --no-* flags still force-disable some extensions in this process.'\n\t\t\t\t\t\t\t\t: 'Reloading to apply updated built-in extensions...',\n\t\t\t\t\t\t\t'info',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait ctx.reload();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst [sub, ...rest] = (trimmed || 'list').split(/\\s+/);\n\t\t\t\tconst arg = rest.join(' ');\n\t\t\t\tconst states =\n\t\t\t\t\tresolve_builtin_extension_states(force_disabled);\n\n\t\t\t\tswitch (sub) {\n\t\t\t\t\tcase 'list': {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\tformat_extension_lines(states, {\n\t\t\t\t\t\t\t\theading: 'Built-in extensions',\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'enable':\n\t\t\t\t\tcase 'disable':\n\t\t\t\t\tcase 'toggle': {\n\t\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t\t`Usage: /extensions ${sub} <key>`,\n\t\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst extension = find_builtin_extension(arg);\n\t\t\t\t\t\tif (!extension) {\n\t\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t\t`Unknown extension: ${arg}. Use: ${BUILTIN_EXTENSIONS.map((item) => item.key).join(', ')}`,\n\t\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst current_state = states.find(\n\t\t\t\t\t\t\t(state) => state.key === extension.key,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst next_enabled =\n\t\t\t\t\t\t\tsub === 'enable'\n\t\t\t\t\t\t\t\t? true\n\t\t\t\t\t\t\t\t: sub === 'disable'\n\t\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t\t: !current_state?.saved_enabled;\n\t\t\t\t\t\tsave_extension_enabled(extension.key, next_enabled);\n\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\tnext_enabled && force_disabled.has(extension.key)\n\t\t\t\t\t\t\t\t? `Enabled ${extension.key} in saved config. Still disabled in this process by ${extension.cli_flag}. /reload or restart without that flag to apply.`\n\t\t\t\t\t\t\t\t: `${extension.key} ${next_enabled ? 'enabled' : 'disabled'}. /reload to apply.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'search': {\n\t\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t\t'Usage: /extensions search <query>',\n\t\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst results = search_states(states, arg);\n\t\t\t\t\t\tif (results.length === 0) {\n\t\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t\t`No built-in extensions matching \"${arg}\"`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\tformat_extension_lines(results, {\n\t\t\t\t\t\t\t\theading: `Built-in extensions matching \"${arg}\"`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t`Unknown: ${sub}. Use: ${subs.join(', ')}`,\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t};\n}\n\nexport default create_extensions_extension();\n","// Filter-output extension — redact secrets from tool output\n// Patterns from https://github.com/spences10/nopeek\n\nimport type { ExtensionAPI } from '@mariozechner/pi-coding-agent';\n\ninterface SecretPattern {\n\tname: string;\n\tpattern: RegExp;\n}\n\nconst SECRET_PATTERNS: SecretPattern[] = [\n\t{ name: 'AWS Access Key', pattern: /AKIA[A-Z0-9]{16}/g },\n\t{ name: 'AWS Temp Access Key', pattern: /ASIA[A-Z0-9]{16}/g },\n\t{\n\t\tname: 'AWS Secret Key',\n\t\tpattern:\n\t\t\t/\\b(?:AWS_SECRET_ACCESS_KEY|aws_secret_access_key|secret_access_key|SecretAccessKey)\\b\\s*[:=]\\s*[\"']?[A-Za-z0-9/+=]{40,}[\"']?/g,\n\t},\n\t{\n\t\tname: 'Bearer Token',\n\t\tpattern: /Bearer\\s+[a-zA-Z0-9._-]{20,}/g,\n\t},\n\t{\n\t\tname: 'OpenAI/Anthropic API Key',\n\t\tpattern: /sk-[a-zA-Z0-9._-]{20,}/g,\n\t},\n\t{\n\t\tname: 'Stripe Live Key',\n\t\tpattern: /sk_live_[a-zA-Z0-9]{20,}/g,\n\t},\n\t{\n\t\tname: 'Stripe Test Key',\n\t\tpattern: /sk_test_[a-zA-Z0-9]{20,}/g,\n\t},\n\t{\n\t\tname: 'Hetzner Token',\n\t\tpattern:\n\t\t\t/(?:HCLOUD_TOKEN|hcloud_token|token)\\s*[:=]\\s*[\"']?[a-f0-9]{64}\\b/g,\n\t},\n\t{\n\t\tname: 'Private Key',\n\t\tpattern:\n\t\t\t/-----BEGIN\\s+[\\w\\s]*PRIVATE\\s+KEY-----[\\s\\S]*?-----END\\s+[\\w\\s]*PRIVATE\\s+KEY-----/g,\n\t},\n\t{\n\t\tname: 'Connection String with Password',\n\t\tpattern: /:\\/\\/[^:]+:[^@]+@/g,\n\t},\n\t{\n\t\tname: 'Generic Password Field',\n\t\tpattern:\n\t\t\t/\\b[\\w-]*(?:password|passwd|secret|token|api[_-]?key)\\b\\s*[:=]\\s*[\"']?[A-Za-z0-9._:/+=@!-]{8,}/gi,\n\t},\n\t{\n\t\tname: 'Generic Secret Phrase',\n\t\tpattern:\n\t\t\t/\\b(?:password|passwd|secret|token|api[_-]?key)\\b(?:\\s+(?:is|was|seen|value|header))?\\s*[:=]?\\s+[A-Za-z0-9._:/+=@!-]{8,}/gi,\n\t},\n\t{\n\t\tname: 'Tavily API Key',\n\t\tpattern: /tvly-[a-zA-Z0-9_-]{20,}/g,\n\t},\n\t{\n\t\tname: 'Kagi API Key',\n\t\tpattern: /[a-zA-Z0-9_-]{40,}\\.[a-zA-Z0-9_-]{40,}/g,\n\t},\n\t{\n\t\tname: 'Brave API Key',\n\t\tpattern: /BSA[A-Z0-9]{20,}/g,\n\t},\n\t{\n\t\tname: 'Firecrawl API Key',\n\t\tpattern: /fc-[a-f0-9]{32}/g,\n\t},\n\t{\n\t\tname: 'GitHub Token',\n\t\tpattern: /gh[pousr]_[a-zA-Z0-9]{36,}/g,\n\t},\n\t{\n\t\tname: 'GitHub Fine-grained PAT',\n\t\tpattern: /github_pat_[a-zA-Z0-9_]{20,}/g,\n\t},\n];\n\nfunction redact(text: string): { redacted: string; count: number } {\n\tlet count = 0;\n\tlet result = text;\n\n\tfor (const sp of SECRET_PATTERNS) {\n\t\tsp.pattern.lastIndex = 0;\n\t\tresult = result.replace(sp.pattern, (match) => {\n\t\t\tcount++;\n\t\t\tconst prefix = match.slice(0, 4);\n\t\t\treturn `${prefix}${'*'.repeat(Math.min(match.length - 4, 20))}[REDACTED:${sp.name}]`;\n\t\t});\n\t}\n\n\treturn { redacted: result, count };\n}\n\nexport default async function filter_output(pi: ExtensionAPI) {\n\tlet totalRedacted = 0;\n\n\tpi.on('tool_result' as const, async (event: any) => {\n\t\tif (!event.content) return;\n\n\t\tlet modified = false;\n\t\tconst newContent = event.content.map(\n\t\t\t(item: { type: string; text?: string }) => {\n\t\t\t\tif (item.type !== 'text' || !item.text) return item;\n\t\t\t\tconst { redacted, count } = redact(item.text);\n\t\t\t\tif (count > 0) {\n\t\t\t\t\tmodified = true;\n\t\t\t\t\ttotalRedacted += count;\n\t\t\t\t}\n\t\t\t\treturn { ...item, text: redacted };\n\t\t\t},\n\t\t);\n\n\t\tif (modified) {\n\t\t\treturn { content: newContent };\n\t\t}\n\t});\n\n\tpi.registerCommand('redact-stats', {\n\t\tdescription: 'Show how many secrets have been redacted',\n\t\thandler: async (_args, ctx) => {\n\t\t\tctx.ui.notify(\n\t\t\t\t`Secrets redacted this session: ${totalRedacted}`,\n\t\t\t);\n\t\t},\n\t});\n}\n","// Handoff extension — generate a focused prompt for a new session\n\nimport { complete, type Message } from '@mariozechner/pi-ai';\nimport type {\n\tExtensionAPI,\n\tSessionEntry,\n} from '@mariozechner/pi-coding-agent';\nimport {\n\tBorderedLoader,\n\tconvertToLlm,\n\tserializeConversation,\n} from '@mariozechner/pi-coding-agent';\n\nconst SYSTEM_PROMPT = `You are a context transfer assistant. Given a conversation history and the user's goal for a new thread, generate a focused prompt that:\n\n1. Summarizes relevant context from the conversation (decisions made, approaches taken, key findings)\n2. Lists any relevant files that were discussed or modified\n3. Clearly states the next task based on the user's goal\n4. Is self-contained - the new thread should be able to proceed without the old conversation\n\nFormat your response as a prompt the user can send to start the new thread. Be concise but include all necessary context. Do not include any preamble like \"Here's the prompt\" - just output the prompt itself.\n\nExample output format:\n## Context\nWe've been working on X. Key decisions:\n- Decision 1\n- Decision 2\n\nFiles involved:\n- path/to/file1.ts\n- path/to/file2.ts\n\n## Task\n[Clear description of what to do next based on user's goal]`;\n\nexport default async function handoff(pi: ExtensionAPI) {\n\tpi.registerCommand('handoff', {\n\t\tdescription:\n\t\t\t'Transfer context to a new focused session with an AI-generated prompt',\n\t\thandler: async (args, ctx) => {\n\t\t\tif (!ctx.hasUI) {\n\t\t\t\tctx.ui.notify('handoff requires interactive mode', 'error');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!ctx.model) {\n\t\t\t\tctx.ui.notify('No model selected', 'error');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst goal = args.trim();\n\t\t\tif (!goal) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t'Usage: /handoff <goal for new thread>',\n\t\t\t\t\t'error',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst branch = ctx.sessionManager.getBranch();\n\t\t\tconst messages = branch\n\t\t\t\t.filter(\n\t\t\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\t\t\tentry.type === 'message',\n\t\t\t\t)\n\t\t\t\t.map((entry) => entry.message);\n\n\t\t\tif (messages.length === 0) {\n\t\t\t\tctx.ui.notify('No conversation to hand off', 'error');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst llm_messages = convertToLlm(messages);\n\t\t\tconst conversation_text = serializeConversation(llm_messages);\n\t\t\tconst current_session_file =\n\t\t\t\tctx.sessionManager.getSessionFile();\n\t\t\tconst model = ctx.model;\n\n\t\t\tconst result = await ctx.ui.custom<string | null>(\n\t\t\t\t(tui, theme, _kb, done) => {\n\t\t\t\t\tconst loader = new BorderedLoader(\n\t\t\t\t\t\ttui,\n\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t'Generating handoff prompt...',\n\t\t\t\t\t);\n\t\t\t\t\tloader.onAbort = () => done(null);\n\n\t\t\t\t\tconst generate = async () => {\n\t\t\t\t\t\tconst auth =\n\t\t\t\t\t\t\tawait ctx.modelRegistry.getApiKeyAndHeaders(model);\n\t\t\t\t\t\tif (!auth.ok || !auth.apiKey) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\tauth.ok\n\t\t\t\t\t\t\t\t\t? `No API key for ${model.provider}`\n\t\t\t\t\t\t\t\t\t: auth.error,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst user_message: Message = {\n\t\t\t\t\t\t\trole: 'user',\n\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\t\t\ttext: `## Conversation History\\n\\n${conversation_text}\\n\\n## User's Goal for New Thread\\n\\n${goal}`,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tconst response = await complete(\n\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsystemPrompt: SYSTEM_PROMPT,\n\t\t\t\t\t\t\t\tmessages: [user_message],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tapiKey: auth.apiKey,\n\t\t\t\t\t\t\t\theaders: auth.headers,\n\t\t\t\t\t\t\t\tsignal: loader.signal,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (response.stopReason === 'aborted') {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn response.content\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(c): c is { type: 'text'; text: string } =>\n\t\t\t\t\t\t\t\t\tc.type === 'text',\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.map((c) => c.text)\n\t\t\t\t\t\t\t.join('\\n');\n\t\t\t\t\t};\n\n\t\t\t\t\tgenerate()\n\t\t\t\t\t\t.then(done)\n\t\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\t\tconsole.error('Handoff generation failed:', err);\n\t\t\t\t\t\t\tdone(null);\n\t\t\t\t\t\t});\n\n\t\t\t\t\treturn loader;\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (result === null) {\n\t\t\t\tctx.ui.notify('Cancelled', 'info');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst edited_prompt = await ctx.ui.editor(\n\t\t\t\t'Edit handoff prompt',\n\t\t\t\tresult,\n\t\t\t);\n\t\t\tif (edited_prompt === undefined) {\n\t\t\t\tctx.ui.notify('Cancelled', 'info');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst new_session_result = await ctx.newSession({\n\t\t\t\tparentSession: current_session_file,\n\t\t\t});\n\t\t\tif (new_session_result.cancelled) {\n\t\t\t\tctx.ui.notify('New session cancelled', 'info');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tctx.ui.setEditorText(edited_prompt);\n\t\t\tctx.ui.notify('Handoff ready. Submit when ready.', 'info');\n\t\t},\n\t});\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { EventEmitter } from 'node:events';\nimport { pathToFileURL } from 'node:url';\n\nexport interface LspPosition {\n\tline: number;\n\tcharacter: number;\n}\n\nexport interface LspRange {\n\tstart: LspPosition;\n\tend: LspPosition;\n}\n\nexport interface LspLocation {\n\turi: string;\n\trange: LspRange;\n}\n\nexport interface LspLocationLink {\n\ttargetUri: string;\n\ttargetRange: LspRange;\n\ttargetSelectionRange?: LspRange;\n\toriginSelectionRange?: LspRange;\n}\n\nexport interface LspDocumentSymbol {\n\tname: string;\n\tkind: number;\n\tdetail?: string;\n\trange: LspRange;\n\tselectionRange: LspRange;\n\tchildren?: LspDocumentSymbol[];\n\turi?: string;\n\tcontainerName?: string;\n}\n\nexport interface LspDiagnostic {\n\trange: LspRange;\n\tseverity?: 1 | 2 | 3 | 4;\n\tcode?: string | number;\n\tsource?: string;\n\tmessage: string;\n}\n\nexport interface LspHover {\n\tcontents:\n\t\t| string\n\t\t| { language?: string; value: string }\n\t\t| { kind: string; value: string }\n\t\t| Array<\n\t\t\t\t| string\n\t\t\t\t| { language?: string; value: string }\n\t\t\t\t| { kind: string; value: string }\n\t\t >;\n\trange?: LspRange;\n}\n\ninterface JsonRpcMessage {\n\tjsonrpc: '2.0';\n\tid?: number | string;\n\tmethod?: string;\n\tparams?: unknown;\n\tresult?: unknown;\n\terror?: { code: number; message: string; data?: unknown };\n}\n\nexport interface LspClientOptions {\n\tcommand: string;\n\targs: string[];\n\troot_uri: string;\n\tlanguage_id_for_uri: (uri: string) => string | undefined;\n\trequest_timeout_ms?: number;\n}\n\nexport class LspClientStartError extends Error {\n\tcommand: string;\n\targs: string[];\n\tcode?: string;\n\n\tconstructor(\n\t\tmessage: string,\n\t\toptions: {\n\t\t\tcommand: string;\n\t\t\targs: string[];\n\t\t\tcause?: unknown;\n\t\t\tcode?: string;\n\t\t},\n\t) {\n\t\tsuper(\n\t\t\tmessage,\n\t\t\toptions.cause ? { cause: options.cause } : undefined,\n\t\t);\n\t\tthis.name = 'LspClientStartError';\n\t\tthis.command = options.command;\n\t\tthis.args = options.args;\n\t\tthis.code = options.code;\n\t}\n}\n\nexport class LspClient extends EventEmitter {\n\t#proc: ChildProcess | null = null;\n\t#options: LspClientOptions;\n\t#next_id = 1;\n\t#pending = new Map<\n\t\tnumber,\n\t\t{\n\t\t\tresolve: (v: unknown) => void;\n\t\t\treject: (e: Error) => void;\n\t\t\ttimer: NodeJS.Timeout;\n\t\t}\n\t>();\n\t#buffer = Buffer.alloc(0);\n\t#initialized = false;\n\t#open_docs = new Map<string, { version: number; text: string }>();\n\t#diagnostics_by_uri = new Map<string, LspDiagnostic[]>();\n\t#diagnostic_waiters = new Set<() => void>();\n\n\tconstructor(options: LspClientOptions) {\n\t\tsuper();\n\t\tthis.#options = options;\n\t}\n\n\tasync start(): Promise<void> {\n\t\tthis.#proc = spawn(this.#options.command, this.#options.args, {\n\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\tenv: process.env,\n\t\t});\n\n\t\tlet start_reject: ((error: Error) => void) | null = null;\n\t\tconst start_failure = new Promise<never>((_, reject) => {\n\t\t\tstart_reject = reject;\n\t\t});\n\t\tconst reject_start = (error: Error): boolean => {\n\t\t\tif (!start_reject) return false;\n\t\t\tconst reject = start_reject;\n\t\t\tstart_reject = null;\n\t\t\treject(error);\n\t\t\treturn true;\n\t\t};\n\t\tconst start_error = (\n\t\t\tmessage: string,\n\t\t\tcause?: unknown,\n\t\t\tcode?: string,\n\t\t): LspClientStartError =>\n\t\t\tnew LspClientStartError(message, {\n\t\t\t\tcommand: this.#options.command,\n\t\t\t\targs: this.#options.args,\n\t\t\t\tcause,\n\t\t\t\tcode,\n\t\t\t});\n\n\t\tthis.#proc.on('error', (err) => {\n\t\t\tconst wrapped = start_error(\n\t\t\t\t`Failed to spawn ${this.#options.command}`,\n\t\t\t\terr,\n\t\t\t\terror_code(err),\n\t\t\t);\n\t\t\tif (!reject_start(wrapped)) {\n\t\t\t\tthis.#emit_error(wrapped);\n\t\t\t}\n\t\t});\n\t\tthis.#proc.on('close', () => {\n\t\t\tif (!this.#initialized) {\n\t\t\t\treject_start(\n\t\t\t\t\tstart_error(\n\t\t\t\t\t\t`LSP server ${this.#options.command} closed before initialization`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const pending of this.#pending.values()) {\n\t\t\t\tclearTimeout(pending.timer);\n\t\t\t\tpending.reject(new Error('LSP server closed'));\n\t\t\t}\n\t\t\tthis.#pending.clear();\n\t\t\tthis.#initialized = false;\n\t\t\tthis.#proc = null;\n\t\t});\n\t\tthis.#proc.stderr?.on('data', () => {\n\t\t\t// Discard stderr; many servers are chatty.\n\t\t});\n\t\tthis.#proc.stdout!.on('data', (chunk: Buffer) => {\n\t\t\tthis.#buffer = Buffer.concat([this.#buffer, chunk]);\n\t\t\tthis.#drain_buffer();\n\t\t});\n\n\t\ttry {\n\t\t\tawait Promise.race([\n\t\t\t\tthis.#request('initialize', {\n\t\t\t\t\tprocessId: process.pid,\n\t\t\t\t\trootUri: this.#options.root_uri,\n\t\t\t\t\tcapabilities: {\n\t\t\t\t\t\ttextDocument: {\n\t\t\t\t\t\t\tpublishDiagnostics: {\n\t\t\t\t\t\t\t\trelatedInformation: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\thover: {\n\t\t\t\t\t\t\t\tcontentFormat: ['markdown', 'plaintext'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdefinition: { linkSupport: false },\n\t\t\t\t\t\t\treferences: {},\n\t\t\t\t\t\t\tdocumentSymbol: {\n\t\t\t\t\t\t\t\thierarchicalDocumentSymbolSupport: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tworkspace: {\n\t\t\t\t\t\t\tworkspaceFolders: true,\n\t\t\t\t\t\t\tsymbol: {},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tworkspaceFolders: [\n\t\t\t\t\t\t{ uri: this.#options.root_uri, name: 'workspace' },\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t\tstart_failure,\n\t\t\t]);\n\t\t\tthis.#notify('initialized', {});\n\t\t\tthis.#initialized = true;\n\t\t\tstart_reject = null;\n\t\t} catch (error) {\n\t\t\tawait this.stop();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tis_ready(): boolean {\n\t\treturn this.#initialized;\n\t}\n\n\tasync ensure_document_open(\n\t\turi: string,\n\t\ttext: string,\n\t): Promise<void> {\n\t\tconst existing = this.#open_docs.get(uri);\n\t\tif (existing) {\n\t\t\tif (existing.text === text) return;\n\t\t\tconst next_version = existing.version + 1;\n\t\t\tthis.#open_docs.set(uri, { version: next_version, text });\n\t\t\tthis.#notify('textDocument/didChange', {\n\t\t\t\ttextDocument: { uri, version: next_version },\n\t\t\t\tcontentChanges: [{ text }],\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst language_id =\n\t\t\tthis.#options.language_id_for_uri(uri) ?? 'plaintext';\n\t\tthis.#open_docs.set(uri, { version: 1, text });\n\t\tthis.#notify('textDocument/didOpen', {\n\t\t\ttextDocument: {\n\t\t\t\turi,\n\t\t\t\tlanguageId: language_id,\n\t\t\t\tversion: 1,\n\t\t\t\ttext,\n\t\t\t},\n\t\t});\n\t}\n\n\tasync hover(\n\t\turi: string,\n\t\tposition: LspPosition,\n\t): Promise<LspHover | null> {\n\t\tconst result = (await this.#request('textDocument/hover', {\n\t\t\ttextDocument: { uri },\n\t\t\tposition,\n\t\t})) as LspHover | null;\n\t\treturn result ?? null;\n\t}\n\n\tasync definition(\n\t\turi: string,\n\t\tposition: LspPosition,\n\t): Promise<LspLocation[]> {\n\t\tconst result = (await this.#request('textDocument/definition', {\n\t\t\ttextDocument: { uri },\n\t\t\tposition,\n\t\t})) as\n\t\t\t| LspLocation\n\t\t\t| LspLocation[]\n\t\t\t| LspLocationLink\n\t\t\t| LspLocationLink[]\n\t\t\t| null;\n\t\treturn normalize_location_result(result);\n\t}\n\n\tasync references(\n\t\turi: string,\n\t\tposition: LspPosition,\n\t\tinclude_declaration: boolean,\n\t): Promise<LspLocation[]> {\n\t\tconst result = (await this.#request('textDocument/references', {\n\t\t\ttextDocument: { uri },\n\t\t\tposition,\n\t\t\tcontext: { includeDeclaration: include_declaration },\n\t\t})) as LspLocation[] | null;\n\t\treturn result ?? [];\n\t}\n\n\tasync document_symbols(uri: string): Promise<LspDocumentSymbol[]> {\n\t\tconst result = (await this.#request(\n\t\t\t'textDocument/documentSymbol',\n\t\t\t{\n\t\t\t\ttextDocument: { uri },\n\t\t\t},\n\t\t)) as\n\t\t\t| LspDocumentSymbol[]\n\t\t\t| Array<{\n\t\t\t\t\tname: string;\n\t\t\t\t\tkind: number;\n\t\t\t\t\tlocation: LspLocation;\n\t\t\t\t\tcontainerName?: string;\n\t\t\t }>\n\t\t\t| null;\n\t\treturn normalize_document_symbol_result(result);\n\t}\n\n\tget_diagnostics(uri: string): LspDiagnostic[] {\n\t\treturn this.#diagnostics_by_uri.get(uri) ?? [];\n\t}\n\n\tasync wait_for_diagnostics(\n\t\turi: string,\n\t\ttimeout_ms = 1500,\n\t): Promise<LspDiagnostic[]> {\n\t\tif (this.#diagnostics_by_uri.has(uri)) {\n\t\t\treturn this.get_diagnostics(uri);\n\t\t}\n\t\treturn new Promise((resolve) => {\n\t\t\tlet active = true;\n\t\t\tconst cleanup = () => {\n\t\t\t\tif (!active) return;\n\t\t\t\tactive = false;\n\t\t\t\tthis.off('diagnostics', handler);\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tthis.#diagnostic_waiters.delete(cleanup);\n\t\t\t\tresolve(this.get_diagnostics(uri));\n\t\t\t};\n\t\t\tconst handler = (event_uri: string) => {\n\t\t\t\tif (event_uri !== uri) return;\n\t\t\t\tcleanup();\n\t\t\t};\n\t\t\tconst timer = setTimeout(cleanup, timeout_ms);\n\t\t\tthis.on('diagnostics', handler);\n\t\t\tthis.#diagnostic_waiters.add(cleanup);\n\t\t});\n\t}\n\n\tasync stop(): Promise<void> {\n\t\tif (this.#initialized) {\n\t\t\ttry {\n\t\t\t\tawait this.#request('shutdown', null, 1000);\n\t\t\t\tthis.#notify('exit', null);\n\t\t\t} catch {\n\t\t\t\t// Server may already be dead; proceed.\n\t\t\t}\n\t\t}\n\t\tfor (const pending of this.#pending.values()) {\n\t\t\tclearTimeout(pending.timer);\n\t\t\tpending.reject(new Error('LSP client stopped'));\n\t\t}\n\t\tthis.#pending.clear();\n\t\tfor (const cleanup of Array.from(this.#diagnostic_waiters)) {\n\t\t\tcleanup();\n\t\t}\n\t\tif (this.#proc) {\n\t\t\tthis.#proc.kill();\n\t\t\tthis.#proc = null;\n\t\t}\n\t\tthis.#initialized = false;\n\t}\n\n\t#request(\n\t\tmethod: string,\n\t\tparams: unknown,\n\t\ttimeout_override?: number,\n\t): Promise<unknown> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst id = this.#next_id++;\n\t\t\tconst timeout_ms =\n\t\t\t\ttimeout_override ??\n\t\t\t\tthis.#options.request_timeout_ms ??\n\t\t\t\t30_000;\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tif (this.#pending.has(id)) {\n\t\t\t\t\tthis.#pending.delete(id);\n\t\t\t\t\treject(new Error(`LSP request ${method} timed out`));\n\t\t\t\t}\n\t\t\t}, timeout_ms);\n\t\t\tthis.#pending.set(id, { resolve, reject, timer });\n\t\t\ttry {\n\t\t\t\tthis.#send({ jsonrpc: '2.0', id, method, params });\n\t\t\t} catch (error) {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tthis.#pending.delete(id);\n\t\t\t\treject(error as Error);\n\t\t\t}\n\t\t});\n\t}\n\n\t#notify(method: string, params: unknown): void {\n\t\tthis.#send({ jsonrpc: '2.0', method, params });\n\t}\n\n\t#send(message: JsonRpcMessage): void {\n\t\tif (!this.#proc?.stdin?.writable) {\n\t\t\tthrow new Error('LSP server not connected');\n\t\t}\n\t\tconst body = Buffer.from(JSON.stringify(message), 'utf8');\n\t\tconst header = Buffer.from(\n\t\t\t`Content-Length: ${body.length}\\r\\n\\r\\n`,\n\t\t\t'ascii',\n\t\t);\n\t\tthis.#proc.stdin.write(Buffer.concat([header, body]));\n\t}\n\n\t#emit_error(error: unknown): void {\n\t\tif (this.listenerCount('error') > 0) {\n\t\t\tthis.emit('error', error);\n\t\t}\n\t}\n\n\t#drain_buffer(): void {\n\t\twhile (true) {\n\t\t\tconst header_end = this.#buffer.indexOf('\\r\\n\\r\\n');\n\t\t\tif (header_end === -1) return;\n\n\t\t\tconst header = this.#buffer\n\t\t\t\t.subarray(0, header_end)\n\t\t\t\t.toString('ascii');\n\t\t\tconst match = header.match(/Content-Length:\\s*(\\d+)/i);\n\t\t\tif (!match) {\n\t\t\t\tthis.#buffer = this.#buffer.subarray(header_end + 4);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst length = Number(match[1]);\n\t\t\tconst body_start = header_end + 4;\n\t\t\tif (this.#buffer.length < body_start + length) return;\n\n\t\t\tconst body = this.#buffer.subarray(\n\t\t\t\tbody_start,\n\t\t\t\tbody_start + length,\n\t\t\t);\n\t\t\tthis.#buffer = this.#buffer.subarray(body_start + length);\n\n\t\t\ttry {\n\t\t\t\tthis.#handle_message(\n\t\t\t\t\tJSON.parse(body.toString('utf8')) as JsonRpcMessage,\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tthis.#emit_error(error);\n\t\t\t}\n\t\t}\n\t}\n\n\t#handle_message(message: JsonRpcMessage): void {\n\t\tconst numeric_id =\n\t\t\ttypeof message.id === 'number'\n\t\t\t\t? message.id\n\t\t\t\t: typeof message.id === 'string' && /^-?\\d+$/.test(message.id)\n\t\t\t\t\t? Number(message.id)\n\t\t\t\t\t: null;\n\t\tif (numeric_id != null && this.#pending.has(numeric_id)) {\n\t\t\tconst pending = this.#pending.get(numeric_id)!;\n\t\t\tthis.#pending.delete(numeric_id);\n\t\t\tclearTimeout(pending.timer);\n\t\t\tif (message.error) {\n\t\t\t\tpending.reject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`LSP error ${message.error.code}: ${message.error.message}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpending.resolve(message.result);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tmessage.method === 'textDocument/publishDiagnostics' &&\n\t\t\tmessage.params\n\t\t) {\n\t\t\tconst params = message.params as {\n\t\t\t\turi: string;\n\t\t\t\tdiagnostics: LspDiagnostic[];\n\t\t\t};\n\t\t\tthis.#diagnostics_by_uri.set(params.uri, params.diagnostics);\n\t\t\tthis.emit('diagnostics', params.uri);\n\t\t\treturn;\n\t\t}\n\n\t\tif (message.method && message.id != null) {\n\t\t\t// Respond to server-to-client requests we don't implement so it doesn't block.\n\t\t\tthis.#send({\n\t\t\t\tjsonrpc: '2.0',\n\t\t\t\tid: message.id,\n\t\t\t\tresult: null,\n\t\t\t});\n\t\t}\n\t}\n}\n\nexport function normalize_location_result(\n\tresult:\n\t\t| LspLocation\n\t\t| LspLocation[]\n\t\t| LspLocationLink\n\t\t| LspLocationLink[]\n\t\t| null,\n): LspLocation[] {\n\tif (!result) return [];\n\tconst entries = Array.isArray(result) ? result : [result];\n\treturn entries.map((entry) => {\n\t\tif ('uri' in entry) return entry;\n\t\treturn {\n\t\t\turi: entry.targetUri,\n\t\t\trange: entry.targetSelectionRange ?? entry.targetRange,\n\t\t};\n\t});\n}\n\nexport function normalize_document_symbol_result(\n\tresult:\n\t\t| LspDocumentSymbol[]\n\t\t| Array<{\n\t\t\t\tname: string;\n\t\t\t\tkind: number;\n\t\t\t\tlocation: LspLocation;\n\t\t\t\tcontainerName?: string;\n\t\t }>\n\t\t| null,\n): LspDocumentSymbol[] {\n\tif (!result) return [];\n\tif (\n\t\tresult.length === 0 ||\n\t\t('range' in result[0] && 'selectionRange' in result[0])\n\t) {\n\t\treturn result as LspDocumentSymbol[];\n\t}\n\tconst symbol_info = result as Array<{\n\t\tname: string;\n\t\tkind: number;\n\t\tlocation: LspLocation;\n\t\tcontainerName?: string;\n\t}>;\n\treturn symbol_info.map((entry) => ({\n\t\tname: entry.name,\n\t\tkind: entry.kind,\n\t\trange: entry.location.range,\n\t\tselectionRange: entry.location.range,\n\t\tcontainerName: entry.containerName,\n\t\turi: entry.location.uri,\n\t}));\n}\n\nexport function file_path_to_uri(file_path: string): string {\n\treturn pathToFileURL(file_path).href;\n}\n\nfunction error_code(error: unknown): string | undefined {\n\treturn typeof error === 'object' &&\n\t\terror !== null &&\n\t\t'code' in error &&\n\t\ttypeof (error as { code?: unknown }).code === 'string'\n\t\t? (error as { code: string }).code\n\t\t: undefined;\n}\n","import { existsSync } from 'node:fs';\nimport {\n\tdirname,\n\textname,\n\tisAbsolute,\n\tjoin,\n\tresolve,\n} from 'node:path';\n\nexport interface LspServerConfig {\n\tlanguage: string;\n\tcommand: string;\n\targs: string[];\n\tinstall_hint?: string;\n}\n\nconst EXTENSION_LANGUAGES: Record<string, string> = {\n\t'.ts': 'typescript',\n\t'.tsx': 'typescript',\n\t'.mts': 'typescript',\n\t'.cts': 'typescript',\n\t'.js': 'typescript',\n\t'.jsx': 'typescript',\n\t'.mjs': 'typescript',\n\t'.cjs': 'typescript',\n\t'.py': 'python',\n\t'.rs': 'rust',\n\t'.go': 'go',\n\t'.rb': 'ruby',\n\t'.java': 'java',\n\t'.lua': 'lua',\n\t'.svelte': 'svelte',\n};\n\nconst LANGUAGE_SERVERS: Record<string, LspServerConfig> = {\n\ttypescript: {\n\t\tlanguage: 'typescript',\n\t\tcommand: 'typescript-language-server',\n\t\targs: ['--stdio'],\n\t\tinstall_hint:\n\t\t\t'Install TypeScript LSP with: pnpm add -D typescript typescript-language-server',\n\t},\n\tpython: {\n\t\tlanguage: 'python',\n\t\tcommand: 'pylsp',\n\t\targs: [],\n\t\tinstall_hint:\n\t\t\t'Install Python LSP with: pip install python-lsp-server',\n\t},\n\trust: {\n\t\tlanguage: 'rust',\n\t\tcommand: 'rust-analyzer',\n\t\targs: [],\n\t\tinstall_hint:\n\t\t\t'Install Rust Analyzer and ensure the rust-analyzer binary is on PATH.',\n\t},\n\tgo: {\n\t\tlanguage: 'go',\n\t\tcommand: 'gopls',\n\t\targs: ['serve'],\n\t\tinstall_hint:\n\t\t\t'Install Go LSP with: go install golang.org/x/tools/gopls@latest',\n\t},\n\truby: {\n\t\tlanguage: 'ruby',\n\t\tcommand: 'solargraph',\n\t\targs: ['stdio'],\n\t\tinstall_hint: 'Install Ruby LSP with: gem install solargraph',\n\t},\n\tjava: {\n\t\tlanguage: 'java',\n\t\tcommand: 'jdtls',\n\t\targs: [],\n\t\tinstall_hint:\n\t\t\t'Install Eclipse JDT Language Server and ensure the jdtls binary is on PATH.',\n\t},\n\tlua: {\n\t\tlanguage: 'lua',\n\t\tcommand: 'lua-language-server',\n\t\targs: [],\n\t\tinstall_hint:\n\t\t\t'Install Lua LSP and ensure the lua-language-server binary is on PATH.',\n\t},\n\tsvelte: {\n\t\tlanguage: 'svelte',\n\t\tcommand: 'svelteserver',\n\t\targs: ['--stdio'],\n\t\tinstall_hint:\n\t\t\t'Install Svelte LSP with: pnpm add -D svelte-language-server (or volta install svelte-language-server)',\n\t},\n};\n\nconst WORKSPACE_MARKERS = [\n\t'svelte.config.js',\n\t'svelte.config.ts',\n\t'tsconfig.json',\n\t'jsconfig.json',\n\t'package.json',\n\t'pyproject.toml',\n\t'Cargo.toml',\n\t'go.mod',\n\t'Gemfile',\n\t'pom.xml',\n\t'build.gradle',\n\t'build.gradle.kts',\n];\n\nconst REPOSITORY_MARKERS = [\n\t'pnpm-workspace.yaml',\n\t'package-lock.json',\n\t'yarn.lock',\n\t'bun.lockb',\n\t'bun.lock',\n\t'.git',\n];\n\nexport function detect_language(\n\tfile_path: string,\n): string | undefined {\n\treturn EXTENSION_LANGUAGES[extname(file_path).toLowerCase()];\n}\n\nexport function list_supported_languages(): string[] {\n\treturn Object.keys(LANGUAGE_SERVERS).sort();\n}\n\nexport function resolve_server_command(\n\tcommand: string,\n\tcwd: string = process.cwd(),\n): string {\n\tif (!command) return command;\n\tif (\n\t\tisAbsolute(command) ||\n\t\tcommand.includes('/') ||\n\t\tcommand.includes('\\\\')\n\t) {\n\t\treturn command;\n\t}\n\n\tfor (const dir of ancestor_directories(cwd)) {\n\t\tconst local_bin = resolve_local_binary(dir, command);\n\t\tif (local_bin) return local_bin;\n\t}\n\n\treturn command;\n}\n\nexport function get_server_config(\n\tlanguage: string,\n\tcwd: string = process.cwd(),\n): LspServerConfig | undefined {\n\tconst base = LANGUAGE_SERVERS[language];\n\tif (!base) return undefined;\n\treturn {\n\t\t...base,\n\t\tcommand: resolve_server_command(base.command, cwd),\n\t};\n}\n\nexport function language_id_for_file(\n\tfile_path: string,\n): string | undefined {\n\treturn detect_language(file_path);\n}\n\nexport function find_workspace_root(\n\tfile_path: string,\n\tfallback: string = process.cwd(),\n): string {\n\tconst start = resolve(dirname(file_path));\n\tconst project_root = find_nearest_marker_directory(\n\t\tstart,\n\t\tWORKSPACE_MARKERS,\n\t);\n\tif (project_root) return project_root;\n\n\tconst repo_root = find_nearest_marker_directory(\n\t\tstart,\n\t\tREPOSITORY_MARKERS,\n\t);\n\tif (repo_root) return repo_root;\n\n\treturn resolve(fallback);\n}\n\nfunction find_nearest_marker_directory(\n\tstart: string,\n\tmarkers: string[],\n): string | undefined {\n\tfor (const dir of ancestor_directories(start)) {\n\t\tif (markers.some((marker) => existsSync(join(dir, marker)))) {\n\t\t\treturn dir;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction ancestor_directories(start: string): string[] {\n\tconst dirs: string[] = [];\n\tlet current = resolve(start);\n\twhile (true) {\n\t\tdirs.push(current);\n\t\tconst parent = dirname(current);\n\t\tif (parent === current) break;\n\t\tcurrent = parent;\n\t}\n\treturn dirs;\n}\n\nfunction resolve_local_binary(\n\tdirectory: string,\n\tcommand: string,\n): string | undefined {\n\tconst candidates = [\n\t\tjoin(directory, 'node_modules', '.bin', command),\n\t\tjoin(directory, 'node_modules', '.bin', `${command}.cmd`),\n\t];\n\treturn candidates.find((candidate) => existsSync(candidate));\n}\n","import {\n\tdefineTool,\n\ttype ExtensionAPI,\n\ttype ExtensionCommandContext,\n} from '@mariozechner/pi-coding-agent';\nimport { Type } from '@sinclair/typebox';\nimport { readFile } from 'node:fs/promises';\nimport { isAbsolute, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport {\n\tfile_path_to_uri,\n\tLspClient,\n\tLspClientStartError,\n\ttype LspClientOptions,\n\ttype LspDiagnostic,\n\ttype LspDocumentSymbol,\n\ttype LspHover,\n\ttype LspLocation,\n\ttype LspPosition,\n} from '../lsp/client.js';\nimport {\n\tdetect_language,\n\tfind_workspace_root,\n\tget_server_config,\n\tlanguage_id_for_file,\n\tlist_supported_languages,\n} from '../lsp/servers.js';\n\ninterface ServerState {\n\tclient: LspClientLike;\n\tlanguage: string;\n\tworkspace_root: string;\n\troot_uri: string;\n\tcommand: string;\n\tinstall_hint?: string;\n}\n\ninterface LspToolErrorDetails {\n\tkind:\n\t\t| 'unsupported_language'\n\t\t| 'server_start_failed'\n\t\t| 'tool_execution_failed';\n\tfile: string;\n\tmessage: string;\n\tlanguage?: string;\n\tcommand?: string;\n\tworkspace_root?: string;\n\tinstall_hint?: string;\n\tcode?: string;\n}\n\nclass LspToolError extends Error {\n\tdetails: LspToolErrorDetails;\n\n\tconstructor(details: LspToolErrorDetails) {\n\t\tsuper(details.message);\n\t\tthis.name = 'LspToolError';\n\t\tthis.details = details;\n\t}\n}\n\nclass LspStartupCancelledError extends Error {\n\tconstructor(language: string, workspace_root: string) {\n\t\tsuper(\n\t\t\t`Startup cancelled for ${language} LSP in ${workspace_root}`,\n\t\t);\n\t\tthis.name = 'LspStartupCancelledError';\n\t}\n}\n\ninterface StartingServerState {\n\tcancelled: boolean;\n\tpromise: Promise<ServerState | undefined>;\n}\n\nconst SYMBOL_KIND_LABELS: Record<number, string> = {\n\t2: 'module',\n\t3: 'namespace',\n\t5: 'class',\n\t6: 'method',\n\t7: 'property',\n\t8: 'field',\n\t9: 'constructor',\n\t11: 'interface',\n\t12: 'function',\n\t13: 'variable',\n\t14: 'constant',\n\t23: 'struct',\n\t24: 'event',\n};\n\nconst SYMBOL_KIND_NAMES = Object.values(SYMBOL_KIND_LABELS);\nconst SYMBOL_KIND_SCHEMA = Type.Union(\n\tSYMBOL_KIND_NAMES.map((name) => Type.Literal(name)),\n);\n\nexport interface LspClientLike {\n\tstart(): Promise<void>;\n\tstop(): Promise<void>;\n\tis_ready(): boolean;\n\tensure_document_open(uri: string, text: string): Promise<void>;\n\thover(uri: string, position: LspPosition): Promise<LspHover | null>;\n\tdefinition(\n\t\turi: string,\n\t\tposition: LspPosition,\n\t): Promise<LspLocation[]>;\n\treferences(\n\t\turi: string,\n\t\tposition: LspPosition,\n\t\tinclude_declaration: boolean,\n\t): Promise<LspLocation[]>;\n\tdocument_symbols(uri: string): Promise<LspDocumentSymbol[]>;\n\twait_for_diagnostics(\n\t\turi: string,\n\t\ttimeout_ms?: number,\n\t): Promise<LspDiagnostic[]>;\n}\n\nexport interface CreateLspExtensionOptions {\n\tcreate_client?: (options: LspClientOptions) => LspClientLike;\n\tread_file?: (path: string) => Promise<string>;\n\tcwd?: () => string;\n}\n\nexport function create_lsp_extension(\n\toptions: CreateLspExtensionOptions = {},\n) {\n\tconst create_client =\n\t\toptions.create_client ??\n\t\t((client_options: LspClientOptions) =>\n\t\t\tnew LspClient(client_options));\n\tconst read_file =\n\t\toptions.read_file ?? ((path: string) => readFile(path, 'utf-8'));\n\n\treturn async function lsp(pi: ExtensionAPI) {\n\t\tconst cwd = options.cwd?.() ?? process.cwd();\n\t\tconst clients_by_server = new Map<string, ServerState>();\n\t\tconst failed_servers = new Map<string, LspToolErrorDetails>();\n\t\tconst starting_servers = new Map<string, StartingServerState>();\n\n\t\tconst resolve_abs = (file: string): string =>\n\t\t\tisAbsolute(file) ? file : resolve(cwd, file);\n\t\tconst server_key = (\n\t\t\tlanguage: string,\n\t\t\tworkspace_root: string,\n\t\t): string => `${language}\\u0000${workspace_root}`;\n\t\tconst make_tool_result = (\n\t\t\ttext: string,\n\t\t\tdetails: unknown = {},\n\t\t) => ({\n\t\t\tcontent: [{ type: 'text' as const, text }],\n\t\t\tdetails,\n\t\t});\n\t\tconst make_tool_error = (details: LspToolErrorDetails) =>\n\t\t\tmake_tool_result(format_tool_error(details), {\n\t\t\t\tok: false,\n\t\t\t\terror: details,\n\t\t\t});\n\n\t\tconst clear_language_state = async (\n\t\t\tlanguage?: string,\n\t\t): Promise<void> => {\n\t\t\tconst states = language\n\t\t\t\t? Array.from(clients_by_server.entries()).filter(\n\t\t\t\t\t\t([, state]) => state.language === language,\n\t\t\t\t\t)\n\t\t\t\t: Array.from(clients_by_server.entries());\n\t\t\tconst starting = language\n\t\t\t\t? Array.from(starting_servers.entries()).filter(([key]) =>\n\t\t\t\t\t\tkey.startsWith(`${language}\\u0000`),\n\t\t\t\t\t)\n\t\t\t\t: Array.from(starting_servers.entries());\n\t\t\tfor (const [key, startup] of starting) {\n\t\t\t\tstartup.cancelled = true;\n\t\t\t\tstarting_servers.delete(key);\n\t\t\t}\n\t\t\tawait Promise.allSettled(\n\t\t\t\tstates.map(([, state]) => state.client.stop()),\n\t\t\t);\n\t\t\tfor (const [key] of states) {\n\t\t\t\tclients_by_server.delete(key);\n\t\t\t}\n\n\t\t\tif (!language) {\n\t\t\t\tfailed_servers.clear();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const [key, failure] of failed_servers.entries()) {\n\t\t\t\tif (failure.language === language) {\n\t\t\t\t\tfailed_servers.delete(key);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tconst get_or_start_client = async (\n\t\t\tfile_path: string,\n\t\t): Promise<ServerState | undefined> => {\n\t\t\tconst language = detect_language(file_path);\n\t\t\tif (!language) return undefined;\n\t\t\tconst workspace_root = find_workspace_root(file_path, cwd);\n\t\t\tconst key = server_key(language, workspace_root);\n\t\t\tconst existing = clients_by_server.get(key);\n\t\t\tif (existing) return existing;\n\t\t\tconst failed = failed_servers.get(key);\n\t\t\tif (failed) {\n\t\t\t\tthrow new LspToolError(failed);\n\t\t\t}\n\t\t\tconst in_flight = starting_servers.get(key);\n\t\t\tif (in_flight) return in_flight.promise;\n\n\t\t\tconst server_config = get_server_config(\n\t\t\t\tlanguage,\n\t\t\t\tworkspace_root,\n\t\t\t);\n\t\t\tif (!server_config) return undefined;\n\t\t\tconst root_uri = file_path_to_uri(workspace_root);\n\n\t\t\tconst startup: StartingServerState = {\n\t\t\t\tcancelled: false,\n\t\t\t\tpromise: Promise.resolve<ServerState | undefined>(undefined),\n\t\t\t};\n\t\t\tconst start_promise = (async () => {\n\t\t\t\tconst client = create_client({\n\t\t\t\t\tcommand: server_config.command,\n\t\t\t\t\targs: server_config.args,\n\t\t\t\t\troot_uri,\n\t\t\t\t\tlanguage_id_for_uri: (uri) => language_id_for_file(uri),\n\t\t\t\t});\n\n\t\t\t\ttry {\n\t\t\t\t\tawait client.start();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (startup.cancelled) {\n\t\t\t\t\t\tthrow new LspStartupCancelledError(\n\t\t\t\t\t\t\tlanguage,\n\t\t\t\t\t\t\tworkspace_root,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst failure = to_lsp_tool_error(\n\t\t\t\t\t\tfile_path,\n\t\t\t\t\t\tlanguage,\n\t\t\t\t\t\tworkspace_root,\n\t\t\t\t\t\tserver_config.command,\n\t\t\t\t\t\tserver_config.install_hint,\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\t\t\t\t\tfailed_servers.set(key, failure);\n\t\t\t\t\tthrow new LspToolError(failure);\n\t\t\t\t}\n\n\t\t\t\tif (startup.cancelled) {\n\t\t\t\t\tawait Promise.allSettled([client.stop()]);\n\t\t\t\t\tthrow new LspStartupCancelledError(\n\t\t\t\t\t\tlanguage,\n\t\t\t\t\t\tworkspace_root,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst state: ServerState = {\n\t\t\t\t\tclient,\n\t\t\t\t\tlanguage,\n\t\t\t\t\tworkspace_root,\n\t\t\t\t\troot_uri,\n\t\t\t\t\tcommand: server_config.command,\n\t\t\t\t\tinstall_hint: server_config.install_hint,\n\t\t\t\t};\n\t\t\t\tclients_by_server.set(key, state);\n\t\t\t\tfailed_servers.delete(key);\n\t\t\t\treturn state;\n\t\t\t})();\n\n\t\t\tstartup.promise = start_promise;\n\t\t\tstarting_servers.set(key, startup);\n\t\t\ttry {\n\t\t\t\treturn await start_promise;\n\t\t\t} finally {\n\t\t\t\tif (starting_servers.get(key) === startup) {\n\t\t\t\t\tstarting_servers.delete(key);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tconst open_file = async (\n\t\t\tstate: ServerState,\n\t\t\tabs_path: string,\n\t\t): Promise<string> => {\n\t\t\tconst text = await read_file(abs_path);\n\t\t\tconst uri = file_path_to_uri(abs_path);\n\t\t\tawait state.client.ensure_document_open(uri, text);\n\t\t\treturn uri;\n\t\t};\n\n\t\tconst get_file_state = async (\n\t\t\tfile: string,\n\t\t): Promise<\n\t\t\t| {\n\t\t\t\t\tabs: string;\n\t\t\t\t\turi: string;\n\t\t\t\t\tstate: ServerState;\n\t\t\t }\n\t\t\t| undefined\n\t\t> => {\n\t\t\tconst abs = resolve_abs(file);\n\t\t\tconst state = await get_or_start_client(abs);\n\t\t\tif (!state) return undefined;\n\t\t\tconst uri = await open_file(state, abs);\n\t\t\treturn { abs, uri, state };\n\t\t};\n\n\t\tconst resolve_file_state = async (file: string) => {\n\t\t\tconst abs = resolve_abs(file);\n\t\t\ttry {\n\t\t\t\tconst result = await get_file_state(abs);\n\t\t\t\tif (!result) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false as const,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tkind: 'unsupported_language' as const,\n\t\t\t\t\t\t\tfile: abs,\n\t\t\t\t\t\t\tmessage: `No language server configured for ${abs}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tok: true as const,\n\t\t\t\t\tresult,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof LspToolError) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false as const,\n\t\t\t\t\t\terror: error.details,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tok: false as const,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tkind: 'tool_execution_failed' as const,\n\t\t\t\t\t\tfile: abs,\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t};\n\n\t\tconst with_file_state = async (\n\t\t\tfile: string,\n\t\t\trun: (result: {\n\t\t\t\tabs: string;\n\t\t\t\turi: string;\n\t\t\t\tstate: ServerState;\n\t\t\t}) => Promise<string>,\n\t\t) => {\n\t\t\tconst resolved = await resolve_file_state(file);\n\t\t\tif (!resolved.ok) {\n\t\t\t\treturn make_tool_error(resolved.error);\n\t\t\t}\n\t\t\tconst { result } = resolved;\n\t\t\ttry {\n\t\t\t\tconst text = await run(result);\n\t\t\t\treturn make_tool_result(text, {\n\t\t\t\t\tok: true,\n\t\t\t\t\tlanguage: result.state.language,\n\t\t\t\t\tcommand: result.state.command,\n\t\t\t\t\tworkspace_root: result.state.workspace_root,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\treturn make_tool_error(\n\t\t\t\t\tto_lsp_tool_error(\n\t\t\t\t\t\tresult.abs,\n\t\t\t\t\t\tresult.state.language,\n\t\t\t\t\t\tresult.state.workspace_root,\n\t\t\t\t\t\tresult.state.command,\n\t\t\t\t\t\tresult.state.install_hint,\n\t\t\t\t\t\terror,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tpi.registerTool(\n\t\t\tdefineTool({\n\t\t\t\tname: 'lsp_diagnostics',\n\t\t\t\tlabel: 'LSP: diagnostics',\n\t\t\t\tdescription:\n\t\t\t\t\t'Get language server diagnostics (errors, warnings, hints) for a file. Uses the project language server and returns empty output if the file is clean.',\n\t\t\t\tparameters: Type.Object({\n\t\t\t\t\tfile: Type.String({\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Path to the file to check (relative to cwd or absolute).',\n\t\t\t\t\t}),\n\t\t\t\t\twait_ms: Type.Optional(\n\t\t\t\t\t\tType.Number({\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t'Max ms to wait for diagnostics after opening the file. Default 1500.',\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\texecute: async (_id, params) =>\n\t\t\t\t\twith_file_state(params.file, async (result) => {\n\t\t\t\t\t\tconst diagnostics =\n\t\t\t\t\t\t\tawait result.state.client.wait_for_diagnostics(\n\t\t\t\t\t\t\t\tresult.uri,\n\t\t\t\t\t\t\t\tparams.wait_ms ?? 1500,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn format_diagnostics(result.abs, diagnostics);\n\t\t\t\t\t}),\n\t\t\t}),\n\t\t);\n\n\t\tpi.registerTool(\n\t\t\tdefineTool({\n\t\t\t\tname: 'lsp_diagnostics_many',\n\t\t\t\tlabel: 'LSP: diagnostics many',\n\t\t\t\tdescription:\n\t\t\t\t\t'Get language server diagnostics for multiple files in one call. Useful for package-level sweeps and summarization.',\n\t\t\t\tparameters: Type.Object({\n\t\t\t\t\tfiles: Type.Array(Type.String(), {\n\t\t\t\t\t\tminItems: 1,\n\t\t\t\t\t\tmaxItems: 100,\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Files to check (relative to cwd or absolute).',\n\t\t\t\t\t}),\n\t\t\t\t\twait_ms: Type.Optional(\n\t\t\t\t\t\tType.Number({\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t'Max ms to wait for diagnostics after opening each file. Default 1500.',\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\texecute: async (_id, params) => {\n\t\t\t\t\tconst results = await Promise.all(\n\t\t\t\t\t\tparams.files.map((file) => resolve_file_state(file)),\n\t\t\t\t\t);\n\t\t\t\t\tconst wait_ms = params.wait_ms ?? 1500;\n\t\t\t\t\tconst lines_with_stats = await Promise.all(\n\t\t\t\t\t\tresults.map(async (resolved) => {\n\t\t\t\t\t\t\tif (!resolved.ok) {\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tline: format_tool_error(resolved.error),\n\t\t\t\t\t\t\t\t\tdiagnostics: 0,\n\t\t\t\t\t\t\t\t\terror: true,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst diagnostics =\n\t\t\t\t\t\t\t\tawait resolved.result.state.client.wait_for_diagnostics(\n\t\t\t\t\t\t\t\t\tresolved.result.uri,\n\t\t\t\t\t\t\t\t\twait_ms,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tline: format_diagnostics(\n\t\t\t\t\t\t\t\t\tresolved.result.abs,\n\t\t\t\t\t\t\t\t\tdiagnostics,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tdiagnostics: diagnostics.length,\n\t\t\t\t\t\t\t\terror: false,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\n\t\t\t\t\tlet diagnostic_count = 0;\n\t\t\t\t\tlet clean_count = 0;\n\t\t\t\t\tlet error_count = 0;\n\t\t\t\t\tconst lines: string[] = [];\n\t\t\t\t\tfor (const entry of lines_with_stats) {\n\t\t\t\t\t\tlines.push(entry.line);\n\t\t\t\t\t\tif (entry.error) {\n\t\t\t\t\t\t\terror_count += 1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdiagnostic_count += entry.diagnostics;\n\t\t\t\t\t\t\tif (entry.diagnostics === 0) clean_count += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn make_tool_result(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t`Checked ${params.files.length} file(s): ${diagnostic_count} diagnostic(s), ${clean_count} clean, ${error_count} error(s)`,\n\t\t\t\t\t\t\t...lines,\n\t\t\t\t\t\t].join('\\n\\n'),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tok: error_count === 0,\n\t\t\t\t\t\t\tchecked: params.files.length,\n\t\t\t\t\t\t\tdiagnostic_count,\n\t\t\t\t\t\t\tclean_count,\n\t\t\t\t\t\t\terror_count,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\n\t\tpi.registerTool(\n\t\t\tdefineTool({\n\t\t\t\tname: 'lsp_find_symbol',\n\t\t\t\tlabel: 'LSP: find symbol',\n\t\t\t\tdescription:\n\t\t\t\t\t'Find symbols in a file by name or detail text using document symbols. Supports exact matching, kind filters, and top-level-only mode.',\n\t\t\t\tparameters: Type.Object({\n\t\t\t\t\tfile: Type.String(),\n\t\t\t\t\tquery: Type.String({\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Substring to match against symbol names/details.',\n\t\t\t\t\t}),\n\t\t\t\t\tmax_results: Type.Optional(\n\t\t\t\t\t\tType.Number({\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t'Max number of matches to return. Default 20.',\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\ttop_level_only: Type.Optional(\n\t\t\t\t\t\tType.Boolean({\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t'Only match top-level symbols. Default false.',\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\texact_match: Type.Optional(\n\t\t\t\t\t\tType.Boolean({\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t'Match whole symbol names/details exactly instead of substring matching. Default false.',\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tkinds: Type.Optional(\n\t\t\t\t\t\tType.Array(SYMBOL_KIND_SCHEMA, {\n\t\t\t\t\t\t\tminItems: 1,\n\t\t\t\t\t\t\tmaxItems: SYMBOL_KIND_NAMES.length,\n\t\t\t\t\t\t\tdescription: 'Restrict matches to these symbol kinds.',\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\texecute: async (_id, params) =>\n\t\t\t\t\twith_file_state(params.file, async (result) => {\n\t\t\t\t\t\tconst symbols =\n\t\t\t\t\t\t\tawait result.state.client.document_symbols(result.uri);\n\t\t\t\t\t\tconst matches = find_symbol_matches(\n\t\t\t\t\t\t\tsymbols,\n\t\t\t\t\t\t\tparams.query,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmax_results: params.max_results ?? 20,\n\t\t\t\t\t\t\t\ttop_level_only: params.top_level_only ?? false,\n\t\t\t\t\t\t\t\texact_match: params.exact_match ?? false,\n\t\t\t\t\t\t\t\tkinds: new Set(params.kinds ?? []),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn format_symbol_matches(\n\t\t\t\t\t\t\tresult.abs,\n\t\t\t\t\t\t\tparams.query,\n\t\t\t\t\t\t\tmatches,\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t}),\n\t\t);\n\n\t\tpi.registerTool(\n\t\t\tdefineTool({\n\t\t\t\tname: 'lsp_hover',\n\t\t\t\tlabel: 'LSP: hover',\n\t\t\t\tdescription:\n\t\t\t\t\t'Get hover info (types, docs) at a position in a file. Positions are zero-based.',\n\t\t\t\tparameters: Type.Object({\n\t\t\t\t\tfile: Type.String(),\n\t\t\t\t\tline: Type.Number({\n\t\t\t\t\t\tdescription: 'Zero-based line number.',\n\t\t\t\t\t}),\n\t\t\t\t\tcharacter: Type.Number({\n\t\t\t\t\t\tdescription: 'Zero-based character offset.',\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t\texecute: async (_id, params) =>\n\t\t\t\t\twith_file_state(params.file, async (result) => {\n\t\t\t\t\t\tconst hover = await result.state.client.hover(\n\t\t\t\t\t\t\tresult.uri,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tline: params.line,\n\t\t\t\t\t\t\t\tcharacter: params.character,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn format_hover(hover);\n\t\t\t\t\t}),\n\t\t\t}),\n\t\t);\n\n\t\tpi.registerTool(\n\t\t\tdefineTool({\n\t\t\t\tname: 'lsp_definition',\n\t\t\t\tlabel: 'LSP: go to definition',\n\t\t\t\tdescription:\n\t\t\t\t\t'Find definition locations for the symbol at a position. Positions are zero-based.',\n\t\t\t\tparameters: Type.Object({\n\t\t\t\t\tfile: Type.String(),\n\t\t\t\t\tline: Type.Number(),\n\t\t\t\t\tcharacter: Type.Number(),\n\t\t\t\t}),\n\t\t\t\texecute: async (_id, params) =>\n\t\t\t\t\twith_file_state(params.file, async (result) => {\n\t\t\t\t\t\tconst locations = await result.state.client.definition(\n\t\t\t\t\t\t\tresult.uri,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tline: params.line,\n\t\t\t\t\t\t\t\tcharacter: params.character,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn format_locations(\n\t\t\t\t\t\t\tlocations,\n\t\t\t\t\t\t\t'No definition found.',\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t}),\n\t\t);\n\n\t\tpi.registerTool(\n\t\t\tdefineTool({\n\t\t\t\tname: 'lsp_references',\n\t\t\t\tlabel: 'LSP: find references',\n\t\t\t\tdescription:\n\t\t\t\t\t'Find references to the symbol at a position. Positions are zero-based.',\n\t\t\t\tparameters: Type.Object({\n\t\t\t\t\tfile: Type.String(),\n\t\t\t\t\tline: Type.Number(),\n\t\t\t\t\tcharacter: Type.Number(),\n\t\t\t\t\tinclude_declaration: Type.Optional(Type.Boolean()),\n\t\t\t\t}),\n\t\t\t\texecute: async (_id, params) =>\n\t\t\t\t\twith_file_state(params.file, async (result) => {\n\t\t\t\t\t\tconst locations = await result.state.client.references(\n\t\t\t\t\t\t\tresult.uri,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tline: params.line,\n\t\t\t\t\t\t\t\tcharacter: params.character,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tparams.include_declaration ?? true,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn format_locations(\n\t\t\t\t\t\t\tlocations,\n\t\t\t\t\t\t\t'No references found.',\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t}),\n\t\t);\n\n\t\tpi.registerTool(\n\t\t\tdefineTool({\n\t\t\t\tname: 'lsp_document_symbols',\n\t\t\t\tlabel: 'LSP: document symbols',\n\t\t\t\tdescription:\n\t\t\t\t\t'List symbols in a file (functions, classes, variables) using the language server.',\n\t\t\t\tparameters: Type.Object({\n\t\t\t\t\tfile: Type.String(),\n\t\t\t\t}),\n\t\t\t\texecute: async (_id, params) =>\n\t\t\t\t\twith_file_state(params.file, async (result) => {\n\t\t\t\t\t\tconst symbols =\n\t\t\t\t\t\t\tawait result.state.client.document_symbols(result.uri);\n\t\t\t\t\t\treturn format_document_symbols(result.abs, symbols);\n\t\t\t\t\t}),\n\t\t\t}),\n\t\t);\n\n\t\tpi.registerCommand('lsp', {\n\t\t\tdescription: 'Show or manage language server state',\n\t\t\tgetArgumentCompletions: (prefix) => {\n\t\t\t\tconst parts = prefix.trim().split(/\\s+/);\n\t\t\t\tconst subcommands = ['status', 'list', 'restart'];\n\t\t\t\tif (!prefix.trim()) {\n\t\t\t\t\treturn subcommands.map((value) => ({\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\tlabel: value,\n\t\t\t\t\t}));\n\t\t\t\t}\n\t\t\t\tif (parts.length <= 1) {\n\t\t\t\t\treturn subcommands\n\t\t\t\t\t\t.filter((value) => value.startsWith(parts[0]))\n\t\t\t\t\t\t.map((value) => ({ value, label: value }));\n\t\t\t\t}\n\t\t\t\tif (parts[0] === 'restart') {\n\t\t\t\t\tconst candidate = parts[1] ?? '';\n\t\t\t\t\treturn ['all', ...list_supported_languages()]\n\t\t\t\t\t\t.filter((value) => value.startsWith(candidate))\n\t\t\t\t\t\t.map((value) => ({\n\t\t\t\t\t\t\tvalue: `restart ${value}`,\n\t\t\t\t\t\t\tlabel: value,\n\t\t\t\t\t\t}));\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\thandler: async (args, ctx) => {\n\t\t\t\tawait handle_lsp_command(\n\t\t\t\t\targs,\n\t\t\t\t\tctx,\n\t\t\t\t\tcwd,\n\t\t\t\t\tclients_by_server,\n\t\t\t\t\tfailed_servers,\n\t\t\t\t\tclear_language_state,\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\n\t\tpi.on('session_shutdown', async () => {\n\t\t\tawait clear_language_state();\n\t\t});\n\t};\n}\n\nexport default create_lsp_extension();\n\nasync function handle_lsp_command(\n\targs: string,\n\tctx: ExtensionCommandContext,\n\tcwd: string,\n\tclients_by_server: Map<string, ServerState>,\n\tfailed_servers: Map<string, LspToolErrorDetails>,\n\tclear_language_state: (language?: string) => Promise<void>,\n): Promise<void> {\n\tconst parts = args.trim() ? args.trim().split(/\\s+/, 2) : [];\n\tconst [subcommand = 'status', target] = parts;\n\n\tswitch (subcommand) {\n\t\tcase 'status':\n\t\tcase 'list':\n\t\t\tctx.ui.notify(\n\t\t\t\tformat_status_lines(\n\t\t\t\t\tcwd,\n\t\t\t\t\tclients_by_server,\n\t\t\t\t\tfailed_servers,\n\t\t\t\t).join('\\n'),\n\t\t\t);\n\t\t\treturn;\n\t\tcase 'restart': {\n\t\t\tif (!target || target === 'all') {\n\t\t\t\tawait clear_language_state();\n\t\t\t\tctx.ui.notify('Restarted all language server state.');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!list_supported_languages().includes(target)) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Unknown language: ${target}. Use one of: ${list_supported_languages().join(', ')}`,\n\t\t\t\t\t'warning',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait clear_language_state(target);\n\t\t\tctx.ui.notify(`Restarted ${target} language server state.`);\n\t\t\treturn;\n\t\t}\n\t\tdefault:\n\t\t\tctx.ui.notify(\n\t\t\t\t`Unknown subcommand: ${subcommand}. Use: status, list, restart`,\n\t\t\t\t'warning',\n\t\t\t);\n\t}\n}\n\nfunction format_status_lines(\n\tcwd: string,\n\tclients_by_server: Map<string, ServerState>,\n\tfailed_servers: Map<string, LspToolErrorDetails>,\n): string[] {\n\tconst lines: string[] = [];\n\tconst active_languages = new Set<string>();\n\tconst running_states = Array.from(clients_by_server.values()).sort(\n\t\t(a, b) =>\n\t\t\ta.language.localeCompare(b.language) ||\n\t\t\ta.workspace_root.localeCompare(b.workspace_root),\n\t);\n\tfor (const running of running_states) {\n\t\tactive_languages.add(running.language);\n\t\tlines.push(\n\t\t\t`${running.language}: running (ready=${running.client.is_ready()}) — ${running.command} [workspace ${running.workspace_root}]`,\n\t\t);\n\t}\n\n\tconst failures = Array.from(failed_servers.values()).sort(\n\t\t(a, b) =>\n\t\t\t(a.language ?? '').localeCompare(b.language ?? '') ||\n\t\t\t(a.workspace_root ?? '').localeCompare(b.workspace_root ?? ''),\n\t);\n\tfor (const failure of failures) {\n\t\tif (failure.language) {\n\t\t\tactive_languages.add(failure.language);\n\t\t}\n\t\tconst workspace = failure.workspace_root\n\t\t\t? ` [workspace ${failure.workspace_root}]`\n\t\t\t: '';\n\t\tconst language = failure.language ?? 'unknown';\n\t\tlines.push(\n\t\t\t`${language}: failed — ${failure.message}${workspace}`,\n\t\t);\n\t}\n\n\tfor (const language of list_supported_languages()) {\n\t\tif (active_languages.has(language)) continue;\n\t\tconst config = get_server_config(language, cwd);\n\t\tif (config) {\n\t\t\tlines.push(`${language}: idle — ${config.command}`);\n\t\t}\n\t}\n\treturn lines.length > 0\n\t\t? lines\n\t\t: ['No language servers configured for this project.'];\n}\n\nfunction to_lsp_tool_error(\n\tfile: string,\n\tlanguage: string,\n\tworkspace_root: string,\n\tcommand: string,\n\tinstall_hint: string | undefined,\n\terror: unknown,\n): LspToolErrorDetails {\n\tif (error instanceof LspToolError) {\n\t\treturn error.details;\n\t}\n\tif (error instanceof LspClientStartError) {\n\t\tconst missing_binary = error.code === 'ENOENT';\n\t\treturn {\n\t\t\tkind: 'server_start_failed',\n\t\t\tfile,\n\t\t\tlanguage,\n\t\t\tworkspace_root,\n\t\t\tcommand,\n\t\t\tinstall_hint,\n\t\t\tcode: error.code,\n\t\t\tmessage: missing_binary\n\t\t\t\t? `command \"${command}\" not found`\n\t\t\t\t: error.message,\n\t\t};\n\t}\n\treturn {\n\t\tkind: 'tool_execution_failed',\n\t\tfile,\n\t\tlanguage,\n\t\tworkspace_root,\n\t\tcommand,\n\t\tinstall_hint,\n\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\tcode:\n\t\t\ttypeof error === 'object' &&\n\t\t\terror !== null &&\n\t\t\t'code' in error &&\n\t\t\ttypeof (error as { code?: unknown }).code === 'string'\n\t\t\t\t? (error as { code: string }).code\n\t\t\t\t: undefined,\n\t};\n}\n\nfunction format_tool_error(details: LspToolErrorDetails): string {\n\tif (details.kind === 'unsupported_language') {\n\t\treturn details.message;\n\t}\n\tconst lines = [\n\t\tdetails.language\n\t\t\t? `${details.language} LSP unavailable for ${details.file}`\n\t\t\t: `LSP request failed for ${details.file}`,\n\t\t`Reason: ${details.message}`,\n\t];\n\tif (details.command) {\n\t\tlines.push(`Command: ${details.command}`);\n\t}\n\tif (details.workspace_root) {\n\t\tlines.push(`Workspace: ${details.workspace_root}`);\n\t}\n\tif (details.install_hint) {\n\t\tlines.push(`Hint: ${details.install_hint}`);\n\t}\n\treturn lines.join('\\n');\n}\n\nfunction severity_label(severity: LspDiagnostic['severity']): string {\n\tswitch (severity) {\n\t\tcase 1:\n\t\t\treturn 'error';\n\t\tcase 2:\n\t\t\treturn 'warning';\n\t\tcase 3:\n\t\t\treturn 'info';\n\t\tcase 4:\n\t\t\treturn 'hint';\n\t\tdefault:\n\t\t\treturn 'info';\n\t}\n}\n\nfunction format_diagnostics(\n\tfile: string,\n\tdiagnostics: LspDiagnostic[],\n): string {\n\tif (diagnostics.length === 0) {\n\t\treturn `${file}: no diagnostics`;\n\t}\n\tconst lines = [`${file}: ${diagnostics.length} diagnostic(s)`];\n\tfor (const d of diagnostics) {\n\t\tconst position = `${d.range.start.line + 1}:${d.range.start.character + 1}`;\n\t\tconst source = d.source ? ` [${d.source}]` : '';\n\t\tconst code = d.code != null ? ` (${d.code})` : '';\n\t\tlines.push(\n\t\t\t` ${position} ${severity_label(d.severity)}${source}${code}: ${d.message}`,\n\t\t);\n\t}\n\treturn lines.join('\\n');\n}\n\nfunction format_hover(hover: LspHover | null): string {\n\tif (!hover) return 'No hover info.';\n\tconst contents = hover.contents;\n\tconst extract = (\n\t\titem:\n\t\t\t| string\n\t\t\t| { language?: string; value: string }\n\t\t\t| { kind: string; value: string },\n\t): string => (typeof item === 'string' ? item : (item.value ?? ''));\n\n\tif (Array.isArray(contents)) {\n\t\treturn (\n\t\t\tcontents.map(extract).join('\\n\\n').trim() || 'No hover info.'\n\t\t);\n\t}\n\treturn extract(contents).trim() || 'No hover info.';\n}\n\nfunction format_locations(\n\tlocations: LspLocation[],\n\tempty_message: string,\n): string {\n\tif (locations.length === 0) return empty_message;\n\treturn locations\n\t\t.map((loc) => {\n\t\t\tconst path = file_url_to_path_or_value(loc.uri);\n\t\t\treturn `${path}:${loc.range.start.line + 1}:${loc.range.start.character + 1}`;\n\t\t})\n\t\t.join('\\n');\n}\n\nfunction format_document_symbols(\n\tfile: string,\n\tsymbols: LspDocumentSymbol[],\n): string {\n\tif (symbols.length === 0) {\n\t\treturn `${file}: no symbols`;\n\t}\n\tconst lines = [`${file}: ${symbols.length} top-level symbol(s)`];\n\tappend_symbol_lines(lines, symbols, 1);\n\treturn lines.join('\\n');\n}\n\nfunction find_symbol_matches(\n\tsymbols: LspDocumentSymbol[],\n\tquery: string,\n\toptions: {\n\t\tmax_results: number;\n\t\ttop_level_only: boolean;\n\t\texact_match: boolean;\n\t\tkinds: ReadonlySet<string>;\n\t},\n): Array<{ symbol: LspDocumentSymbol; depth: number }> {\n\tconst normalized = query.trim().toLowerCase();\n\tif (!normalized) return [];\n\tconst matches: Array<{ symbol: LspDocumentSymbol; depth: number }> =\n\t\t[];\n\tconst matches_query = (symbol: LspDocumentSymbol): boolean => {\n\t\tconst values = [symbol.name, symbol.detail ?? ''].map((value) =>\n\t\t\tvalue.trim().toLowerCase(),\n\t\t);\n\t\treturn options.exact_match\n\t\t\t? values.some((value) => value === normalized)\n\t\t\t: values.some((value) => value.includes(normalized));\n\t};\n\tconst matches_kind = (symbol: LspDocumentSymbol): boolean => {\n\t\tif (options.kinds.size === 0) return true;\n\t\treturn options.kinds.has(symbol_kind_label(symbol.kind));\n\t};\n\tconst visit = (\n\t\tentries: LspDocumentSymbol[],\n\t\tdepth: number,\n\t): void => {\n\t\tfor (const symbol of entries) {\n\t\t\tif (matches_kind(symbol) && matches_query(symbol)) {\n\t\t\t\tmatches.push({ symbol, depth });\n\t\t\t\tif (matches.length >= options.max_results) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!options.top_level_only && symbol.children?.length) {\n\t\t\t\tvisit(symbol.children, depth + 1);\n\t\t\t\tif (matches.length >= options.max_results) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\tvisit(symbols, 1);\n\treturn matches;\n}\n\nfunction format_symbol_matches(\n\tfile: string,\n\tquery: string,\n\tmatches: Array<{ symbol: LspDocumentSymbol; depth: number }>,\n): string {\n\tif (matches.length === 0) {\n\t\treturn `${file}: no symbols matching \"${query}\"`;\n\t}\n\tconst lines = [\n\t\t`${file}: ${matches.length} symbol match(es) for \"${query}\"`,\n\t];\n\tfor (const { symbol, depth } of matches) {\n\t\tconst indent = ' '.repeat(depth);\n\t\tconst detail = symbol.detail ? ` — ${symbol.detail}` : '';\n\t\tconst range = `${symbol.range.start.line + 1}:${symbol.range.start.character + 1}`;\n\t\tlines.push(\n\t\t\t`${indent}${symbol_kind_label(symbol.kind)} ${symbol.name}${detail} @ ${range}`,\n\t\t);\n\t}\n\treturn lines.join('\\n');\n}\n\nfunction append_symbol_lines(\n\tlines: string[],\n\tsymbols: LspDocumentSymbol[],\n\tdepth: number,\n): void {\n\tfor (const symbol of symbols) {\n\t\tconst indent = ' '.repeat(depth);\n\t\tconst detail = symbol.detail ? ` — ${symbol.detail}` : '';\n\t\tconst range = `${symbol.range.start.line + 1}:${symbol.range.start.character + 1}`;\n\t\tlines.push(\n\t\t\t`${indent}${symbol_kind_label(symbol.kind)} ${symbol.name}${detail} @ ${range}`,\n\t\t);\n\t\tif (symbol.children?.length) {\n\t\t\tappend_symbol_lines(lines, symbol.children, depth + 1);\n\t\t}\n\t}\n}\n\nfunction symbol_kind_label(kind: number): string {\n\treturn SYMBOL_KIND_LABELS[kind] ?? 'symbol';\n}\n\nfunction file_url_to_path_or_value(uri: string): string {\n\ttry {\n\t\treturn uri.startsWith('file:') ? fileURLToPath(uri) : uri;\n\t} catch {\n\t\treturn uri;\n\t}\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\n\nexport interface McpStdioServerConfig {\n\tname: string;\n\ttransport: 'stdio';\n\tcommand: string;\n\targs?: string[];\n\tenv?: Record<string, string>;\n}\n\nexport interface McpHttpServerConfig {\n\tname: string;\n\ttransport: 'http';\n\turl: string;\n\theaders?: Record<string, string>;\n}\n\nexport type McpServerConfig =\n\t| McpStdioServerConfig\n\t| McpHttpServerConfig;\n\ninterface JsonRpcRequest {\n\tjsonrpc: '2.0';\n\tid?: number;\n\tmethod: string;\n\tparams?: unknown;\n}\n\ninterface JsonRpcResponse {\n\tjsonrpc?: '2.0';\n\tid?: number;\n\tresult?: unknown;\n\terror?: { code: number; message: string };\n}\n\nexport interface McpToolInfo {\n\tname: string;\n\tdescription?: string;\n\tinputSchema?: Record<string, unknown>;\n}\n\nexport class McpClient {\n\t#proc: ChildProcess | null = null;\n\t#config: McpServerConfig;\n\t#nextId = 1;\n\t#pending = new Map<\n\t\tnumber,\n\t\t{\n\t\t\tresolve: (v: unknown) => void;\n\t\t\treject: (e: Error) => void;\n\t\t}\n\t>();\n\t#buffer = '';\n\t#sessionId?: string;\n\n\tconstructor(config: McpServerConfig) {\n\t\tthis.#config = config;\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (this.#config.transport === 'stdio') {\n\t\t\tawait this.#connect_stdio();\n\t\t}\n\n\t\tawait this.#request('initialize', {\n\t\t\tprotocolVersion: '2024-11-05',\n\t\t\tcapabilities: {},\n\t\t\tclientInfo: { name: 'my-pi', version: '0.0.1' },\n\t\t});\n\n\t\tawait this.#send({\n\t\t\tjsonrpc: '2.0',\n\t\t\tmethod: 'notifications/initialized',\n\t\t});\n\t}\n\n\tasync listTools(): Promise<McpToolInfo[]> {\n\t\tconst result = (await this.#request('tools/list', {})) as {\n\t\t\ttools: McpToolInfo[];\n\t\t};\n\t\treturn result.tools;\n\t}\n\n\tasync callTool(\n\t\tname: string,\n\t\targs: Record<string, unknown>,\n\t): Promise<unknown> {\n\t\treturn this.#request('tools/call', {\n\t\t\tname,\n\t\t\targuments: args,\n\t\t});\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tif (this.#config.transport === 'http') {\n\t\t\tawait this.#disconnect_http();\n\t\t}\n\t\tif (this.#proc) {\n\t\t\tthis.#proc.kill();\n\t\t\tthis.#proc = null;\n\t\t}\n\t\tthis.#pending.clear();\n\t}\n\n\tasync #connect_stdio(): Promise<void> {\n\t\tconst {\n\t\t\tcommand,\n\t\t\targs = [],\n\t\t\tenv,\n\t\t} = this.#config as McpStdioServerConfig;\n\n\t\tthis.#proc = spawn(command, args, {\n\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\tenv: { ...process.env, ...env },\n\t\t});\n\n\t\tthis.#proc.stdout!.setEncoding('utf8');\n\t\tthis.#proc.stdout!.on('data', (chunk: string) => {\n\t\t\tthis.#buffer += chunk;\n\t\t\tconst lines = this.#buffer.split('\\n');\n\t\t\tthis.#buffer = lines.pop() || '';\n\n\t\t\tfor (const line of lines) {\n\t\t\t\tif (!line.trim()) continue;\n\t\t\t\ttry {\n\t\t\t\t\tthis.#handle_message(JSON.parse(line) as JsonRpcResponse);\n\t\t\t\t} catch {\n\t\t\t\t\t// ignore non-JSON lines\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t#request(method: string, params: unknown): Promise<unknown> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst id = this.#nextId++;\n\t\t\tthis.#pending.set(id, { resolve, reject });\n\t\t\tthis.#send({ jsonrpc: '2.0', id, method, params }).catch(\n\t\t\t\t(error) => {\n\t\t\t\t\tif (this.#pending.has(id)) {\n\t\t\t\t\t\tthis.#pending.delete(id);\n\t\t\t\t\t\treject(error as Error);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (this.#pending.has(id)) {\n\t\t\t\t\tthis.#pending.delete(id);\n\t\t\t\t\treject(new Error(`MCP request ${method} timed out`));\n\t\t\t\t}\n\t\t\t}, 30_000);\n\t\t});\n\t}\n\n\tasync #send(msg: JsonRpcRequest): Promise<void> {\n\t\tif (this.#config.transport === 'http') {\n\t\t\tawait this.#send_http(msg);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.#proc?.stdin?.writable) {\n\t\t\tthrow new Error('MCP server not connected');\n\t\t}\n\t\tthis.#proc.stdin.write(JSON.stringify(msg) + '\\n');\n\t}\n\n\tasync #send_http(msg: JsonRpcRequest): Promise<void> {\n\t\tconst config = this.#config as McpHttpServerConfig;\n\t\tconst headers = new Headers(config.headers ?? {});\n\t\theaders.set('content-type', 'application/json');\n\t\theaders.set('accept', 'application/json, text/event-stream');\n\t\tif (this.#sessionId) {\n\t\t\theaders.set('mcp-session-id', this.#sessionId);\n\t\t}\n\n\t\tconst response = await fetch(config.url, {\n\t\t\tmethod: 'POST',\n\t\t\theaders,\n\t\t\tbody: JSON.stringify(msg),\n\t\t});\n\n\t\tconst sessionId = response.headers.get('mcp-session-id');\n\t\tif (sessionId) {\n\t\t\tthis.#sessionId = sessionId;\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tconst body = await response.text().catch(() => '');\n\t\t\tthrow new Error(\n\t\t\t\t`MCP HTTP ${response.status}${body ? `: ${body}` : ''}`,\n\t\t\t);\n\t\t}\n\n\t\tif (response.status === 204) return;\n\n\t\tconst contentType = response.headers.get('content-type') ?? '';\n\t\tif (contentType.includes('text/event-stream')) {\n\t\t\tawait this.#consume_sse_response(response, config.name);\n\t\t\treturn;\n\t\t}\n\n\t\tconst body = await response.text();\n\t\tif (!body.trim()) return;\n\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(body);\n\t\t} catch {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid MCP HTTP response from ${config.name}: ${body.slice(0, 200)}`,\n\t\t\t);\n\t\t}\n\t\tthis.#dispatch_message(parsed);\n\t}\n\n\tasync #disconnect_http(): Promise<void> {\n\t\tconst config = this.#config as McpHttpServerConfig;\n\t\tif (!this.#sessionId) return;\n\n\t\tconst headers = new Headers(config.headers ?? {});\n\t\theaders.set('mcp-session-id', this.#sessionId);\n\t\tconst response = await fetch(config.url, {\n\t\t\tmethod: 'DELETE',\n\t\t\theaders,\n\t\t});\n\t\tif (response.status !== 405 && !response.ok) {\n\t\t\tconst body = await response.text().catch(() => '');\n\t\t\tthrow new Error(\n\t\t\t\t`MCP HTTP disconnect ${response.status}${body ? `: ${body}` : ''}`,\n\t\t\t);\n\t\t}\n\t\tthis.#sessionId = undefined;\n\t}\n\n\tasync #consume_sse_response(\n\t\tresponse: Response,\n\t\tserver_name: string,\n\t): Promise<void> {\n\t\tif (!response.body) return;\n\n\t\tconst reader = response.body.getReader();\n\t\tconst decoder = new TextDecoder();\n\t\tlet buffer = '';\n\t\tlet event_lines: string[] = [];\n\n\t\tconst flush_event = () => {\n\t\t\tif (event_lines.length === 0) return;\n\t\t\tconst data_lines = event_lines\n\t\t\t\t.filter((line) => line.startsWith('data:'))\n\t\t\t\t.map((line) => line.slice(5).trimStart());\n\t\t\tevent_lines = [];\n\t\t\tif (data_lines.length === 0) return;\n\t\t\tconst payload = data_lines.join('\\n').trim();\n\t\t\tif (!payload) return;\n\n\t\t\ttry {\n\t\t\t\tthis.#dispatch_message(JSON.parse(payload));\n\t\t\t} catch {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid MCP SSE payload from ${server_name}: ${payload.slice(0, 200)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tbuffer += decoder.decode(value ?? new Uint8Array(), {\n\t\t\t\tstream: !done,\n\t\t\t});\n\t\t\tconst normalized = buffer.replace(/\\r\\n/g, '\\n');\n\t\t\tconst lines = normalized.split('\\n');\n\t\t\tbuffer = lines.pop() ?? '';\n\n\t\t\tfor (const line of lines) {\n\t\t\t\tif (line === '') {\n\t\t\t\t\tflush_event();\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (line.startsWith(':')) continue;\n\t\t\t\tevent_lines.push(line);\n\t\t\t}\n\n\t\t\tif (done) break;\n\t\t}\n\n\t\tif (buffer.trim()) {\n\t\t\tevent_lines.push(buffer.trim());\n\t\t}\n\t\tflush_event();\n\t}\n\n\t#dispatch_message(message: unknown): void {\n\t\tif (Array.isArray(message)) {\n\t\t\tfor (const item of message) {\n\t\t\t\tthis.#dispatch_message(item);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (!message || typeof message !== 'object') return;\n\t\tthis.#handle_message(message as JsonRpcResponse);\n\t}\n\n\t#handle_message(msg: JsonRpcResponse): void {\n\t\tif (msg.id == null || !this.#pending.has(msg.id)) return;\n\t\tconst pending = this.#pending.get(msg.id)!;\n\t\tthis.#pending.delete(msg.id);\n\t\tif (msg.error) {\n\t\t\tpending.reject(\n\t\t\t\tnew Error(\n\t\t\t\t\t`MCP error ${msg.error.code}: ${msg.error.message}`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tpending.resolve(msg.result);\n\t}\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type {\n\tMcpHttpServerConfig,\n\tMcpServerConfig,\n\tMcpStdioServerConfig,\n} from './client.js';\n\ninterface RawMcpConfigFile {\n\tmcpServers: Record<string, RawMcpServerEntry>;\n}\n\ntype RawMcpServerEntry = {\n\ttype?: unknown;\n\tcommand?: unknown;\n\targs?: unknown;\n\tenv?: unknown;\n\turl?: unknown;\n\theaders?: unknown;\n};\n\nfunction is_string_record(\n\tvalue: unknown,\n\tlabel: string,\n\tname: string,\n): value is Record<string, string> {\n\tif (value === undefined) return true;\n\tif (!value || typeof value !== 'object' || Array.isArray(value)) {\n\t\tthrow new Error(\n\t\t\t`Invalid MCP server \"${name}\": ${label} must be an object of string values`,\n\t\t);\n\t}\n\n\tfor (const [key, entry] of Object.entries(value)) {\n\t\tif (typeof entry !== 'string') {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid MCP server \"${name}\": ${label}.${key} must be a string`,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn true;\n}\n\nfunction parse_server(\n\tname: string,\n\tentry: RawMcpServerEntry,\n): McpServerConfig {\n\tconst type =\n\t\ttypeof entry.type === 'string'\n\t\t\t? entry.type.trim().toLowerCase()\n\t\t\t: '';\n\n\tif (type && !['stdio', 'http', 'streamable-http'].includes(type)) {\n\t\tthrow new Error(\n\t\t\t`Invalid MCP server \"${name}\": unsupported transport type \"${type}\"`,\n\t\t);\n\t}\n\n\tif (\n\t\ttype === 'http' ||\n\t\ttype === 'streamable-http' ||\n\t\tentry.url !== undefined\n\t) {\n\t\tif (typeof entry.url !== 'string' || !entry.url.trim()) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid MCP server \"${name}\": http transport requires a url`,\n\t\t\t);\n\t\t}\n\t\tis_string_record(entry.headers, 'headers', name);\n\t\tconst headers = entry.headers as\n\t\t\t| Record<string, string>\n\t\t\t| undefined;\n\t\tconst config: McpHttpServerConfig = {\n\t\t\tname,\n\t\t\ttransport: 'http',\n\t\t\turl: entry.url.trim(),\n\t\t\t...(headers ? { headers } : {}),\n\t\t};\n\t\treturn config;\n\t}\n\n\tif (typeof entry.command !== 'string' || !entry.command.trim()) {\n\t\tthrow new Error(\n\t\t\t`Invalid MCP server \"${name}\": stdio transport requires a command`,\n\t\t);\n\t}\n\tif (\n\t\tentry.args !== undefined &&\n\t\t(!Array.isArray(entry.args) ||\n\t\t\tentry.args.some((value) => typeof value !== 'string'))\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid MCP server \"${name}\": args must be an array of strings`,\n\t\t);\n\t}\n\tis_string_record(entry.env, 'env', name);\n\tconst args = entry.args as string[] | undefined;\n\tconst env = entry.env as Record<string, string> | undefined;\n\n\tconst config: McpStdioServerConfig = {\n\t\tname,\n\t\ttransport: 'stdio',\n\t\tcommand: entry.command.trim(),\n\t\t...(args ? { args } : {}),\n\t\t...(env ? { env } : {}),\n\t};\n\treturn config;\n}\n\nfunction read_config(path: string): RawMcpConfigFile['mcpServers'] {\n\tif (!existsSync(path)) return {};\n\tconst raw = readFileSync(path, 'utf-8');\n\tconst config = JSON.parse(raw) as RawMcpConfigFile;\n\treturn config.mcpServers || {};\n}\n\nexport function load_mcp_config(cwd: string): McpServerConfig[] {\n\tconst global_servers = read_config(\n\t\tjoin(homedir(), '.pi', 'agent', 'mcp.json'),\n\t);\n\tconst project_servers = read_config(join(cwd, 'mcp.json'));\n\tconst merged = { ...global_servers, ...project_servers };\n\n\treturn Object.entries(merged).map(([name, server]) =>\n\t\tparse_server(name, server),\n\t);\n}\n","import {\n\ttype ExtensionAPI,\n\tdefineTool,\n} from '@mariozechner/pi-coding-agent';\nimport { McpClient, type McpServerConfig } from '../mcp/client.js';\nimport { load_mcp_config } from '../mcp/config.js';\n\ninterface ServerState {\n\tconfig: McpServerConfig;\n\tclient?: McpClient;\n\ttool_names: string[];\n\tenabled: boolean;\n\tstatus: 'disconnected' | 'connecting' | 'connected' | 'failed';\n\terror?: string;\n\tconnect_promise?: Promise<void>;\n}\n\nfunction remove_server_tools_from_active(\n\tpi: ExtensionAPI,\n\ttool_names: string[],\n): void {\n\tconst tool_set = new Set(tool_names);\n\tpi.setActiveTools(\n\t\tpi.getActiveTools().filter((tool) => !tool_set.has(tool)),\n\t);\n}\n\nfunction format_server_status(state: ServerState): string {\n\tswitch (state.status) {\n\t\tcase 'connected':\n\t\t\treturn state.enabled ? 'enabled' : 'disabled';\n\t\tcase 'connecting':\n\t\t\treturn state.enabled ? 'connecting' : 'connecting, disabled';\n\t\tcase 'failed':\n\t\t\treturn state.enabled ? 'failed' : 'failed, disabled';\n\t\tdefault:\n\t\t\treturn state.enabled ? 'not connected yet' : 'disabled';\n\t}\n}\n\n// Default export for Pi Package / additionalExtensionPaths loading\nexport default async function mcp(pi: ExtensionAPI) {\n\tconst cwd = process.cwd();\n\tconst configs = load_mcp_config(cwd);\n\tconst servers = new Map<string, ServerState>(\n\t\tconfigs.map((config) => [\n\t\t\tconfig.name,\n\t\t\t{\n\t\t\t\tconfig,\n\t\t\t\ttool_names: [],\n\t\t\t\tenabled: true,\n\t\t\t\tstatus: 'disconnected' as const,\n\t\t\t},\n\t\t]),\n\t);\n\tconst registered_tool_names = new Set<string>();\n\n\tconst connect_server = async (\n\t\tstate: ServerState,\n\t): Promise<void> => {\n\t\tif (state.status === 'connected') return;\n\t\tif (state.connect_promise) {\n\t\t\tawait state.connect_promise;\n\t\t\treturn;\n\t\t}\n\n\t\tstate.connect_promise = (async () => {\n\t\t\tstate.status = 'connecting';\n\t\t\tstate.error = undefined;\n\n\t\t\tconst client = new McpClient(state.config);\n\t\t\ttry {\n\t\t\t\tawait client.connect();\n\t\t\t\tstate.client = client;\n\n\t\t\t\tconst mcp_tools = await client.listTools();\n\t\t\t\tconst tool_names: string[] = [];\n\n\t\t\t\tfor (const mcp_tool of mcp_tools) {\n\t\t\t\t\tconst tool_name = `mcp__${state.config.name}__${mcp_tool.name}`;\n\t\t\t\t\ttool_names.push(tool_name);\n\n\t\t\t\t\tif (registered_tool_names.has(tool_name)) continue;\n\t\t\t\t\tregistered_tool_names.add(tool_name);\n\n\t\t\t\t\tpi.registerTool(\n\t\t\t\t\t\tdefineTool({\n\t\t\t\t\t\t\tname: tool_name,\n\t\t\t\t\t\t\tlabel: `${state.config.name}: ${mcp_tool.name}`,\n\t\t\t\t\t\t\tdescription: mcp_tool.description || mcp_tool.name,\n\t\t\t\t\t\t\tparameters: (mcp_tool.inputSchema || {\n\t\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t\t\t}) as Parameters<typeof defineTool>[0]['parameters'],\n\t\t\t\t\t\t\texecute: async (_id, params) => {\n\t\t\t\t\t\t\t\tconst result = (await state.client!.callTool(\n\t\t\t\t\t\t\t\t\tmcp_tool.name,\n\t\t\t\t\t\t\t\t\tparams as Record<string, unknown>,\n\t\t\t\t\t\t\t\t)) as {\n\t\t\t\t\t\t\t\t\tcontent?: Array<{\n\t\t\t\t\t\t\t\t\t\ttype: string;\n\t\t\t\t\t\t\t\t\t\ttext?: string;\n\t\t\t\t\t\t\t\t\t}>;\n\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\tconst text =\n\t\t\t\t\t\t\t\t\tresult?.content\n\t\t\t\t\t\t\t\t\t\t?.map((c) => c.text || '')\n\t\t\t\t\t\t\t\t\t\t.join('\\n') || JSON.stringify(result);\n\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tcontent: [{ type: 'text' as const, text }],\n\t\t\t\t\t\t\t\t\tdetails: {},\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tstate.tool_names = tool_names;\n\t\t\t\tstate.status = 'connected';\n\t\t\t\tif (!state.enabled) {\n\t\t\t\t\tremove_server_tools_from_active(pi, state.tool_names);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tstate.status = 'failed';\n\t\t\t\tstate.error =\n\t\t\t\t\terror instanceof Error ? error.message : String(error);\n\t\t\t\tstate.client = undefined;\n\t\t\t\tawait client.disconnect().catch(() => {});\n\t\t\t\tconsole.error(\n\t\t\t\t\t`MCP server failed (${state.config.name}): ${state.error}`,\n\t\t\t\t);\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tstate.connect_promise = undefined;\n\t\t\t}\n\t\t})();\n\n\t\tawait state.connect_promise;\n\t};\n\n\tconst connect_all_servers = async (\n\t\toptions: { include_failed?: boolean } = {},\n\t): Promise<void> => {\n\t\tawait Promise.allSettled(\n\t\t\tArray.from(servers.values())\n\t\t\t\t.filter((state) => state.enabled)\n\t\t\t\t.filter(\n\t\t\t\t\t(state) =>\n\t\t\t\t\t\toptions.include_failed || state.status !== 'failed',\n\t\t\t\t)\n\t\t\t\t.map((state) => connect_server(state)),\n\t\t);\n\t};\n\n\tpi.on('session_start', async () => {\n\t\tvoid connect_all_servers();\n\t});\n\n\tpi.on('before_agent_start', async (event) => {\n\t\tawait connect_all_servers();\n\t\treturn event;\n\t});\n\n\tpi.registerCommand('mcp', {\n\t\tdescription: 'Manage MCP servers (list, enable, disable)',\n\t\tgetArgumentCompletions: (prefix) => {\n\t\t\tconst parts = prefix.split(' ');\n\t\t\tif (parts.length <= 1) {\n\t\t\t\treturn ['list', 'enable', 'disable']\n\t\t\t\t\t.filter((s) => s.startsWith(prefix))\n\t\t\t\t\t.map((s) => ({ value: s, label: s }));\n\t\t\t}\n\t\t\tif (parts[0] === 'enable' || parts[0] === 'disable') {\n\t\t\t\tconst name_prefix = parts[1] || '';\n\t\t\t\treturn Array.from(servers.keys())\n\t\t\t\t\t.filter((n) => n.startsWith(name_prefix))\n\t\t\t\t\t.map((n) => ({\n\t\t\t\t\t\tvalue: `${parts[0]} ${n}`,\n\t\t\t\t\t\tlabel: n,\n\t\t\t\t\t}));\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\thandler: async (args, ctx) => {\n\t\t\tconst [sub, ...rest] = args.trim().split(/\\s+/);\n\t\t\tconst name = rest.join(' ');\n\n\t\t\tswitch (sub || 'list') {\n\t\t\t\tcase 'list': {\n\t\t\t\t\tif (servers.size === 0) {\n\t\t\t\t\t\tctx.ui.notify('No MCP servers configured');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst lines: string[] = [];\n\t\t\t\t\tfor (const [sname, state] of servers.entries()) {\n\t\t\t\t\t\tlines.push(\n\t\t\t\t\t\t\t`${sname} (${format_server_status(state)}) — ${state.tool_names.length} tools${state.error ? ` — ${state.error}` : ''}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tctx.ui.notify(lines.join('\\n'));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'enable': {\n\t\t\t\t\tconst server = servers.get(name);\n\t\t\t\t\tif (!server) {\n\t\t\t\t\t\tctx.ui.notify(`Unknown server: ${name}`, 'warning');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (server.enabled && server.status !== 'failed') {\n\t\t\t\t\t\tctx.ui.notify(`${name} already enabled`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tserver.enabled = true;\n\t\t\t\t\tif (server.status === 'connected') {\n\t\t\t\t\t\tconst active = pi.getActiveTools();\n\t\t\t\t\t\tpi.setActiveTools([...active, ...server.tool_names]);\n\t\t\t\t\t\tctx.ui.notify(`Enabled ${name}`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (server.status === 'failed') {\n\t\t\t\t\t\tserver.status = 'disconnected';\n\t\t\t\t\t\tserver.error = undefined;\n\t\t\t\t\t}\n\t\t\t\t\tvoid connect_server(server);\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t`Enabling ${name} and connecting in background`,\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'disable': {\n\t\t\t\t\tconst server = servers.get(name);\n\t\t\t\t\tif (!server) {\n\t\t\t\t\t\tctx.ui.notify(`Unknown server: ${name}`, 'warning');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!server.enabled) {\n\t\t\t\t\t\tctx.ui.notify(`${name} already disabled`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tserver.enabled = false;\n\t\t\t\t\tremove_server_tools_from_active(pi, server.tool_names);\n\t\t\t\t\tctx.ui.notify(`Disabled ${name}`);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t`Unknown subcommand: ${sub}. Use list, enable, or disable.`,\n\t\t\t\t\t\t'warning',\n\t\t\t\t\t);\n\t\t\t}\n\t\t},\n\t});\n\n\tpi.on('session_shutdown', async () => {\n\t\tawait Promise.allSettled(\n\t\t\tArray.from(servers.values()).map(async (server) => {\n\t\t\t\tawait server.connect_promise?.catch(() => {});\n\t\t\t\tawait server.client?.disconnect();\n\t\t\t\tserver.client = undefined;\n\t\t\t\tif (server.status !== 'failed') {\n\t\t\t\t\tserver.status = 'disconnected';\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t});\n}\n","import {\n\tgetAgentDir,\n\ttype ExtensionAPI,\n\ttype ExtensionCommandContext,\n\ttype ExtensionContext,\n\ttype ReadonlyFooterDataProvider,\n} from '@mariozechner/pi-coding-agent';\nimport {\n\tContainer,\n\tSettingsList,\n\tText,\n\ttruncateToWidth,\n\tvisibleWidth,\n\ttype SettingItem,\n} from '@mariozechner/pi-tui';\nimport {\n\texistsSync,\n\tmkdirSync,\n\treadFileSync,\n\trenameSync,\n\tunlinkSync,\n\twriteFileSync,\n} from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nexport type PromptPresetKind = 'base' | 'layer';\nexport type PromptPresetSource = 'builtin' | 'user' | 'project';\n\nexport interface PromptPreset {\n\tkind?: PromptPresetKind;\n\tdescription?: string;\n\tinstructions: string;\n}\n\nexport type PromptPresetMap = Record<string, PromptPreset>;\n\nexport interface LoadedPromptPreset extends PromptPreset {\n\tname: string;\n\tkind: PromptPresetKind;\n\tsource: PromptPresetSource;\n}\n\nexport interface PromptPresetState {\n\tbase_name: string | null;\n\tlayer_names: string[];\n}\n\ninterface PersistedPromptPresetStates {\n\tversion: number;\n\tprojects: Record<string, PromptPresetState>;\n}\n\nconst PRESET_STATE_TYPE = 'prompt-preset-state';\nconst ENABLED = '[x]';\nconst DISABLED = '[ ]';\nconst SELECTED = '(x)';\nconst UNSELECTED = '( )';\nconst NONE_BASE_ID = '__base_none__';\n\nexport const DEFAULT_PROMPT_PRESETS: PromptPresetMap = {\n\tterse: {\n\t\tkind: 'base',\n\t\tdescription: 'Short, direct, no fluff',\n\t\tinstructions:\n\t\t\t\"Be concise and direct. Default to the shortest response that fully solves the user's request. No purple prose, no filler, no repetitive caveats. Prefer a short paragraph or a few bullets. Only include extra detail when it materially affects the decision, implementation, or next step.\",\n\t},\n\tstandard: {\n\t\tkind: 'base',\n\t\tdescription: 'Clear and concise with key context',\n\t\tinstructions:\n\t\t\t'Be clear, direct, and concise. Include only the reasoning and implementation details that matter. Avoid filler, grandstanding, and ornamental language. Use bullets when they improve scanability.',\n\t},\n\tdetailed: {\n\t\tkind: 'base',\n\t\tdescription: 'More explanation when nuance matters',\n\t\tinstructions:\n\t\t\t'Be thorough when the task is complex or tradeoffs matter, but stay practical. Explain only the details that help the user decide, verify, or implement. Avoid purple prose and unnecessary scene-setting.',\n\t},\n\t'no-purple-prose': {\n\t\tkind: 'layer',\n\t\tdescription: 'Strip out ornamental language',\n\t\tinstructions:\n\t\t\t'Do not use purple prose, flourish, motivational filler, or theatrical transitions. Prefer plain language and concrete statements.',\n\t},\n\tbullets: {\n\t\tkind: 'layer',\n\t\tdescription: 'Prefer short bullets when useful',\n\t\tinstructions:\n\t\t\t'When presenting options, findings, or steps, prefer short bullet lists over long paragraphs.',\n\t},\n\t'clarify-first': {\n\t\tkind: 'layer',\n\t\tdescription:\n\t\t\t'Ask brief clarifying questions when requirements are ambiguous',\n\t\tinstructions:\n\t\t\t'If the request is materially ambiguous, ask the minimum clarifying question(s) needed before proceeding. Do not ask unnecessary questions.',\n\t},\n\t'include-risks': {\n\t\tkind: 'layer',\n\t\tdescription: 'Call out notable risks or tradeoffs',\n\t\tinstructions:\n\t\t\t'When making a recommendation or implementation plan, briefly mention the key risk, tradeoff, or caveat if one materially matters.',\n\t},\n};\n\nexport function normalize_prompt_presets(\n\tinput: unknown,\n): PromptPresetMap {\n\tif (!input || typeof input !== 'object') return {};\n\n\tconst normalized: PromptPresetMap = {};\n\tfor (const [raw_name, raw_value] of Object.entries(input)) {\n\t\tconst name = raw_name.trim();\n\t\tif (!name) continue;\n\n\t\tif (typeof raw_value === 'string') {\n\t\t\tnormalized[name] = {\n\t\t\t\tkind: 'base',\n\t\t\t\tinstructions: raw_value,\n\t\t\t};\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!raw_value || typeof raw_value !== 'object') continue;\n\t\tconst candidate = raw_value as {\n\t\t\tkind?: unknown;\n\t\t\tdescription?: unknown;\n\t\t\tinstructions?: unknown;\n\t\t};\n\t\tif (typeof candidate.instructions !== 'string') continue;\n\n\t\tnormalized[name] = {\n\t\t\tinstructions: candidate.instructions,\n\t\t\t...(candidate.kind === 'layer'\n\t\t\t\t? { kind: 'layer' as const }\n\t\t\t\t: {}),\n\t\t\t...(typeof candidate.description === 'string'\n\t\t\t\t? { description: candidate.description }\n\t\t\t\t: {}),\n\t\t};\n\t}\n\n\treturn normalized;\n}\n\nexport function merge_prompt_presets(\n\t...sources: PromptPresetMap[]\n): PromptPresetMap {\n\treturn Object.assign({}, ...sources);\n}\n\nfunction to_loaded_prompt_presets(\n\tpresets: PromptPresetMap,\n\tsource: PromptPresetSource,\n): Record<string, LoadedPromptPreset> {\n\treturn Object.fromEntries(\n\t\tObject.entries(presets).map(([name, preset]) => [\n\t\t\tname,\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tkind: preset.kind === 'layer' ? 'layer' : 'base',\n\t\t\t\tsource,\n\t\t\t\t...preset,\n\t\t\t},\n\t\t]),\n\t);\n}\n\nfunction get_global_presets_path(): string {\n\treturn join(getAgentDir(), 'presets.json');\n}\n\nfunction get_project_presets_path(cwd: string): string {\n\treturn join(cwd, '.pi', 'presets.json');\n}\n\nfunction get_persisted_prompt_state_path(): string {\n\treturn join(getAgentDir(), 'prompt-preset-state.json');\n}\n\nfunction read_prompt_presets_file(path: string): PromptPresetMap {\n\tif (!existsSync(path)) return {};\n\n\ttry {\n\t\treturn normalize_prompt_presets(\n\t\t\tJSON.parse(readFileSync(path, 'utf-8')),\n\t\t);\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nexport function load_prompt_presets(\n\tcwd: string,\n): Record<string, LoadedPromptPreset> {\n\treturn Object.assign(\n\t\t{},\n\t\tto_loaded_prompt_presets(DEFAULT_PROMPT_PRESETS, 'builtin'),\n\t\tto_loaded_prompt_presets(\n\t\t\tread_prompt_presets_file(get_global_presets_path()),\n\t\t\t'user',\n\t\t),\n\t\tto_loaded_prompt_presets(\n\t\t\tread_prompt_presets_file(get_project_presets_path(cwd)),\n\t\t\t'project',\n\t\t),\n\t);\n}\n\nfunction sort_prompt_presets(\n\tpresets: PromptPresetMap,\n): PromptPresetMap {\n\treturn Object.fromEntries(\n\t\tObject.entries(presets).sort(([a], [b]) => a.localeCompare(b)),\n\t);\n}\n\nexport function save_project_prompt_presets(\n\tcwd: string,\n\tpresets: PromptPresetMap,\n): string {\n\tconst path = get_project_presets_path(cwd);\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n\n\tconst tmp = `${path}.tmp-${Date.now()}`;\n\twriteFileSync(\n\t\ttmp,\n\t\tJSON.stringify(sort_prompt_presets(presets), null, '\\t') + '\\n',\n\t\t{ mode: 0o600 },\n\t);\n\trenameSync(tmp, path);\n\treturn path;\n}\n\nexport function remove_project_prompt_preset(\n\tcwd: string,\n\tname: string,\n): {\n\tremoved: boolean;\n\tpath: string;\n\tremaining: number;\n} {\n\tconst path = get_project_presets_path(cwd);\n\tconst project_presets = read_prompt_presets_file(path);\n\tif (!(name in project_presets)) {\n\t\treturn {\n\t\t\tremoved: false,\n\t\t\tpath,\n\t\t\tremaining: Object.keys(project_presets).length,\n\t\t};\n\t}\n\n\tdelete project_presets[name];\n\tconst remaining = Object.keys(project_presets).length;\n\tif (remaining === 0) {\n\t\tif (existsSync(path)) {\n\t\t\tunlinkSync(path);\n\t\t}\n\t\treturn { removed: true, path, remaining };\n\t}\n\n\tsave_project_prompt_presets(cwd, project_presets);\n\treturn { removed: true, path, remaining };\n}\n\nfunction normalize_prompt_preset_state(\n\tinput: unknown,\n): PromptPresetState | undefined {\n\tif (!input || typeof input !== 'object') return undefined;\n\n\tconst candidate = input as {\n\t\tbase_name?: unknown;\n\t\tlayer_names?: unknown;\n\t};\n\tconst base_name =\n\t\ttypeof candidate.base_name === 'string' &&\n\t\tcandidate.base_name.trim()\n\t\t\t? candidate.base_name.trim()\n\t\t\t: null;\n\tconst layer_names = Array.isArray(candidate.layer_names)\n\t\t? [\n\t\t\t\t...new Set(\n\t\t\t\t\tcandidate.layer_names\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t(value): value is string =>\n\t\t\t\t\t\t\t\ttypeof value === 'string' && value.trim().length > 0,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.map((value) => value.trim()),\n\t\t\t\t),\n\t\t\t].sort()\n\t\t: [];\n\n\treturn {\n\t\tbase_name,\n\t\tlayer_names,\n\t};\n}\n\nfunction read_persisted_prompt_states(\n\tpath = get_persisted_prompt_state_path(),\n): PersistedPromptPresetStates {\n\tif (!existsSync(path)) {\n\t\treturn { version: 1, projects: {} };\n\t}\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(path, 'utf-8')) as {\n\t\t\tversion?: unknown;\n\t\t\tprojects?: unknown;\n\t\t};\n\t\tconst raw_projects =\n\t\t\tparsed.projects && typeof parsed.projects === 'object'\n\t\t\t\t? parsed.projects\n\t\t\t\t: {};\n\t\tconst projects: Record<string, PromptPresetState> = {};\n\t\tfor (const [cwd, value] of Object.entries(raw_projects)) {\n\t\t\tconst normalized = normalize_prompt_preset_state(value);\n\t\t\tif (!normalized) continue;\n\t\t\tprojects[cwd] = normalized;\n\t\t}\n\t\treturn {\n\t\t\tversion:\n\t\t\t\ttypeof parsed.version === 'number' ? parsed.version : 1,\n\t\t\tprojects,\n\t\t};\n\t} catch {\n\t\treturn { version: 1, projects: {} };\n\t}\n}\n\nexport function load_persisted_prompt_state(\n\tcwd: string,\n\tpath = get_persisted_prompt_state_path(),\n): PromptPresetState | undefined {\n\treturn read_persisted_prompt_states(path).projects[cwd];\n}\n\nexport function save_persisted_prompt_state(\n\tcwd: string,\n\tstate: PromptPresetState,\n\tpath = get_persisted_prompt_state_path(),\n): string {\n\tconst persisted = read_persisted_prompt_states(path);\n\tpersisted.projects[cwd] = normalize_prompt_preset_state(state) ?? {\n\t\tbase_name: null,\n\t\tlayer_names: [],\n\t};\n\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n\n\tconst tmp = `${path}.tmp-${Date.now()}`;\n\twriteFileSync(\n\t\ttmp,\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tversion: 1,\n\t\t\t\tprojects: Object.fromEntries(\n\t\t\t\t\tObject.entries(persisted.projects).sort(([a], [b]) =>\n\t\t\t\t\t\ta.localeCompare(b),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t},\n\t\t\tnull,\n\t\t\t'\\t',\n\t\t) + '\\n',\n\t\t{ mode: 0o600 },\n\t);\n\trenameSync(tmp, path);\n\treturn path;\n}\n\nfunction get_last_preset_state(\n\tctx: ExtensionContext,\n): PromptPresetState | undefined {\n\tconst entries = ctx.sessionManager.getEntries();\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i] as {\n\t\t\ttype?: string;\n\t\t\tcustomType?: string;\n\t\t\tdata?: PromptPresetState;\n\t\t};\n\t\tif (\n\t\t\tentry.type === 'custom' &&\n\t\t\tentry.customType === PRESET_STATE_TYPE &&\n\t\t\tentry.data\n\t\t) {\n\t\t\treturn entry.data;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction sets_equal(\n\ta: ReadonlySet<string>,\n\tb: ReadonlySet<string>,\n): boolean {\n\tif (a.size !== b.size) return false;\n\tfor (const value of a) {\n\t\tif (!b.has(value)) return false;\n\t}\n\treturn true;\n}\n\nfunction get_prompt_source_label(source: PromptPresetSource): string {\n\tswitch (source) {\n\t\tcase 'builtin':\n\t\t\treturn 'built-in';\n\t\tcase 'user':\n\t\t\treturn 'user';\n\t\tcase 'project':\n\t\t\treturn 'project';\n\t}\n}\n\nfunction list_base_presets(\n\tpresets: Record<string, LoadedPromptPreset>,\n): LoadedPromptPreset[] {\n\treturn Object.values(presets)\n\t\t.filter((preset) => preset.kind === 'base')\n\t\t.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction list_layer_presets(\n\tpresets: Record<string, LoadedPromptPreset>,\n): LoadedPromptPreset[] {\n\treturn Object.values(presets)\n\t\t.filter((preset) => preset.kind === 'layer')\n\t\t.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction format_summary(\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n\tpresets: Record<string, LoadedPromptPreset>,\n): string {\n\tconst lines = [`Base: ${active_base_name ?? '(none)'}`];\n\n\tconst layer_names = [...active_layers].sort();\n\tif (layer_names.length === 0) {\n\t\tlines.push('Layers: (none)');\n\t} else {\n\t\tlines.push('Layers:');\n\t\tfor (const name of layer_names) {\n\t\t\tconst preset = presets[name];\n\t\t\tconst description = preset?.description\n\t\t\t\t? ` — ${preset.description}`\n\t\t\t\t: '';\n\t\t\tlines.push(`- ${name}${description}`);\n\t\t}\n\t}\n\n\treturn lines.join('\\n');\n}\n\nfunction format_active_details(\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n\tpresets: Record<string, LoadedPromptPreset>,\n): string {\n\tconst parts: string[] = [];\n\n\tif (active_base_name) {\n\t\tconst base = presets[active_base_name];\n\t\tif (base) {\n\t\t\tparts.push(`Base: ${base.name}`);\n\t\t\tif (base.description)\n\t\t\t\tparts.push(`Description: ${base.description}`);\n\t\t\tparts.push(`Source: ${get_prompt_source_label(base.source)}`);\n\t\t\tparts.push('', base.instructions.trim());\n\t\t}\n\t}\n\n\tconst layer_names = [...active_layers].sort();\n\tif (layer_names.length > 0) {\n\t\tif (parts.length > 0) parts.push('', '---', '');\n\t\tparts.push('Layers:');\n\t\tfor (const name of layer_names) {\n\t\t\tconst layer = presets[name];\n\t\t\tif (!layer) continue;\n\t\t\tparts.push(\n\t\t\t\t`- ${layer.name} (${get_prompt_source_label(layer.source)})`,\n\t\t\t);\n\t\t\tif (layer.description) parts.push(` ${layer.description}`);\n\t\t}\n\t}\n\n\treturn parts.join('\\n') || 'No preset or layers active';\n}\n\nfunction get_footer_prompt_status(\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): string | undefined {\n\tif (!active_base_name && active_layers.size === 0) {\n\t\treturn undefined;\n\t}\n\n\tconst label = active_base_name ?? 'none';\n\tconst layer_suffix =\n\t\tactive_layers.size > 0 ? ` +${active_layers.size}` : '';\n\treturn `prompt:${label}${layer_suffix}`;\n}\n\nfunction sanitize_status_text(text: string): string {\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, ' ')\n\t\t.replace(/ +/g, ' ')\n\t\t.trim();\n}\n\nfunction format_token_count(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\nfunction get_current_thinking_level(ctx: ExtensionContext): string {\n\tconst entries = ctx.sessionManager.getEntries();\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i] as {\n\t\t\ttype?: string;\n\t\t\tthinkingLevel?: string;\n\t\t};\n\t\tif (\n\t\t\tentry.type === 'thinking_level_change' &&\n\t\t\ttypeof entry.thinkingLevel === 'string'\n\t\t) {\n\t\t\treturn entry.thinkingLevel;\n\t\t}\n\t}\n\treturn ctx.model?.reasoning ? 'high' : 'off';\n}\n\nfunction render_footer_lines(\n\tctx: ExtensionContext,\n\ttheme: ExtensionContext['ui']['theme'],\n\tfooter_data: ReadonlyFooterDataProvider,\n\twidth: number,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): string[] {\n\tlet total_input = 0;\n\tlet total_output = 0;\n\tlet total_cache_read = 0;\n\tlet total_cache_write = 0;\n\tlet total_cost = 0;\n\tfor (const entry of ctx.sessionManager.getEntries()) {\n\t\tif (\n\t\t\tentry.type === 'message' &&\n\t\t\tentry.message.role === 'assistant'\n\t\t) {\n\t\t\ttotal_input += entry.message.usage.input;\n\t\t\ttotal_output += entry.message.usage.output;\n\t\t\ttotal_cache_read += entry.message.usage.cacheRead;\n\t\t\ttotal_cache_write += entry.message.usage.cacheWrite;\n\t\t\ttotal_cost += entry.message.usage.cost.total;\n\t\t}\n\t}\n\n\tconst context_usage = ctx.getContextUsage();\n\tconst context_window =\n\t\tcontext_usage?.contextWindow ?? ctx.model?.contextWindow ?? 0;\n\tconst context_percent_value = context_usage?.percent ?? 0;\n\tconst context_percent =\n\t\tcontext_usage?.percent !== null\n\t\t\t? context_percent_value.toFixed(1)\n\t\t\t: '?';\n\n\tlet pwd = ctx.cwd;\n\tconst home = process.env.HOME || process.env.USERPROFILE;\n\tif (home && pwd.startsWith(home)) {\n\t\tpwd = `~${pwd.slice(home.length)}`;\n\t}\n\n\tconst branch = footer_data.getGitBranch();\n\tif (branch) {\n\t\tpwd = `${pwd} (${branch})`;\n\t}\n\n\tconst session_name = ctx.sessionManager.getSessionName();\n\tif (session_name) {\n\t\tpwd = `${pwd} • ${session_name}`;\n\t}\n\n\tconst stats_parts: string[] = [];\n\tif (total_input)\n\t\tstats_parts.push(`↑${format_token_count(total_input)}`);\n\tif (total_output)\n\t\tstats_parts.push(`↓${format_token_count(total_output)}`);\n\tif (total_cache_read)\n\t\tstats_parts.push(`R${format_token_count(total_cache_read)}`);\n\tif (total_cache_write)\n\t\tstats_parts.push(`W${format_token_count(total_cache_write)}`);\n\n\tconst using_subscription = ctx.model\n\t\t? ctx.modelRegistry.isUsingOAuth(ctx.model)\n\t\t: false;\n\tif (total_cost || using_subscription) {\n\t\tstats_parts.push(\n\t\t\t`$${total_cost.toFixed(3)}${using_subscription ? ' (sub)' : ''}`,\n\t\t);\n\t}\n\n\tconst context_percent_display =\n\t\tcontext_percent === '?'\n\t\t\t? `?/${format_token_count(context_window)}`\n\t\t\t: `${context_percent}%/${format_token_count(context_window)}`;\n\tlet context_percent_str = context_percent_display;\n\tif (context_percent_value > 90) {\n\t\tcontext_percent_str = theme.fg('error', context_percent_display);\n\t} else if (context_percent_value > 70) {\n\t\tcontext_percent_str = theme.fg(\n\t\t\t'warning',\n\t\t\tcontext_percent_display,\n\t\t);\n\t}\n\tstats_parts.push(context_percent_str);\n\n\tlet stats_left = stats_parts.join(' ');\n\tlet stats_left_width = visibleWidth(stats_left);\n\tif (stats_left_width > width) {\n\t\tstats_left = truncateToWidth(stats_left, width, '...');\n\t\tstats_left_width = visibleWidth(stats_left);\n\t}\n\n\tconst model_name = ctx.model?.id || 'no-model';\n\tconst thinking_level = get_current_thinking_level(ctx);\n\tlet right_side_without_provider = model_name;\n\tif (ctx.model?.reasoning) {\n\t\tright_side_without_provider =\n\t\t\tthinking_level === 'off'\n\t\t\t\t? `${model_name} • thinking off`\n\t\t\t\t: `${model_name} • ${thinking_level}`;\n\t}\n\n\tlet right_side = right_side_without_provider;\n\tif (footer_data.getAvailableProviderCount() > 1 && ctx.model) {\n\t\tright_side = `(${ctx.model.provider}) ${right_side_without_provider}`;\n\t\tif (stats_left_width + 2 + visibleWidth(right_side) > width) {\n\t\t\tright_side = right_side_without_provider;\n\t\t}\n\t}\n\n\tconst right_side_width = visibleWidth(right_side);\n\tconst total_needed = stats_left_width + 2 + right_side_width;\n\tlet stats_line: string;\n\tif (total_needed <= width) {\n\t\tconst padding = ' '.repeat(\n\t\t\twidth - stats_left_width - right_side_width,\n\t\t);\n\t\tstats_line = stats_left + padding + right_side;\n\t} else {\n\t\tconst available_for_right = width - stats_left_width - 2;\n\t\tif (available_for_right > 0) {\n\t\t\tconst truncated_right = truncateToWidth(\n\t\t\t\tright_side,\n\t\t\t\tavailable_for_right,\n\t\t\t\t'',\n\t\t\t);\n\t\t\tconst truncated_right_width = visibleWidth(truncated_right);\n\t\t\tconst padding = ' '.repeat(\n\t\t\t\tMath.max(0, width - stats_left_width - truncated_right_width),\n\t\t\t);\n\t\t\tstats_line = stats_left + padding + truncated_right;\n\t\t} else {\n\t\t\tstats_line = stats_left;\n\t\t}\n\t}\n\n\tconst dim_stats_left = theme.fg('dim', stats_left);\n\tconst remainder = stats_line.slice(stats_left.length);\n\tconst dim_remainder = theme.fg('dim', remainder);\n\tconst lines = [\n\t\ttruncateToWidth(\n\t\t\ttheme.fg('dim', pwd),\n\t\t\twidth,\n\t\t\ttheme.fg('dim', '...'),\n\t\t),\n\t\tdim_stats_left + dim_remainder,\n\t];\n\n\tconst prompt_status = get_footer_prompt_status(\n\t\tactive_base_name,\n\t\tactive_layers,\n\t);\n\tif (prompt_status) {\n\t\tconst themed_status = theme.fg('dim', prompt_status);\n\t\tconst status_width = visibleWidth(themed_status);\n\t\tconst aligned_status =\n\t\t\tstatus_width >= width\n\t\t\t\t? truncateToWidth(\n\t\t\t\t\t\tthemed_status,\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\ttheme.fg('dim', '...'),\n\t\t\t\t\t)\n\t\t\t\t: `${' '.repeat(width - status_width)}${themed_status}`;\n\t\tlines.push(aligned_status);\n\t}\n\n\tconst other_statuses = Array.from(\n\t\tfooter_data.getExtensionStatuses().entries(),\n\t)\n\t\t.filter(([key]) => key !== 'preset')\n\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t.map(([, text]) => sanitize_status_text(text));\n\tif (other_statuses.length > 0) {\n\t\tlines.push(\n\t\t\ttruncateToWidth(\n\t\t\t\tother_statuses.join(' '),\n\t\t\t\twidth,\n\t\t\t\ttheme.fg('dim', '...'),\n\t\t\t),\n\t\t);\n\t}\n\n\treturn lines;\n}\n\nfunction set_status(\n\tctx: ExtensionContext,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): void {\n\tctx.ui.setStatus('preset', undefined);\n\tif (!ctx.hasUI) return;\n\tctx.ui.setFooter((tui, theme, footer_data) => {\n\t\tconst unsubscribe = footer_data.onBranchChange(() =>\n\t\t\ttui.requestRender(),\n\t\t);\n\t\treturn {\n\t\t\tdispose: unsubscribe,\n\t\t\tinvalidate() {},\n\t\t\trender(width: number) {\n\t\t\t\treturn render_footer_lines(\n\t\t\t\t\tctx,\n\t\t\t\t\ttheme,\n\t\t\t\t\tfooter_data,\n\t\t\t\t\twidth,\n\t\t\t\t\tactive_base_name,\n\t\t\t\t\tactive_layers,\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t});\n}\n\nfunction persist_state(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): void {\n\tconst state = {\n\t\tbase_name: active_base_name ?? null,\n\t\tlayer_names: [...active_layers].sort(),\n\t};\n\tpi.appendEntry(PRESET_STATE_TYPE, state);\n\tsave_persisted_prompt_state(ctx.cwd, state);\n}\n\nfunction normalize_active_state(\n\tpresets: Record<string, LoadedPromptPreset>,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): {\n\tactive_base_name: string | undefined;\n\tactive_layers: Set<string>;\n} {\n\tconst next_base_name =\n\t\tactive_base_name && presets[active_base_name]?.kind === 'base'\n\t\t\t? active_base_name\n\t\t\t: undefined;\n\tconst next_layers = new Set(\n\t\t[...active_layers].filter(\n\t\t\t(name) => presets[name]?.kind === 'layer',\n\t\t),\n\t);\n\treturn {\n\t\tactive_base_name: next_base_name,\n\t\tactive_layers: next_layers,\n\t};\n}\n\nfunction parse_preset_flag(flag: string): string[] {\n\treturn flag\n\t\t.split(',')\n\t\t.map((item) => item.trim())\n\t\t.filter(Boolean);\n}\n\nfunction is_subcommand(command: string): boolean {\n\treturn [\n\t\t'list',\n\t\t'show',\n\t\t'clear',\n\t\t'edit',\n\t\t'delete',\n\t\t'reset',\n\t\t'reload',\n\t\t'base',\n\t\t'enable',\n\t\t'disable',\n\t\t'toggle',\n\t].includes(command);\n}\n\nexport default async function prompt_presets(pi: ExtensionAPI) {\n\tlet presets: Record<string, LoadedPromptPreset> = {};\n\tlet active_base_name: string | undefined;\n\tlet active_layers = new Set<string>();\n\n\tfunction get_base(\n\t\tname: string | undefined,\n\t): LoadedPromptPreset | undefined {\n\t\treturn name ? presets[name] : undefined;\n\t}\n\n\tfunction get_layer(name: string): LoadedPromptPreset | undefined {\n\t\tconst preset = presets[name];\n\t\treturn preset?.kind === 'layer' ? preset : undefined;\n\t}\n\n\tfunction commit_state(\n\t\tctx: ExtensionContext,\n\t\tnext_base_name: string | undefined,\n\t\tnext_layers: ReadonlySet<string>,\n\t\toptions?: { persist?: boolean; notify?: string },\n\t): void {\n\t\tactive_base_name = next_base_name;\n\t\tactive_layers = new Set(next_layers);\n\t\tset_status(ctx, active_base_name, active_layers);\n\t\tif (options?.persist !== false) {\n\t\t\tpersist_state(pi, ctx, active_base_name, active_layers);\n\t\t}\n\t\tif (options?.notify) {\n\t\t\tctx.ui.notify(options.notify, 'info');\n\t\t}\n\t}\n\n\tfunction activate_base(\n\t\tname: string | undefined,\n\t\tctx: ExtensionContext,\n\t\toptions?: { persist?: boolean },\n\t): boolean {\n\t\tif (!name) {\n\t\t\tcommit_state(ctx, undefined, active_layers, {\n\t\t\t\tpersist: options?.persist,\n\t\t\t\tnotify: 'Base preset cleared',\n\t\t\t});\n\t\t\treturn true;\n\t\t}\n\n\t\tconst preset = get_base(name);\n\t\tif (!preset) {\n\t\t\tctx.ui.notify(`Unknown base preset: ${name}`, 'warning');\n\t\t\treturn false;\n\t\t}\n\n\t\tcommit_state(ctx, preset.name, active_layers, {\n\t\t\tpersist: options?.persist,\n\t\t\tnotify: `Base preset \"${preset.name}\" activated`,\n\t\t});\n\t\treturn true;\n\t}\n\n\tfunction set_layer_enabled(\n\t\tname: string,\n\t\tenabled: boolean,\n\t\tctx: ExtensionContext,\n\t\toptions?: { persist?: boolean },\n\t): boolean {\n\t\tconst preset = get_layer(name);\n\t\tif (!preset) {\n\t\t\tctx.ui.notify(`Unknown prompt layer: ${name}`, 'warning');\n\t\t\treturn false;\n\t\t}\n\n\t\tconst next_layers = new Set(active_layers);\n\t\tif (enabled) {\n\t\t\tnext_layers.add(preset.name);\n\t\t} else {\n\t\t\tnext_layers.delete(preset.name);\n\t\t}\n\n\t\tcommit_state(ctx, active_base_name, next_layers, {\n\t\t\tpersist: options?.persist,\n\t\t\tnotify: enabled\n\t\t\t\t? `Layer \"${preset.name}\" enabled`\n\t\t\t\t: `Layer \"${preset.name}\" disabled`,\n\t\t});\n\t\treturn true;\n\t}\n\n\tfunction toggle_layer(\n\t\tname: string,\n\t\tctx: ExtensionContext,\n\t\toptions?: { persist?: boolean },\n\t): boolean {\n\t\treturn set_layer_enabled(\n\t\t\tname,\n\t\t\t!active_layers.has(name),\n\t\t\tctx,\n\t\t\toptions,\n\t\t);\n\t}\n\n\tasync function edit_preset(\n\t\tname: string,\n\t\tctx: ExtensionCommandContext,\n\t): Promise<void> {\n\t\tconst existing = presets[name];\n\t\tconst kind_choice = await ctx.ui.select('Preset kind', [\n\t\t\texisting?.kind === 'layer'\n\t\t\t\t? 'layer (current)'\n\t\t\t\t: 'base (current)',\n\t\t\texisting?.kind === 'layer' ? 'base' : 'layer',\n\t\t]);\n\t\tif (!kind_choice) return;\n\t\tconst kind: PromptPresetKind = kind_choice.startsWith('layer')\n\t\t\t? 'layer'\n\t\t\t: 'base';\n\n\t\tconst description = await ctx.ui.input(\n\t\t\t`Description for ${name}`,\n\t\t\texisting?.description ?? '',\n\t\t);\n\t\tif (description === undefined) return;\n\n\t\tconst instructions = await ctx.ui.editor(\n\t\t\t`Edit ${kind} preset: ${name}`,\n\t\t\texisting?.instructions ?? '',\n\t\t);\n\t\tif (instructions === undefined) return;\n\n\t\tsave_project_prompt_presets(ctx.cwd, {\n\t\t\t...read_prompt_presets_file(get_project_presets_path(ctx.cwd)),\n\t\t\t[name]: {\n\t\t\t\tkind,\n\t\t\t\tinstructions,\n\t\t\t\t...(description.trim()\n\t\t\t\t\t? { description: description.trim() }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t});\n\n\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\tconst normalized = normalize_active_state(\n\t\t\tpresets,\n\t\t\tactive_base_name,\n\t\t\tactive_layers,\n\t\t);\n\t\tactive_base_name = normalized.active_base_name;\n\t\tactive_layers = normalized.active_layers;\n\n\t\tif (kind === 'base') {\n\t\t\tactivate_base(name, ctx);\n\t\t} else {\n\t\t\tset_layer_enabled(name, true, ctx);\n\t\t}\n\t\tctx.ui.notify(\n\t\t\t`Saved preset \"${name}\" to ${get_project_presets_path(ctx.cwd)}`,\n\t\t\t'info',\n\t\t);\n\t}\n\n\tfunction remove_custom_preset(\n\t\tname: string,\n\t\tctx: ExtensionCommandContext,\n\t\tmode: 'delete' | 'reset',\n\t): void {\n\t\tconst result = remove_project_prompt_preset(ctx.cwd, name);\n\t\tif (!result.removed) {\n\t\t\tctx.ui.notify(\n\t\t\t\t`No project-local preset named \"${name}\" to ${mode}`,\n\t\t\t\t'warning',\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\tconst normalized = normalize_active_state(\n\t\t\tpresets,\n\t\t\tactive_base_name,\n\t\t\tactive_layers,\n\t\t);\n\t\tactive_base_name = normalized.active_base_name;\n\t\tactive_layers = normalized.active_layers;\n\t\tset_status(ctx, active_base_name, active_layers);\n\t\tpersist_state(pi, ctx, active_base_name, active_layers);\n\n\t\tconst fallback = presets[name];\n\t\tif (mode === 'reset' && fallback) {\n\t\t\tctx.ui.notify(\n\t\t\t\t`Reset \"${name}\" to ${get_prompt_source_label(fallback.source)} preset`,\n\t\t\t\t'info',\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tctx.ui.notify(\n\t\t\tresult.remaining === 0\n\t\t\t\t? `Removed \"${name}\" and deleted ${result.path}`\n\t\t\t\t: `Removed \"${name}\" from ${result.path}`,\n\t\t\t'info',\n\t\t);\n\t}\n\n\tasync function show_manager(\n\t\tctx: ExtensionCommandContext,\n\t): Promise<void> {\n\t\tconst base_presets = list_base_presets(presets);\n\t\tconst layer_presets = list_layer_presets(presets);\n\t\tif (base_presets.length === 0 && layer_presets.length === 0) {\n\t\t\tctx.ui.notify('No prompt presets available', 'warning');\n\t\t\treturn;\n\t\t}\n\n\t\tconst initial_base = active_base_name;\n\t\tconst initial_layers = new Set(active_layers);\n\t\tlet selected_base = active_base_name;\n\t\tconst enabled_layers = new Set(active_layers);\n\n\t\tconst items: SettingItem[] = [];\n\t\tconst base_ids = new Set<string>();\n\t\tconst layer_ids = new Set<string>();\n\n\t\titems.push({\n\t\t\tid: '__header_base__',\n\t\t\tlabel: `── Base presets (${base_presets.length + 1}) ──`,\n\t\t\tdescription: '',\n\t\t\tcurrentValue: '',\n\t\t});\n\t\titems.push({\n\t\t\tid: NONE_BASE_ID,\n\t\t\tlabel: '(none)',\n\t\t\tdescription: 'No active base preset',\n\t\t\tcurrentValue: UNSELECTED,\n\t\t\tvalues: [SELECTED, UNSELECTED],\n\t\t});\n\t\tbase_ids.add(NONE_BASE_ID);\n\n\t\tfor (const preset of base_presets) {\n\t\t\titems.push({\n\t\t\t\tid: preset.name,\n\t\t\t\tlabel: preset.name,\n\t\t\t\tdescription: [\n\t\t\t\t\t`${get_prompt_source_label(preset.source)} • ${preset.description ?? 'base preset'}`,\n\t\t\t\t].join('\\n'),\n\t\t\t\tcurrentValue: UNSELECTED,\n\t\t\t\tvalues: [SELECTED, UNSELECTED],\n\t\t\t});\n\t\t\tbase_ids.add(preset.name);\n\t\t}\n\n\t\titems.push({\n\t\t\tid: '__header_layers__',\n\t\t\tlabel: `── Prompt layers (${layer_presets.length}) ──`,\n\t\t\tdescription: '',\n\t\t\tcurrentValue: '',\n\t\t});\n\t\tfor (const preset of layer_presets) {\n\t\t\titems.push({\n\t\t\t\tid: preset.name,\n\t\t\t\tlabel: preset.name,\n\t\t\t\tdescription: [\n\t\t\t\t\t`${get_prompt_source_label(preset.source)} • ${preset.description ?? 'layer'}`,\n\t\t\t\t].join('\\n'),\n\t\t\t\tcurrentValue: DISABLED,\n\t\t\t\tvalues: [ENABLED, DISABLED],\n\t\t\t});\n\t\t\tlayer_ids.add(preset.name);\n\t\t}\n\n\t\tfunction sync_values() {\n\t\t\tfor (const item of items) {\n\t\t\t\tif (base_ids.has(item.id)) {\n\t\t\t\t\tconst is_selected =\n\t\t\t\t\t\t(item.id === NONE_BASE_ID && !selected_base) ||\n\t\t\t\t\t\titem.id === selected_base;\n\t\t\t\t\titem.currentValue = is_selected ? SELECTED : UNSELECTED;\n\t\t\t\t} else if (layer_ids.has(item.id)) {\n\t\t\t\t\titem.currentValue = enabled_layers.has(item.id)\n\t\t\t\t\t\t? ENABLED\n\t\t\t\t\t\t: DISABLED;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsync_values();\n\n\t\tawait ctx.ui.custom((tui, theme, _kb, done) => {\n\t\t\tconst list = new SettingsList(\n\t\t\t\titems,\n\t\t\t\tMath.min(Math.max(items.length + 4, 8), 24),\n\t\t\t\t{\n\t\t\t\t\tcursor: theme.fg('accent', '›'),\n\t\t\t\t\tlabel: (text, selected) => {\n\t\t\t\t\t\tif (text.startsWith('──') && text.endsWith('──')) {\n\t\t\t\t\t\t\treturn theme.fg('dim', theme.bold(text));\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn selected ? theme.fg('accent', text) : text;\n\t\t\t\t\t},\n\t\t\t\t\tvalue: (text, selected) => {\n\t\t\t\t\t\tconst color =\n\t\t\t\t\t\t\ttext === ENABLED || text === SELECTED\n\t\t\t\t\t\t\t\t? ('success' as const)\n\t\t\t\t\t\t\t\t: ('dim' as const);\n\t\t\t\t\t\tconst rendered = theme.fg(color, text);\n\t\t\t\t\t\treturn selected\n\t\t\t\t\t\t\t? theme.bold(theme.fg('accent', rendered))\n\t\t\t\t\t\t\t: rendered;\n\t\t\t\t\t},\n\t\t\t\t\tdescription: (text) => theme.fg('muted', text),\n\t\t\t\t\thint: (text) => theme.fg('dim', text),\n\t\t\t\t},\n\t\t\t\t(id, new_value) => {\n\t\t\t\t\tif (id.startsWith('__header_')) return;\n\n\t\t\t\t\tif (base_ids.has(id)) {\n\t\t\t\t\t\tselected_base =\n\t\t\t\t\t\t\tnew_value === SELECTED && id !== NONE_BASE_ID\n\t\t\t\t\t\t\t\t? id\n\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\tsync_values();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (layer_ids.has(id)) {\n\t\t\t\t\t\tif (new_value === ENABLED) {\n\t\t\t\t\t\t\tenabled_layers.add(id);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tenabled_layers.delete(id);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsync_values();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t() => done(undefined),\n\t\t\t\t{ enableSearch: true },\n\t\t\t);\n\n\t\t\tconst container = new Container();\n\t\t\tcontainer.addChild({\n\t\t\t\trender: () => [\n\t\t\t\t\ttheme.fg('accent', theme.bold('Prompt presets')),\n\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t'muted',\n\t\t\t\t\t\t`base: ${selected_base ?? '(none)'} • ${enabled_layers.size} layer(s) enabled`,\n\t\t\t\t\t),\n\t\t\t\t\t'',\n\t\t\t\t],\n\t\t\t\tinvalidate: () => {},\n\t\t\t});\n\t\t\tcontainer.addChild({\n\t\t\t\trender(width: number) {\n\t\t\t\t\treturn list.render(width);\n\t\t\t\t},\n\t\t\t\tinvalidate() {\n\t\t\t\t\tlist.invalidate();\n\t\t\t\t},\n\t\t\t});\n\t\t\tcontainer.addChild(\n\t\t\t\tnew Text(\n\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t'dim',\n\t\t\t\t\t\t'search filters • enter toggles • esc close',\n\t\t\t\t\t),\n\t\t\t\t\t0,\n\t\t\t\t\t1,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\trender(width: number) {\n\t\t\t\t\treturn container.render(width);\n\t\t\t\t},\n\t\t\t\tinvalidate() {\n\t\t\t\t\tcontainer.invalidate();\n\t\t\t\t},\n\t\t\t\thandleInput(data: string) {\n\t\t\t\t\tlist.handleInput(data);\n\t\t\t\t\ttui.requestRender();\n\t\t\t\t},\n\t\t\t};\n\t\t});\n\n\t\tif (\n\t\t\tselected_base !== initial_base ||\n\t\t\t!sets_equal(initial_layers, enabled_layers)\n\t\t) {\n\t\t\tcommit_state(ctx, selected_base, enabled_layers, {\n\t\t\t\tnotify: 'Updated prompt preset selection',\n\t\t\t});\n\t\t}\n\t}\n\n\tpi.registerFlag('preset', {\n\t\tdescription:\n\t\t\t'Activate prompt config on startup. Accepts a base preset or comma-separated preset/layer names.',\n\t\ttype: 'string',\n\t});\n\n\tpi.registerCommand('preset', {\n\t\tdescription: 'Manage base prompt presets and prompt layers',\n\t\tgetArgumentCompletions: (prefix) => {\n\t\t\tconst trimmed = prefix.trim();\n\t\t\tconst parts = trimmed ? trimmed.split(/\\s+/) : [];\n\t\t\tconst base_names = list_base_presets(presets).map(\n\t\t\t\t(preset) => preset.name,\n\t\t\t);\n\t\t\tconst layer_names = list_layer_presets(presets).map(\n\t\t\t\t(preset) => preset.name,\n\t\t\t);\n\t\t\tconst all_names = [...base_names, ...layer_names];\n\n\t\t\tif (parts.length <= 1) {\n\t\t\t\tconst query = parts[0] ?? '';\n\t\t\t\tconst subcommands = [\n\t\t\t\t\t'list',\n\t\t\t\t\t'show',\n\t\t\t\t\t'clear',\n\t\t\t\t\t'edit',\n\t\t\t\t\t'delete',\n\t\t\t\t\t'reset',\n\t\t\t\t\t'reload',\n\t\t\t\t\t'base',\n\t\t\t\t\t'enable',\n\t\t\t\t\t'disable',\n\t\t\t\t\t'toggle',\n\t\t\t\t];\n\t\t\t\treturn [\n\t\t\t\t\t...subcommands\n\t\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t\t.map((item) => ({ value: item, label: item })),\n\t\t\t\t\t...all_names\n\t\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t\t.map((item) => ({ value: item, label: item })),\n\t\t\t\t];\n\t\t\t}\n\n\t\t\tconst command = parts[0];\n\t\t\tconst query = parts.slice(1).join(' ');\n\t\t\tif (command === 'base') {\n\t\t\t\treturn base_names\n\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t.map((item) => ({ value: `base ${item}`, label: item }));\n\t\t\t}\n\t\t\tif (['enable', 'disable', 'toggle'].includes(command)) {\n\t\t\t\treturn layer_names\n\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t.map((item) => ({\n\t\t\t\t\t\tvalue: `${command} ${item}`,\n\t\t\t\t\t\tlabel: item,\n\t\t\t\t\t}));\n\t\t\t}\n\t\t\tif (command === 'edit') {\n\t\t\t\treturn all_names\n\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t.map((item) => ({ value: `edit ${item}`, label: item }));\n\t\t\t}\n\t\t\tif (['delete', 'reset'].includes(command)) {\n\t\t\t\treturn all_names\n\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t.map((item) => ({\n\t\t\t\t\t\tvalue: `${command} ${item}`,\n\t\t\t\t\t\tlabel: item,\n\t\t\t\t\t}));\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\thandler: async (args, ctx) => {\n\t\t\tconst trimmed = args.trim();\n\t\t\tif (!trimmed) {\n\t\t\t\tif (ctx.hasUI) {\n\t\t\t\t\tawait show_manager(ctx);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\tformat_summary(active_base_name, active_layers, presets),\n\t\t\t\t\t'info',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst [first, ...rest] = trimmed.split(/\\s+/);\n\t\t\tconst arg = rest.join(' ').trim();\n\n\t\t\tswitch (first) {\n\t\t\t\tcase 'list':\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\tformat_summary(active_base_name, active_layers, presets),\n\t\t\t\t\t\t'info',\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'show':\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\tformat_active_details(\n\t\t\t\t\t\t\tactive_base_name,\n\t\t\t\t\t\t\tactive_layers,\n\t\t\t\t\t\t\tpresets,\n\t\t\t\t\t\t),\n\t\t\t\t\t\t'info',\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'clear':\n\t\t\t\t\tcommit_state(ctx, undefined, new Set(), {\n\t\t\t\t\t\tnotify: 'Cleared base preset and prompt layers',\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\tcase 'reload': {\n\t\t\t\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\t\t\t\tconst normalized = normalize_active_state(\n\t\t\t\t\t\tpresets,\n\t\t\t\t\t\tactive_base_name,\n\t\t\t\t\t\tactive_layers,\n\t\t\t\t\t);\n\t\t\t\t\tactive_base_name = normalized.active_base_name;\n\t\t\t\t\tactive_layers = normalized.active_layers;\n\t\t\t\t\tset_status(ctx, active_base_name, active_layers);\n\t\t\t\t\tctx.ui.notify('Reloaded prompt presets', 'info');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcase 'base':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify('Usage: /preset base <name>', 'warning');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tactivate_base(arg, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'enable':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify('Usage: /preset enable <layer>', 'warning');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tset_layer_enabled(arg, true, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'disable':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /preset disable <layer>',\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tset_layer_enabled(arg, false, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'toggle':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify('Usage: /preset toggle <layer>', 'warning');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\ttoggle_layer(arg, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'edit':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify('Usage: /preset edit <name>', 'warning');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tawait edit_preset(arg, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'delete':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify('Usage: /preset delete <name>', 'warning');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tremove_custom_preset(arg, ctx, 'delete');\n\t\t\t\t\treturn;\n\t\t\t\tcase 'reset':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify('Usage: /preset reset <name>', 'warning');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tremove_custom_preset(arg, ctx, 'reset');\n\t\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (is_subcommand(first)) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Unsupported preset command: ${first}`,\n\t\t\t\t\t'warning',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst preset = presets[trimmed];\n\t\t\tif (!preset) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Unknown preset or layer: ${trimmed}`,\n\t\t\t\t\t'warning',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (preset.kind === 'base') {\n\t\t\t\tactivate_base(preset.name, ctx);\n\t\t\t} else {\n\t\t\t\ttoggle_layer(preset.name, ctx);\n\t\t\t}\n\t\t},\n\t});\n\n\tpi.on('session_start', async (_event, ctx) => {\n\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\tactive_base_name = undefined;\n\t\tactive_layers = new Set();\n\n\t\tconst preset_flag = pi.getFlag('preset');\n\t\tif (typeof preset_flag === 'string' && preset_flag.trim()) {\n\t\t\tfor (const name of parse_preset_flag(preset_flag)) {\n\t\t\t\tconst preset = presets[name];\n\t\t\t\tif (!preset) continue;\n\t\t\t\tif (preset.kind === 'base') {\n\t\t\t\t\tactive_base_name = name;\n\t\t\t\t} else {\n\t\t\t\t\tactive_layers.add(name);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst normalized = normalize_active_state(\n\t\t\t\tpresets,\n\t\t\t\tactive_base_name,\n\t\t\t\tactive_layers,\n\t\t\t);\n\t\t\tactive_base_name = normalized.active_base_name;\n\t\t\tactive_layers = normalized.active_layers;\n\t\t\tset_status(ctx, active_base_name, active_layers);\n\t\t\treturn;\n\t\t}\n\n\t\tconst restored =\n\t\t\tget_last_preset_state(ctx) ??\n\t\t\tload_persisted_prompt_state(ctx.cwd);\n\t\tif (restored) {\n\t\t\tactive_base_name = restored.base_name ?? undefined;\n\t\t\tactive_layers = new Set(restored.layer_names ?? []);\n\t\t}\n\t\tconst normalized = normalize_active_state(\n\t\t\tpresets,\n\t\t\tactive_base_name,\n\t\t\tactive_layers,\n\t\t);\n\t\tactive_base_name = normalized.active_base_name;\n\t\tactive_layers = normalized.active_layers;\n\t\tset_status(ctx, active_base_name, active_layers);\n\t});\n\n\tpi.on('before_agent_start', async (event) => {\n\t\tconst blocks: string[] = [];\n\t\tconst base = get_base(active_base_name);\n\t\tif (base?.instructions.trim()) {\n\t\t\tblocks.push(\n\t\t\t\t`## Active Base Prompt: ${base.name}\\n${base.instructions.trim()}`,\n\t\t\t);\n\t\t}\n\n\t\tconst layer_blocks = [...active_layers]\n\t\t\t.sort()\n\t\t\t.map((name) => presets[name])\n\t\t\t.filter((preset): preset is LoadedPromptPreset =>\n\t\t\t\tBoolean(preset?.instructions.trim()),\n\t\t\t)\n\t\t\t.map(\n\t\t\t\t(preset) =>\n\t\t\t\t\t`### ${preset.name}\\n${preset.instructions.trim()}`,\n\t\t\t);\n\t\tif (layer_blocks.length > 0) {\n\t\t\tblocks.push(\n\t\t\t\t`## Active Prompt Layers\\n\\n${layer_blocks.join('\\n\\n')}`,\n\t\t\t);\n\t\t}\n\n\t\tif (blocks.length === 0) return;\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n\\n${blocks.join('\\n\\n')}`,\n\t\t};\n\t});\n\n\tpi.on('session_shutdown', async (_event, ctx) => {\n\t\tctx.ui.setStatus('preset', undefined);\n\t\tctx.ui.setFooter(undefined);\n\t});\n}\n","// Recall extension — nudge the agent to use pirecall for past session context\n// The model uses `npx pirecall` via bash directly — no custom tools needed\n\nimport type { ExtensionAPI } from '@mariozechner/pi-coding-agent';\nimport { spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nconst DEFAULT_DB_PATH = join(process.env.HOME!, '.pi', 'pirecall.db');\n\nfunction sync_recall_db_in_background(): void {\n\tif (!existsSync(DEFAULT_DB_PATH)) return;\n\n\ttry {\n\t\tconst proc = spawn('npx', ['pirecall', 'sync', '--json'], {\n\t\t\tstdio: 'ignore',\n\t\t});\n\t\tproc.unref();\n\t} catch {\n\t\t// Non-critical — db may just not have new data\n\t}\n}\n\n// Default export for Pi Package / additionalExtensionPaths loading\nexport default async function recall(pi: ExtensionAPI) {\n\tpi.on('session_start', async () => {\n\t\tsync_recall_db_in_background();\n\t});\n\n\t// System prompt hint so the model knows pirecall exists\n\tpi.on(\n\t\t'before_agent_start',\n\t\tasync (event: { systemPrompt: string }) => {\n\t\t\treturn {\n\t\t\t\tsystemPrompt:\n\t\t\t\t\tevent.systemPrompt +\n\t\t\t\t\t`\n\n## Session Recall\n\nYou have access to past Pi session history via \\`npx pirecall\\`. Use it when:\n- The user references prior work (\"what did we do\", \"last time\", \"remember when\")\n- You need context from a previous session about this project\n- You want to avoid repeating work already done\n\nQuick reference:\n- \\`npx pirecall recall \"<query>\" --json\\` — LLM-optimised context retrieval with surrounding messages\n- \\`npx pirecall search \"<query>\" --json\\` — full-text search (supports FTS5: AND, OR, NOT, \"phrase\", prefix*)\n- \\`npx pirecall search \"<query>\" --json --project my-pi\\` — filter by project\n- \\`npx pirecall search \"<query>\" --json --after 2026-04-10\\` — filter by date\n- \\`npx pirecall sessions --json\\` — list recent sessions\n- \\`npx pirecall stats --json\\` — database statistics\n\nAlways pass \\`--json\\` for structured output.`,\n\t\t\t};\n\t\t},\n\t);\n}\n","// Session name — AI-powered session naming\n// Adapted from Thomas Lopes' pi dotfiles\n\nimport { complete, type Message } from '@mariozechner/pi-ai';\nimport type {\n\tExtensionAPI,\n\tSessionEntry,\n} from '@mariozechner/pi-coding-agent';\nimport {\n\tBorderedLoader,\n\tconvertToLlm,\n\tserializeConversation,\n} from '@mariozechner/pi-coding-agent';\n\nconst SYSTEM_PROMPT = `You are a session naming assistant. Given a conversation history, generate a short, descriptive session name (2-5 words) that captures the main topic or task.\n\nGuidelines:\n- Be concise but specific\n- Use kebab-case or natural language\n- Focus on the core task/question\n- Avoid generic names like \"discussion\" or \"conversation\"\n- No quotes, no punctuation at the end\n\nExamples:\n- \"fix auth bug\" -> \"fix-auth-bug\" or \"authentication fix\"\n- \"how do I deploy to vercel\" -> \"vercel deployment\"\n- \"explain react hooks\" -> \"react hooks explanation\"\n- \"optimize database queries\" -> \"db query optimization\"\n\nOutput ONLY the session name, nothing else.`;\n\nconst AUTO_NAME_THRESHOLD = 1;\nconst MAX_CHARS = 4000;\nconst MAX_NAME_LEN = 50;\n\nfunction clean_name(value: string): string {\n\treturn value\n\t\t.replace(/^[\"']|[\"']$/g, '')\n\t\t.replace(/\\n/g, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim()\n\t\t.slice(0, MAX_NAME_LEN);\n}\n\nfunction truncate_conversation(value: string): string {\n\treturn value.length > MAX_CHARS\n\t\t? value.slice(0, MAX_CHARS) + '\\n...'\n\t\t: value;\n}\n\nasync function generate_session_name(\n\tctx: {\n\t\tmodelRegistry: {\n\t\t\tgetApiKeyAndHeaders: (\n\t\t\t\tmodel: NonNullable<\n\t\t\t\t\tParameters<\n\t\t\t\t\t\tParameters<ExtensionAPI['registerCommand']>[1]['handler']\n\t\t\t\t\t>[1]['model']\n\t\t\t\t>,\n\t\t\t) => Promise<any>;\n\t\t};\n\t},\n\tmodel: NonNullable<\n\t\tParameters<\n\t\t\tParameters<ExtensionAPI['registerCommand']>[1]['handler']\n\t\t>[1]['model']\n\t>,\n\tconversation_text: string,\n\tsignal?: AbortSignal,\n): Promise<string | null> {\n\tconst auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);\n\tif (!auth.ok || !auth.apiKey) {\n\t\tthrow new Error(\n\t\t\tauth.ok ? `No API key for ${model.provider}` : auth.error,\n\t\t);\n\t}\n\n\tconst user_message: Message = {\n\t\trole: 'user',\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: 'text',\n\t\t\t\ttext: `## Conversation History\\n\\n${truncate_conversation(conversation_text)}\\n\\nGenerate a concise session name for this conversation.`,\n\t\t\t},\n\t\t],\n\t\ttimestamp: Date.now(),\n\t};\n\n\tconst response = await complete(\n\t\tmodel,\n\t\t{ systemPrompt: SYSTEM_PROMPT, messages: [user_message] },\n\t\t{ apiKey: auth.apiKey, headers: auth.headers, signal },\n\t);\n\n\tif (response.stopReason === 'aborted') {\n\t\treturn null;\n\t}\n\n\treturn clean_name(\n\t\tresponse.content\n\t\t\t.filter(\n\t\t\t\t(c): c is { type: 'text'; text: string } => c.type === 'text',\n\t\t\t)\n\t\t\t.map((c) => c.text.trim())\n\t\t\t.join(' '),\n\t);\n}\n\nexport default async function session_name(pi: ExtensionAPI) {\n\tlet auto_named_attempted = false;\n\n\tpi.on('agent_end', async (_event, ctx) => {\n\t\tif (!ctx.hasUI || !ctx.model) return;\n\t\tif (pi.getSessionName() || auto_named_attempted) return;\n\n\t\tconst branch = ctx.sessionManager.getBranch();\n\t\tconst user_messages = branch.filter(\n\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\tentry.type === 'message' && entry.message.role === 'user',\n\t\t);\n\t\tif (user_messages.length < AUTO_NAME_THRESHOLD) return;\n\n\t\tauto_named_attempted = true;\n\t\tconst messages = branch\n\t\t\t.filter(\n\t\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\t\tentry.type === 'message',\n\t\t\t)\n\t\t\t.map((entry) => entry.message);\n\t\tif (messages.length === 0) return;\n\n\t\tconst conversation_text = serializeConversation(\n\t\t\tconvertToLlm(messages),\n\t\t);\n\n\t\tgenerate_session_name(ctx, ctx.model, conversation_text)\n\t\t\t.then((name) => {\n\t\t\t\tif (!name) return;\n\t\t\t\tpi.setSessionName(name);\n\t\t\t\tctx.ui.notify(`Auto-named: ${name}`, 'info');\n\t\t\t})\n\t\t\t.catch((err) => {\n\t\t\t\tconsole.error('Auto-naming failed:', err);\n\t\t\t});\n\t});\n\n\tpi.on('session_start', async () => {\n\t\tauto_named_attempted = false;\n\t});\n\n\tpi.registerCommand('session-name', {\n\t\tdescription:\n\t\t\t'Set, show, or auto-generate the current session name',\n\t\thandler: async (args, ctx) => {\n\t\t\tconst trimmed = args.trim();\n\n\t\t\tif (!trimmed) {\n\t\t\t\tconst current = pi.getSessionName();\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\tcurrent ? `Session: ${current}` : 'No session name set',\n\t\t\t\t\t'info',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (trimmed === '--auto' || trimmed === '-a') {\n\t\t\t\tif (!ctx.hasUI || !ctx.model) {\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t'Auto-naming requires interactive mode and a selected model',\n\t\t\t\t\t\t'error',\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst branch = ctx.sessionManager.getBranch();\n\t\t\t\tconst messages = branch\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\t\t\t\tentry.type === 'message',\n\t\t\t\t\t)\n\t\t\t\t\t.map((entry) => entry.message);\n\t\t\t\tif (messages.length === 0) {\n\t\t\t\t\tctx.ui.notify('No conversation to analyze', 'error');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst conversation_text = serializeConversation(\n\t\t\t\t\tconvertToLlm(messages),\n\t\t\t\t);\n\n\t\t\t\tconst result = await ctx.ui.custom<string | null>(\n\t\t\t\t\t(tui, theme, _kb, done) => {\n\t\t\t\t\t\tconst loader = new BorderedLoader(\n\t\t\t\t\t\t\ttui,\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\t'Generating session name...',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tloader.onAbort = () => done(null);\n\n\t\t\t\t\t\tgenerate_session_name(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\tctx.model!,\n\t\t\t\t\t\t\tconversation_text,\n\t\t\t\t\t\t\tloader.signal,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.then(done)\n\t\t\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\t\t\tconsole.error('Auto-naming failed:', err);\n\t\t\t\t\t\t\t\tdone(null);\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn loader;\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (result === null) {\n\t\t\t\t\tctx.ui.notify('Auto-naming cancelled', 'info');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!result) {\n\t\t\t\t\tctx.ui.notify('Failed to generate name', 'error');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tpi.setSessionName(result);\n\t\t\t\tctx.ui.notify(`Session named: ${result}`, 'info');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tpi.setSessionName(clean_name(trimmed));\n\t\t\tctx.ui.notify(`Session named: ${clean_name(trimmed)}`, 'info');\n\t\t},\n\t});\n}\n","import {\n\texistsSync,\n\tmkdirSync,\n\treadFileSync,\n\trenameSync,\n\twriteFileSync,\n} from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { homedir } from 'node:os';\n\nexport interface SkillsConfig {\n\tversion: number;\n\tenabled: Record<string, boolean>;\n\tdefaults: 'all-enabled' | 'all-disabled';\n}\n\nconst DEFAULT_CONFIG: SkillsConfig = {\n\tversion: 1,\n\tenabled: {},\n\tdefaults: 'all-disabled',\n};\n\nexport function get_config_path(): string {\n\tconst xdg =\n\t\tprocess.env.XDG_CONFIG_HOME || join(homedir(), '.config');\n\treturn join(xdg, 'my-pi', 'skills.json');\n}\n\nexport function load_skills_config(): SkillsConfig {\n\tconst path = get_config_path();\n\tif (!existsSync(path)) return { ...DEFAULT_CONFIG };\n\n\ttry {\n\t\tconst raw = readFileSync(path, 'utf-8');\n\t\tconst parsed = JSON.parse(raw) as Partial<SkillsConfig>;\n\t\treturn {\n\t\t\tversion: parsed.version ?? 1,\n\t\t\tenabled: parsed.enabled ?? {},\n\t\t\tdefaults: parsed.defaults ?? 'all-enabled',\n\t\t};\n\t} catch {\n\t\treturn { ...DEFAULT_CONFIG };\n\t}\n}\n\nexport function save_skills_config(config: SkillsConfig): void {\n\tconst path = get_config_path();\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n\n\tconst tmp = `${path}.tmp-${Date.now()}`;\n\twriteFileSync(tmp, JSON.stringify(config, null, '\\t') + '\\n', {\n\t\tmode: 0o600,\n\t});\n\trenameSync(tmp, path);\n}\n\nexport function make_skill_key(name: string, source: string): string {\n\treturn `${name}@${source}`;\n}\n\nexport function is_skill_enabled(\n\tconfig: SkillsConfig,\n\tkey: string,\n): boolean {\n\tif (key in config.enabled) return config.enabled[key];\n\treturn config.defaults === 'all-enabled';\n}\n","import {\n\tparseFrontmatter,\n\ttype SkillFrontmatter,\n} from '@mariozechner/pi-coding-agent';\nimport { existsSync, globSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { basename, dirname, join, resolve } from 'node:path';\n\nexport const IMPORT_METADATA_FILE = '.my-pi-source.json';\n\nexport interface InstalledPlugin {\n\tscope: string;\n\tinstallPath: string;\n\tversion: string;\n\tinstalledAt?: string;\n\tlastUpdated?: string;\n\tgitCommitSha?: string;\n}\n\ninterface InstalledPluginsFile {\n\tversion: number;\n\tplugins: Record<string, InstalledPlugin[]>;\n}\n\nexport interface ImportedSkillMetadata {\n\tversion: number;\n\tsource: string;\n\tupstream_skill_path: string;\n\tupstream_base_dir: string;\n\tupstream_install_path?: string;\n\tupstream_version?: string;\n\tupstream_git_commit_sha?: string;\n\timported_at: string;\n\tlast_synced_at: string;\n\timported_hash: string;\n\tupstream_hash: string;\n}\n\nexport interface PluginSkillSource {\n\tpluginId: string;\n\tinstallPath: string;\n\tversion: string;\n\tgitCommitSha?: string;\n}\n\nexport interface DiscoveredSkill {\n\tname: string;\n\tdescription: string;\n\tskillPath: string;\n\tbaseDir: string;\n\tsource: string;\n\tkind: 'managed' | 'external';\n\tplugin?: PluginSkillSource;\n\timport_meta?: ImportedSkillMetadata;\n}\n\nfunction read_installed_plugins(): InstalledPluginsFile | null {\n\tconst path = join(\n\t\thomedir(),\n\t\t'.claude',\n\t\t'plugins',\n\t\t'installed_plugins.json',\n\t);\n\tif (!existsSync(path)) return null;\n\n\ttry {\n\t\treturn JSON.parse(\n\t\t\treadFileSync(path, 'utf-8'),\n\t\t) as InstalledPluginsFile;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction parse_skill_md(\n\tskill_path: string,\n): { name: string; description: string } | null {\n\ttry {\n\t\tconst content = readFileSync(skill_path, 'utf-8');\n\t\tconst { frontmatter } =\n\t\t\tparseFrontmatter<SkillFrontmatter>(content);\n\t\tconst description = frontmatter?.description;\n\t\tif (!description) return null;\n\n\t\tconst name = frontmatter?.name || basename(dirname(skill_path));\n\t\treturn { name, description: description.trim() };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction read_import_metadata(\n\tbase_dir: string,\n): ImportedSkillMetadata | undefined {\n\tconst metadata_path = join(base_dir, IMPORT_METADATA_FILE);\n\tif (!existsSync(metadata_path)) return undefined;\n\n\ttry {\n\t\treturn JSON.parse(\n\t\t\treadFileSync(metadata_path, 'utf-8'),\n\t\t) as ImportedSkillMetadata;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction scan_dir_for_skills(\n\tdir: string,\n\toptions: {\n\t\tsource: string;\n\t\tkind: 'managed' | 'external';\n\t\tplugin?: PluginSkillSource;\n\t\tinclude_direct_root_skill?: boolean;\n\t},\n): DiscoveredSkill[] {\n\tif (!existsSync(dir)) return [];\n\n\tconst results: DiscoveredSkill[] = [];\n\tconst direct = join(dir, 'SKILL.md');\n\tconst include_direct_root_skill =\n\t\toptions.include_direct_root_skill ?? true;\n\n\tif (include_direct_root_skill && existsSync(direct)) {\n\t\tconst parsed = parse_skill_md(direct);\n\t\tif (parsed) {\n\t\t\tresults.push({\n\t\t\t\t...parsed,\n\t\t\t\tskillPath: direct,\n\t\t\t\tbaseDir: dir,\n\t\t\t\tsource: options.source,\n\t\t\t\tkind: options.kind,\n\t\t\t\tplugin: options.plugin,\n\t\t\t\timport_meta:\n\t\t\t\t\toptions.kind === 'managed'\n\t\t\t\t\t\t? read_import_metadata(dir)\n\t\t\t\t\t\t: undefined,\n\t\t\t});\n\t\t}\n\t\treturn results;\n\t}\n\n\ttry {\n\t\tconst matches = globSync('*/SKILL.md', { cwd: dir });\n\t\tfor (const match of matches) {\n\t\t\tconst full_path = resolve(dir, match);\n\t\t\tconst parsed = parse_skill_md(full_path);\n\t\t\tif (parsed) {\n\t\t\t\tconst base_dir = dirname(full_path);\n\t\t\t\tresults.push({\n\t\t\t\t\t...parsed,\n\t\t\t\t\tskillPath: full_path,\n\t\t\t\t\tbaseDir: base_dir,\n\t\t\t\t\tsource: options.source,\n\t\t\t\t\tkind: options.kind,\n\t\t\t\t\tplugin: options.plugin,\n\t\t\t\t\timport_meta:\n\t\t\t\t\t\toptions.kind === 'managed'\n\t\t\t\t\t\t\t? read_import_metadata(base_dir)\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// skip inaccessible dirs\n\t}\n\n\treturn results;\n}\n\nfunction dedupe_by_skill_path(\n\tskills: DiscoveredSkill[],\n): DiscoveredSkill[] {\n\tconst seen = new Set<string>();\n\tconst deduped: DiscoveredSkill[] = [];\n\n\tfor (const skill of skills) {\n\t\tif (seen.has(skill.skillPath)) continue;\n\t\tseen.add(skill.skillPath);\n\t\tdeduped.push(skill);\n\t}\n\n\treturn deduped;\n}\n\nexport function scan_managed_skills(): DiscoveredSkill[] {\n\tconst skills: DiscoveredSkill[] = [];\n\n\tfor (const skill of scan_dir_for_skills(\n\t\tjoin(homedir(), '.claude', 'skills'),\n\t\t{\n\t\t\tsource: 'user-local',\n\t\t\tkind: 'managed',\n\t\t},\n\t)) {\n\t\tskills.push(skill);\n\t}\n\n\tfor (const skill of scan_dir_for_skills(\n\t\tjoin(homedir(), '.pi', 'agent', 'skills'),\n\t\t{\n\t\t\tsource: 'pi-native',\n\t\t\tkind: 'managed',\n\t\t\tinclude_direct_root_skill: false,\n\t\t},\n\t)) {\n\t\tskills.push(skill);\n\t}\n\n\treturn dedupe_by_skill_path(skills);\n}\n\nexport function scan_importable_skills(): DiscoveredSkill[] {\n\tconst skills: DiscoveredSkill[] = [];\n\tconst plugins = read_installed_plugins();\n\tif (!plugins?.plugins) return skills;\n\n\tfor (const [plugin_id, entries] of Object.entries(\n\t\tplugins.plugins,\n\t)) {\n\t\tconst entry = entries[0];\n\t\tif (!entry?.installPath || !existsSync(entry.installPath))\n\t\t\tcontinue;\n\n\t\tconst source = `plugin:${plugin_id}`;\n\t\tconst plugin: PluginSkillSource = {\n\t\t\tpluginId: plugin_id,\n\t\t\tinstallPath: entry.installPath,\n\t\t\tversion: entry.version,\n\t\t\tgitCommitSha: entry.gitCommitSha,\n\t\t};\n\n\t\tfor (const skill of scan_dir_for_skills(\n\t\t\tjoin(entry.installPath, 'skills'),\n\t\t\t{\n\t\t\t\tsource,\n\t\t\t\tkind: 'external',\n\t\t\t\tplugin,\n\t\t\t},\n\t\t)) {\n\t\t\tskills.push(skill);\n\t\t}\n\n\t\tfor (const skill of scan_dir_for_skills(\n\t\t\tjoin(entry.installPath, '.pi', 'skills'),\n\t\t\t{\n\t\t\t\tsource,\n\t\t\t\tkind: 'external',\n\t\t\t\tplugin,\n\t\t\t},\n\t\t)) {\n\t\t\tskills.push(skill);\n\t\t}\n\n\t\tconst direct_root_skill = join(entry.installPath, 'SKILL.md');\n\t\tif (existsSync(direct_root_skill)) {\n\t\t\tconst parsed = parse_skill_md(direct_root_skill);\n\t\t\tif (parsed) {\n\t\t\t\tskills.push({\n\t\t\t\t\t...parsed,\n\t\t\t\t\tskillPath: direct_root_skill,\n\t\t\t\t\tbaseDir: entry.installPath,\n\t\t\t\t\tsource,\n\t\t\t\t\tkind: 'external',\n\t\t\t\t\tplugin,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn dedupe_by_skill_path(skills);\n}\n\nexport function scan_all_skills(): DiscoveredSkill[] {\n\treturn [...scan_managed_skills(), ...scan_importable_skills()];\n}\n","import { createHash } from 'node:crypto';\nimport {\n\tcpSync,\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trmSync,\n\tstatSync,\n\twriteFileSync,\n} from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join, relative, resolve } from 'node:path';\nimport {\n\tIMPORT_METADATA_FILE,\n\ttype DiscoveredSkill,\n\ttype ImportedSkillMetadata,\n} from './scanner.js';\n\nconst IMPORT_METADATA_VERSION = 1;\n\nfunction get_managed_skills_dir(): string {\n\treturn join(homedir(), '.pi', 'agent', 'skills');\n}\n\nfunction ensure_dir(path: string): void {\n\tmkdirSync(path, { recursive: true, mode: 0o700 });\n}\n\nfunction list_files_recursively(dir: string): string[] {\n\tconst files: string[] = [];\n\n\tfor (const entry of readdirSync(dir, { withFileTypes: true })) {\n\t\tconst full_path = join(dir, entry.name);\n\t\tif (entry.name === IMPORT_METADATA_FILE) continue;\n\t\tif (entry.isDirectory()) {\n\t\t\tfiles.push(...list_files_recursively(full_path));\n\t\t\tcontinue;\n\t\t}\n\t\tif (entry.isFile()) {\n\t\t\tfiles.push(full_path);\n\t\t}\n\t}\n\n\treturn files.sort((a, b) => a.localeCompare(b));\n}\n\nfunction hash_directory(dir: string): string {\n\tconst hash = createHash('sha256');\n\tfor (const file of list_files_recursively(dir)) {\n\t\thash.update(relative(dir, file));\n\t\thash.update('\\0');\n\t\thash.update(readFileSync(file));\n\t\thash.update('\\0');\n\t}\n\treturn hash.digest('hex');\n}\n\nfunction read_metadata(\n\tbase_dir: string,\n): ImportedSkillMetadata | undefined {\n\tconst path = join(base_dir, IMPORT_METADATA_FILE);\n\tif (!existsSync(path)) return undefined;\n\n\ttry {\n\t\treturn JSON.parse(\n\t\t\treadFileSync(path, 'utf-8'),\n\t\t) as ImportedSkillMetadata;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction write_metadata(\n\tbase_dir: string,\n\tmetadata: ImportedSkillMetadata,\n): void {\n\twriteFileSync(\n\t\tjoin(base_dir, IMPORT_METADATA_FILE),\n\t\tJSON.stringify(metadata, null, '\\t') + '\\n',\n\t\t{ mode: 0o600 },\n\t);\n}\n\nfunction replace_directory(\n\tsource_dir: string,\n\tdest_dir: string,\n): void {\n\tconst parent_dir = dirname(dest_dir);\n\tensure_dir(parent_dir);\n\tconst tmp_dir = join(\n\t\tparent_dir,\n\t\t`.${resolve(dest_dir).split('/').pop()}.tmp-${Date.now()}`,\n\t);\n\n\trmSync(tmp_dir, { recursive: true, force: true });\n\tcpSync(source_dir, tmp_dir, {\n\t\trecursive: true,\n\t\tpreserveTimestamps: true,\n\t\tverbatimSymlinks: false,\n\t});\n\trmSync(dest_dir, { recursive: true, force: true });\n\tcpSync(tmp_dir, dest_dir, {\n\t\trecursive: true,\n\t\tpreserveTimestamps: true,\n\t\tverbatimSymlinks: false,\n\t});\n\trmSync(tmp_dir, { recursive: true, force: true });\n}\n\nexport interface ImportSkillResult {\n\tskillDir: string;\n\tmetadata: ImportedSkillMetadata;\n}\n\nexport function import_external_skill(\n\tskill: DiscoveredSkill,\n): ImportSkillResult {\n\tif (skill.kind !== 'external') {\n\t\tthrow new Error(`Skill ${skill.name} is not importable`);\n\t}\n\n\tconst managed_root = get_managed_skills_dir();\n\tensure_dir(managed_root);\n\n\tconst skill_dir = join(managed_root, skill.name);\n\tconst existing = existsSync(skill_dir);\n\tif (existing) {\n\t\tconst existing_stat = statSync(skill_dir);\n\t\tif (!existing_stat.isDirectory()) {\n\t\t\tthrow new Error(`${skill_dir} exists and is not a directory`);\n\t\t}\n\n\t\tconst existing_metadata = read_metadata(skill_dir);\n\t\tif (!existing_metadata) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to overwrite existing unmanaged skill at ${skill_dir}`,\n\t\t\t);\n\t\t}\n\t}\n\n\treplace_directory(skill.baseDir, skill_dir);\n\n\tconst upstream_hash = hash_directory(skill.baseDir);\n\tconst imported_hash = hash_directory(skill_dir);\n\tconst now = new Date().toISOString();\n\tconst metadata: ImportedSkillMetadata = {\n\t\tversion: IMPORT_METADATA_VERSION,\n\t\tsource: skill.source,\n\t\tupstream_skill_path: skill.skillPath,\n\t\tupstream_base_dir: skill.baseDir,\n\t\tupstream_install_path: skill.plugin?.installPath,\n\t\tupstream_version: skill.plugin?.version,\n\t\tupstream_git_commit_sha: skill.plugin?.gitCommitSha,\n\t\timported_at: now,\n\t\tlast_synced_at: now,\n\t\timported_hash,\n\t\tupstream_hash,\n\t};\n\n\twrite_metadata(skill_dir, metadata);\n\treturn {\n\t\tskillDir: skill_dir,\n\t\tmetadata,\n\t};\n}\n\nexport interface SyncSkillResult {\n\tskillDir: string;\n\tmetadata: ImportedSkillMetadata;\n\tchanged: boolean;\n}\n\nexport function sync_imported_skill(\n\tskill: DiscoveredSkill,\n): SyncSkillResult {\n\tif (skill.kind !== 'managed' || !skill.import_meta) {\n\t\tthrow new Error(\n\t\t\t`Skill ${skill.name} is not managed by my-pi sync`,\n\t\t);\n\t}\n\n\tconst metadata = skill.import_meta;\n\tif (!existsSync(metadata.upstream_base_dir)) {\n\t\tthrow new Error(\n\t\t\t`Upstream source no longer exists: ${metadata.upstream_base_dir}`,\n\t\t);\n\t}\n\n\tconst current_hash = hash_directory(skill.baseDir);\n\tif (current_hash !== metadata.imported_hash) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync ${skill.name}; local changes detected in ${skill.baseDir}`,\n\t\t);\n\t}\n\n\tconst upstream_hash = hash_directory(metadata.upstream_base_dir);\n\tif (upstream_hash === metadata.upstream_hash) {\n\t\treturn {\n\t\t\tskillDir: skill.baseDir,\n\t\t\tmetadata,\n\t\t\tchanged: false,\n\t\t};\n\t}\n\n\treplace_directory(metadata.upstream_base_dir, skill.baseDir);\n\tconst imported_hash = hash_directory(skill.baseDir);\n\tconst updated: ImportedSkillMetadata = {\n\t\t...metadata,\n\t\tlast_synced_at: new Date().toISOString(),\n\t\timported_hash,\n\t\tupstream_hash,\n\t};\n\twrite_metadata(skill.baseDir, updated);\n\n\treturn {\n\t\tskillDir: skill.baseDir,\n\t\tmetadata: updated,\n\t\tchanged: true,\n\t};\n}\n","import {\n\ttype SkillsConfig,\n\tis_skill_enabled,\n\tload_skills_config,\n\tmake_skill_key,\n\tsave_skills_config,\n} from './config.js';\nimport {\n\ttype ImportSkillResult,\n\ttype SyncSkillResult,\n\timport_external_skill,\n\tsync_imported_skill,\n} from './importer.js';\nimport {\n\ttype DiscoveredSkill,\n\tscan_importable_skills,\n\tscan_managed_skills,\n} from './scanner.js';\n\nexport interface ManagedSkill extends DiscoveredSkill {\n\tkey: string;\n\tenabled: boolean;\n}\n\nexport interface SkillsManager {\n\tdiscover(): ManagedSkill[];\n\tdiscover_importable(): ManagedSkill[];\n\tget_enabled_skill_paths(): string[];\n\t/** Check if a skill should pass through pi's skillsOverride */\n\tis_enabled_by_skill(name: string, filePath: string): boolean;\n\tenable(key: string): boolean;\n\tdisable(key: string): boolean;\n\ttoggle(key: string): boolean;\n\tsearch(query: string): ManagedSkill[];\n\tsearch_importable(query: string): ManagedSkill[];\n\tset_defaults(policy: 'all-enabled' | 'all-disabled'): void;\n\timport_skill(\n\t\tkey_or_name: string,\n\t): ImportSkillResult & { key: string };\n\tsync_skill(key_or_name: string): SyncSkillResult & { key: string };\n\trefresh(): void;\n}\n\nfunction resolve_skill_key(skill: DiscoveredSkill): string {\n\treturn make_skill_key(skill.name, skill.source);\n}\n\nfunction match_skill_by_key_or_name(\n\tskills: DiscoveredSkill[],\n\tkey_or_name: string,\n): DiscoveredSkill {\n\tconst exact_key = skills.find(\n\t\t(skill) => resolve_skill_key(skill) === key_or_name,\n\t);\n\tif (exact_key) return exact_key;\n\n\tconst by_name = skills.filter(\n\t\t(skill) => skill.name === key_or_name,\n\t);\n\tif (by_name.length === 1) {\n\t\treturn by_name[0]!;\n\t}\n\tif (by_name.length > 1) {\n\t\tthrow new Error(\n\t\t\t`Multiple skills named ${key_or_name}. Use an exact key instead.`,\n\t\t);\n\t}\n\n\tthrow new Error(`Unknown skill: ${key_or_name}`);\n}\n\nexport function create_skills_manager(): SkillsManager {\n\tlet config: SkillsConfig = load_skills_config();\n\tlet managed_cache: DiscoveredSkill[] | null = null;\n\tlet importable_cache: DiscoveredSkill[] | null = null;\n\n\tfunction get_managed(): DiscoveredSkill[] {\n\t\tif (!managed_cache) {\n\t\t\tmanaged_cache = scan_managed_skills();\n\t\t}\n\t\treturn managed_cache;\n\t}\n\n\tfunction get_importable(): DiscoveredSkill[] {\n\t\tif (!importable_cache) {\n\t\t\timportable_cache = scan_importable_skills();\n\t\t}\n\t\treturn importable_cache;\n\t}\n\n\tfunction to_managed(skill: DiscoveredSkill): ManagedSkill {\n\t\tconst key = resolve_skill_key(skill);\n\t\treturn {\n\t\t\t...skill,\n\t\t\tkey,\n\t\t\tenabled:\n\t\t\t\tskill.kind === 'managed'\n\t\t\t\t\t? is_skill_enabled(config, key)\n\t\t\t\t\t: false,\n\t\t};\n\t}\n\n\tfunction get_enabled_managed_skills(): ManagedSkill[] {\n\t\treturn get_managed()\n\t\t\t.filter((skill) =>\n\t\t\t\tis_skill_enabled(config, resolve_skill_key(skill)),\n\t\t\t)\n\t\t\t.map(to_managed);\n\t}\n\n\treturn {\n\t\tdiscover(): ManagedSkill[] {\n\t\t\treturn get_managed().map(to_managed);\n\t\t},\n\n\t\tdiscover_importable(): ManagedSkill[] {\n\t\t\treturn get_importable().map(to_managed);\n\t\t},\n\n\t\tis_enabled_by_skill(name: string, filePath: string): boolean {\n\t\t\tconst discovered = get_managed();\n\t\t\tconst match = discovered.find((s) => s.skillPath === filePath);\n\t\t\tif (match) {\n\t\t\t\treturn is_skill_enabled(config, resolve_skill_key(match));\n\t\t\t}\n\n\t\t\tconst by_name = discovered.find((s) => s.name === name);\n\t\t\tif (by_name) {\n\t\t\t\treturn is_skill_enabled(config, resolve_skill_key(by_name));\n\t\t\t}\n\n\t\t\t// Unknown skill sources should remain enabled so pi's native\n\t\t\t// discovery keeps working for project and other default locations.\n\t\t\treturn true;\n\t\t},\n\n\t\tget_enabled_skill_paths(): string[] {\n\t\t\treturn get_enabled_managed_skills().map(\n\t\t\t\t(skill) => skill.baseDir,\n\t\t\t);\n\t\t},\n\n\t\tenable(key: string): boolean {\n\t\t\tconfig.enabled[key] = true;\n\t\t\tsave_skills_config(config);\n\t\t\treturn true;\n\t\t},\n\n\t\tdisable(key: string): boolean {\n\t\t\tconfig.enabled[key] = false;\n\t\t\tsave_skills_config(config);\n\t\t\treturn false;\n\t\t},\n\n\t\ttoggle(key: string): boolean {\n\t\t\tconst current = is_skill_enabled(config, key);\n\t\t\tconfig.enabled[key] = !current;\n\t\t\tsave_skills_config(config);\n\t\t\treturn !current;\n\t\t},\n\n\t\tsearch(query: string): ManagedSkill[] {\n\t\t\tconst q = query.toLowerCase();\n\t\t\treturn this.discover().filter(\n\t\t\t\t(s) =>\n\t\t\t\t\ts.name.toLowerCase().includes(q) ||\n\t\t\t\t\ts.description.toLowerCase().includes(q) ||\n\t\t\t\t\ts.source.toLowerCase().includes(q),\n\t\t\t);\n\t\t},\n\n\t\tsearch_importable(query: string): ManagedSkill[] {\n\t\t\tconst q = query.toLowerCase();\n\t\t\treturn this.discover_importable().filter(\n\t\t\t\t(s) =>\n\t\t\t\t\ts.name.toLowerCase().includes(q) ||\n\t\t\t\t\ts.description.toLowerCase().includes(q) ||\n\t\t\t\t\ts.source.toLowerCase().includes(q),\n\t\t\t);\n\t\t},\n\n\t\tset_defaults(policy: 'all-enabled' | 'all-disabled'): void {\n\t\t\tconfig.defaults = policy;\n\t\t\tsave_skills_config(config);\n\t\t},\n\n\t\timport_skill(key_or_name: string) {\n\t\t\tconst skill = match_skill_by_key_or_name(\n\t\t\t\tget_importable(),\n\t\t\t\tkey_or_name,\n\t\t\t);\n\t\t\tconst result = import_external_skill(skill);\n\t\t\tconst managed_key = make_skill_key(skill.name, 'pi-native');\n\t\t\tconfig.enabled[managed_key] = true;\n\t\t\tsave_skills_config(config);\n\t\t\tthis.refresh();\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\tkey: managed_key,\n\t\t\t};\n\t\t},\n\n\t\tsync_skill(key_or_name: string) {\n\t\t\tconst skill = match_skill_by_key_or_name(\n\t\t\t\tget_managed(),\n\t\t\t\tkey_or_name,\n\t\t\t);\n\t\t\tconst result = sync_imported_skill(skill);\n\t\t\tthis.refresh();\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\tkey: resolve_skill_key(skill),\n\t\t\t};\n\t\t},\n\n\t\trefresh(): void {\n\t\t\tmanaged_cache = null;\n\t\t\timportable_cache = null;\n\t\t\tconfig = load_skills_config();\n\t\t},\n\t};\n}\n","import type { ExtensionAPI } from '@mariozechner/pi-coding-agent';\nimport {\n\tContainer,\n\tSettingsList,\n\tText,\n\ttype SettingItem,\n} from '@mariozechner/pi-tui';\nimport {\n\tcreate_skills_manager,\n\ttype ManagedSkill,\n} from '../skills/manager.js';\n\nconst ENABLED = '[x]';\nconst DISABLED = '[ ]';\nconst SYNC = '[~]';\nconst IMPORTED_LABEL = '[=]';\n\nfunction sort_skills(skills: ManagedSkill[]): ManagedSkill[] {\n\treturn [...skills].sort((a, b) => {\n\t\tconst by_name = a.name.localeCompare(b.name);\n\t\tif (by_name !== 0) return by_name;\n\t\tconst by_source = a.source.localeCompare(b.source);\n\t\tif (by_source !== 0) return by_source;\n\t\treturn a.key.localeCompare(b.key);\n\t});\n}\n\nfunction find_matching_imported_skill(\n\tmanaged_skills: ManagedSkill[],\n\tskill: ManagedSkill,\n): ManagedSkill | undefined {\n\tconst exact_match = managed_skills.find(\n\t\t(candidate) =>\n\t\t\tcandidate.import_meta?.source === skill.source &&\n\t\t\t(candidate.import_meta.upstream_skill_path ===\n\t\t\t\tskill.skillPath ||\n\t\t\t\tcandidate.import_meta.upstream_base_dir === skill.baseDir),\n\t);\n\tif (exact_match) return exact_match;\n\n\treturn managed_skills.find(\n\t\t(candidate) =>\n\t\t\tcandidate.import_meta?.source === skill.source &&\n\t\t\tcandidate.name === skill.name,\n\t);\n}\n\nfunction get_importable_state(\n\tmanaged_skills: ManagedSkill[],\n\tskill: ManagedSkill,\n): {\n\tlabel: string;\n\tdetail: string;\n\taction: 'import' | 'sync' | null;\n} {\n\tconst imported = find_matching_imported_skill(\n\t\tmanaged_skills,\n\t\tskill,\n\t);\n\tif (imported?.import_meta) {\n\t\tconst version_changed = Boolean(\n\t\t\tskill.plugin?.version &&\n\t\t\timported.import_meta.upstream_version &&\n\t\t\tskill.plugin.version !== imported.import_meta.upstream_version,\n\t\t);\n\t\tconst sha_changed = Boolean(\n\t\t\tskill.plugin?.gitCommitSha &&\n\t\t\timported.import_meta.upstream_git_commit_sha &&\n\t\t\tskill.plugin.gitCommitSha !==\n\t\t\t\timported.import_meta.upstream_git_commit_sha,\n\t\t);\n\n\t\tif (version_changed || sha_changed) {\n\t\t\treturn {\n\t\t\t\tlabel: 'sync',\n\t\t\t\tdetail: 'Press Enter to sync the imported copy and reload',\n\t\t\t\taction: 'sync',\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tlabel: 'imported',\n\t\t\tdetail: `Already imported to ${imported.baseDir}`,\n\t\t\taction: null,\n\t\t};\n\t}\n\n\tconst managed_conflict = managed_skills.find(\n\t\t(candidate) => candidate.name === skill.name,\n\t);\n\tif (managed_conflict) {\n\t\treturn {\n\t\t\tlabel: 'managed',\n\t\t\tdetail: `Already managed at ${managed_conflict.baseDir}`,\n\t\t\taction: null,\n\t\t};\n\t}\n\n\treturn {\n\t\tlabel: 'import',\n\t\tdetail: 'Press Enter to import into pi-native skills and reload',\n\t\taction: 'import',\n\t};\n}\n\nfunction to_setting_item(skill: ManagedSkill): SettingItem {\n\tconst detail_lines = [\n\t\t`${skill.source} • ${skill.key}`,\n\t\tskill.description,\n\t\tskill.baseDir,\n\t];\n\tif (skill.import_meta?.upstream_version) {\n\t\tdetail_lines.push(\n\t\t\t`upstream: ${skill.import_meta.upstream_version}${skill.import_meta.upstream_git_commit_sha ? ` • ${skill.import_meta.upstream_git_commit_sha.slice(0, 12)}` : ''}`,\n\t\t);\n\t}\n\n\treturn {\n\t\tid: skill.key,\n\t\tlabel: skill.name,\n\t\tdescription: detail_lines.join('\\n'),\n\t\tcurrentValue: skill.enabled ? ENABLED : DISABLED,\n\t\tvalues: [ENABLED, DISABLED],\n\t};\n}\n\nfunction to_importable_setting_item(\n\tmanaged_skills: ManagedSkill[],\n\tskill: ManagedSkill,\n): SettingItem {\n\tconst state = get_importable_state(managed_skills, skill);\n\tconst detail_lines = [\n\t\t`${skill.source} • ${skill.key}`,\n\t\tskill.description,\n\t\tskill.baseDir,\n\t];\n\tif (skill.plugin?.version) {\n\t\tdetail_lines.push(\n\t\t\t`plugin: ${skill.plugin.version}${skill.plugin.gitCommitSha ? ` • ${skill.plugin.gitCommitSha.slice(0, 12)}` : ''}`,\n\t\t);\n\t}\n\n\tif (state.action === 'import') {\n\t\treturn {\n\t\t\tid: skill.key,\n\t\t\tlabel: skill.name,\n\t\t\tdescription: detail_lines.join('\\n'),\n\t\t\tcurrentValue: DISABLED,\n\t\t\tvalues: [ENABLED, DISABLED],\n\t\t};\n\t}\n\n\tif (state.action === 'sync') {\n\t\tdetail_lines.push('enter to sync');\n\t\treturn {\n\t\t\tid: skill.key,\n\t\t\tlabel: skill.name,\n\t\t\tdescription: detail_lines.join('\\n'),\n\t\t\tcurrentValue: SYNC,\n\t\t\tvalues: [SYNC],\n\t\t};\n\t}\n\n\tdetail_lines.push(state.detail);\n\treturn {\n\t\tid: skill.key,\n\t\tlabel: skill.name,\n\t\tdescription: detail_lines.join('\\n'),\n\t\tcurrentValue: IMPORTED_LABEL,\n\t};\n}\n\nfunction sets_equal(\n\ta: ReadonlySet<string>,\n\tb: ReadonlySet<string>,\n): boolean {\n\tif (a.size !== b.size) return false;\n\tfor (const value of a) {\n\t\tif (!b.has(value)) return false;\n\t}\n\treturn true;\n}\n\n// Default export for Pi Package / additionalExtensionPaths loading\nexport default async function skills(pi: ExtensionAPI) {\n\tconst mgr = create_skills_manager();\n\n\tconst subs = ['import', 'sync', 'refresh', 'defaults'];\n\n\tpi.registerCommand('skills', {\n\t\tdescription: 'Manage pi-native skills and import external skills',\n\t\tgetArgumentCompletions: (prefix) => {\n\t\t\tconst parts = prefix.trim().split(/\\s+/);\n\t\t\tif (parts.length <= 1) {\n\t\t\t\treturn subs\n\t\t\t\t\t.filter((s) => s.startsWith(parts[0] || ''))\n\t\t\t\t\t.map((s) => ({ value: s, label: s }));\n\t\t\t}\n\n\t\t\tif (parts[0] === 'import') {\n\t\t\t\tconst q = parts.slice(1).join(' ').toLowerCase();\n\t\t\t\treturn sort_skills(mgr.discover_importable())\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\ts.key.toLowerCase().includes(q) ||\n\t\t\t\t\t\t\ts.name.toLowerCase().includes(q),\n\t\t\t\t\t)\n\t\t\t\t\t.slice(0, 20)\n\t\t\t\t\t.map((s) => ({\n\t\t\t\t\t\tvalue: `${parts[0]} ${s.key}`,\n\t\t\t\t\t\tlabel: s.key,\n\t\t\t\t\t}));\n\t\t\t}\n\n\t\t\tif (parts[0] === 'sync') {\n\t\t\t\tconst q = parts.slice(1).join(' ').toLowerCase();\n\t\t\t\treturn sort_skills(\n\t\t\t\t\tmgr\n\t\t\t\t\t\t.discover()\n\t\t\t\t\t\t.filter((skill) => Boolean(skill.import_meta)),\n\t\t\t\t)\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\ts.key.toLowerCase().includes(q) ||\n\t\t\t\t\t\t\ts.name.toLowerCase().includes(q),\n\t\t\t\t\t)\n\t\t\t\t\t.slice(0, 20)\n\t\t\t\t\t.map((s) => ({\n\t\t\t\t\t\tvalue: `${parts[0]} ${s.key}`,\n\t\t\t\t\t\tlabel: s.key,\n\t\t\t\t\t}));\n\t\t\t}\n\n\t\t\treturn null;\n\t\t},\n\t\thandler: async (args, ctx) => {\n\t\t\tconst trimmed = args.trim();\n\n\t\t\tif (!trimmed && ctx.hasUI) {\n\t\t\t\tconst discovered = sort_skills(mgr.discover());\n\t\t\t\tconst importable = sort_skills(mgr.discover_importable());\n\t\t\t\tif (discovered.length === 0 && importable.length === 0) {\n\t\t\t\t\tctx.ui.notify('No managed or importable skills found');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst initial_enabled = new Set(\n\t\t\t\t\tdiscovered\n\t\t\t\t\t\t.filter((skill) => skill.enabled)\n\t\t\t\t\t\t.map((skill) => skill.key),\n\t\t\t\t);\n\t\t\t\tconst current_enabled = new Set(initial_enabled);\n\t\t\t\tconst queued_imports = new Set<string>();\n\t\t\t\tlet reload_notice: string | null = null;\n\n\t\t\t\tconst managed_items = discovered.map(to_setting_item);\n\t\t\t\tconst importable_items = importable.map((skill) =>\n\t\t\t\t\tto_importable_setting_item(discovered, skill),\n\t\t\t\t);\n\n\t\t\t\tconst all_items: SettingItem[] = [];\n\t\t\t\tif (managed_items.length > 0) {\n\t\t\t\t\tall_items.push({\n\t\t\t\t\t\tid: '__header_managed__',\n\t\t\t\t\t\tlabel: `── Managed (${managed_items.length}) ──`,\n\t\t\t\t\t\tdescription: '',\n\t\t\t\t\t\tcurrentValue: '',\n\t\t\t\t\t});\n\t\t\t\t\tall_items.push(...managed_items);\n\t\t\t\t}\n\t\t\t\tif (importable_items.length > 0) {\n\t\t\t\t\tall_items.push({\n\t\t\t\t\t\tid: '__header_importable__',\n\t\t\t\t\t\tlabel: `── Importable (${importable_items.length}) ──`,\n\t\t\t\t\t\tdescription: '',\n\t\t\t\t\t\tcurrentValue: '',\n\t\t\t\t\t});\n\t\t\t\t\tall_items.push(...importable_items);\n\t\t\t\t}\n\n\t\t\t\tconst managed_keys = new Set(discovered.map((s) => s.key));\n\t\t\t\tconst importable_map = new Map(\n\t\t\t\t\timportable.map((s) => [s.key, s]),\n\t\t\t\t);\n\n\t\t\t\tawait ctx.ui.custom((tui, theme, _kb, done) => {\n\t\t\t\t\tconst list = new SettingsList(\n\t\t\t\t\t\tall_items,\n\t\t\t\t\t\tMath.min(Math.max(all_items.length + 4, 8), 22),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcursor: theme.fg('accent', '›'),\n\t\t\t\t\t\t\tlabel: (text, selected) => {\n\t\t\t\t\t\t\t\tif (text.startsWith('──') && text.endsWith('──')) {\n\t\t\t\t\t\t\t\t\treturn theme.fg('dim', theme.bold(text));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn selected ? theme.fg('accent', text) : text;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tvalue: (text, selected) => {\n\t\t\t\t\t\t\t\tconst color =\n\t\t\t\t\t\t\t\t\ttext === ENABLED\n\t\t\t\t\t\t\t\t\t\t? ('success' as const)\n\t\t\t\t\t\t\t\t\t\t: text === SYNC\n\t\t\t\t\t\t\t\t\t\t\t? ('warning' as const)\n\t\t\t\t\t\t\t\t\t\t\t: text === IMPORTED_LABEL\n\t\t\t\t\t\t\t\t\t\t\t\t? ('success' as const)\n\t\t\t\t\t\t\t\t\t\t\t\t: ('dim' as const);\n\t\t\t\t\t\t\t\tconst rendered = theme.fg(color, text);\n\t\t\t\t\t\t\t\treturn selected\n\t\t\t\t\t\t\t\t\t? theme.bold(theme.fg('accent', rendered))\n\t\t\t\t\t\t\t\t\t: rendered;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdescription: (text) => theme.fg('muted', text),\n\t\t\t\t\t\t\thint: (text) => theme.fg('dim', text),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t(id, new_value) => {\n\t\t\t\t\t\t\tif (id.startsWith('__header_')) return;\n\n\t\t\t\t\t\t\tif (managed_keys.has(id)) {\n\t\t\t\t\t\t\t\tif (new_value === ENABLED) {\n\t\t\t\t\t\t\t\t\tcurrent_enabled.add(id);\n\t\t\t\t\t\t\t\t\tmgr.enable(id);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurrent_enabled.delete(id);\n\t\t\t\t\t\t\t\t\tmgr.disable(id);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst import_skill = importable_map.get(id);\n\t\t\t\t\t\t\tif (!import_skill) return;\n\n\t\t\t\t\t\t\tconst state = get_importable_state(\n\t\t\t\t\t\t\t\tdiscovered,\n\t\t\t\t\t\t\t\timport_skill,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tif (state.action === 'import') {\n\t\t\t\t\t\t\t\tif (new_value === ENABLED) {\n\t\t\t\t\t\t\t\t\tqueued_imports.add(id);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tqueued_imports.delete(id);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (state.action === 'sync') {\n\t\t\t\t\t\t\t\tconst imported_skill = find_matching_imported_skill(\n\t\t\t\t\t\t\t\t\tdiscovered,\n\t\t\t\t\t\t\t\t\timport_skill,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tif (!imported_skill) {\n\t\t\t\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t\t\t\t`Imported copy for ${import_skill.name} was not found`,\n\t\t\t\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tconst result = mgr.sync_skill(imported_skill.key);\n\t\t\t\t\t\t\t\t\tif (result.changed) {\n\t\t\t\t\t\t\t\t\t\treload_notice = `Synced ${import_skill.name}. Reloading...`;\n\t\t\t\t\t\t\t\t\t\tdone(undefined);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t\t\t\t\t`${import_skill.name} is already up to date.`,\n\t\t\t\t\t\t\t\t\t\t\t'info',\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t\t\t\t\t\t: String(error),\n\t\t\t\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => done(undefined),\n\t\t\t\t\t\t{ enableSearch: true },\n\t\t\t\t\t);\n\n\t\t\t\t\tconst container = new Container();\n\n\t\t\t\t\tcontainer.addChild({\n\t\t\t\t\t\trender: () => {\n\t\t\t\t\t\t\tconst enabled = current_enabled.size;\n\t\t\t\t\t\t\tconst disabled = discovered.length - enabled;\n\t\t\t\t\t\t\tconst queued = queued_imports.size;\n\t\t\t\t\t\t\tconst parts = [\n\t\t\t\t\t\t\t\t`${enabled} enabled`,\n\t\t\t\t\t\t\t\t`${disabled} disabled`,\n\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\tif (importable.length > 0) {\n\t\t\t\t\t\t\t\tparts.push(`${importable.length} importable`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (queued > 0) {\n\t\t\t\t\t\t\t\tparts.push(`${queued} queued for import`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\ttheme.fg('accent', theme.bold('Skills')),\n\t\t\t\t\t\t\t\ttheme.fg('muted', parts.join(' • ')),\n\t\t\t\t\t\t\t\t'',\n\t\t\t\t\t\t\t];\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinvalidate: () => {},\n\t\t\t\t\t});\n\n\t\t\t\t\tcontainer.addChild({\n\t\t\t\t\t\trender(width: number) {\n\t\t\t\t\t\t\treturn list.render(width);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinvalidate() {\n\t\t\t\t\t\t\tlist.invalidate();\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\n\t\t\t\t\tcontainer.addChild(\n\t\t\t\t\t\tnew Text(\n\t\t\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\t\t'dim',\n\t\t\t\t\t\t\t\t'search filters • enter toggles • esc close',\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\trender(width: number) {\n\t\t\t\t\t\t\treturn container.render(width);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tinvalidate() {\n\t\t\t\t\t\t\tcontainer.invalidate();\n\t\t\t\t\t\t},\n\t\t\t\t\t\thandleInput(data: string) {\n\t\t\t\t\t\t\tlist.handleInput(data);\n\t\t\t\t\t\t\ttui.requestRender();\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t});\n\n\t\t\t\tif (queued_imports.size > 0) {\n\t\t\t\t\tconst imported_names: string[] = [];\n\t\t\t\t\tfor (const key of queued_imports) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tmgr.import_skill(key);\n\t\t\t\t\t\t\timported_names.push(key);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t\t\t\t: String(error),\n\t\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (imported_names.length > 0) {\n\t\t\t\t\t\treload_notice = `Imported ${imported_names.length} skill(s). Reloading...`;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (reload_notice) {\n\t\t\t\t\tctx.ui.notify(reload_notice, 'info');\n\t\t\t\t\tawait ctx.reload();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!sets_equal(initial_enabled, current_enabled)) {\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t'Reloading to apply updated skills...',\n\t\t\t\t\t\t'info',\n\t\t\t\t\t);\n\t\t\t\t\tawait ctx.reload();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst [sub, ...rest] = (trimmed || 'list').split(/\\s+/);\n\t\t\tconst arg = rest.join(' ');\n\n\t\t\tswitch (sub) {\n\t\t\t\tcase 'import': {\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /skills import <key|name>',\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = mgr.import_skill(arg);\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t`Imported ${arg} to ${result.skillDir}. Reloading...`,\n\t\t\t\t\t\t\t'info',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait ctx.reload();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcase 'sync': {\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /skills sync <key|name>',\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = mgr.sync_skill(arg);\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\tresult.changed\n\t\t\t\t\t\t\t\t? `Synced ${arg}. Reloading...`\n\t\t\t\t\t\t\t\t: `${arg} is already up to date.`,\n\t\t\t\t\t\t\t'info',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (result.changed) {\n\t\t\t\t\t\t\tawait ctx.reload();\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcase 'refresh': {\n\t\t\t\t\tmgr.refresh();\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t`Rescanned: ${mgr.discover().length} managed skills, ${mgr.discover_importable().length} importable skills found`,\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'defaults': {\n\t\t\t\t\tif (arg !== 'all-enabled' && arg !== 'all-disabled') {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /skills defaults <all-enabled|all-disabled>',\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tmgr.set_defaults(arg);\n\t\t\t\t\tctx.ui.notify(`Default policy: ${arg}`);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t`Unknown: ${sub}. Use: ${subs.join(', ')}`,\n\t\t\t\t\t\t'warning',\n\t\t\t\t\t);\n\t\t\t}\n\t\t},\n\t});\n}\n","import { getAgentDir } from '@mariozechner/pi-coding-agent';\nimport {\n\texistsSync,\n\tmkdirSync,\n\treadFileSync,\n\trenameSync,\n\twriteFileSync,\n} from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\nexport interface TelemetryConfig {\n\tversion: number;\n\tenabled: boolean;\n}\n\nconst DEFAULT_CONFIG: TelemetryConfig = {\n\tversion: 1,\n\tenabled: false,\n};\n\nexport function get_telemetry_config_path(): string {\n\treturn join(getAgentDir(), 'telemetry.json');\n}\n\nexport function get_default_telemetry_db_path(): string {\n\treturn join(getAgentDir(), 'telemetry.db');\n}\n\nexport function resolve_telemetry_db_path(\n\tcwd: string,\n\toverride_path?: string,\n): string {\n\tif (!override_path) return get_default_telemetry_db_path();\n\treturn resolve(cwd, override_path);\n}\n\nexport function load_telemetry_config(): TelemetryConfig {\n\tconst path = get_telemetry_config_path();\n\tif (!existsSync(path)) return { ...DEFAULT_CONFIG };\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(path, 'utf-8')) as {\n\t\t\tversion?: unknown;\n\t\t\tenabled?: unknown;\n\t\t};\n\t\treturn {\n\t\t\tversion:\n\t\t\t\ttypeof parsed.version === 'number'\n\t\t\t\t\t? parsed.version\n\t\t\t\t\t: DEFAULT_CONFIG.version,\n\t\t\tenabled:\n\t\t\t\ttypeof parsed.enabled === 'boolean'\n\t\t\t\t\t? parsed.enabled\n\t\t\t\t\t: DEFAULT_CONFIG.enabled,\n\t\t};\n\t} catch {\n\t\treturn { ...DEFAULT_CONFIG };\n\t}\n}\n\nexport function save_telemetry_config(config: TelemetryConfig): void {\n\tconst path = get_telemetry_config_path();\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n\n\tconst tmp = `${path}.tmp-${Date.now()}`;\n\twriteFileSync(tmp, JSON.stringify(config, null, '\\t') + '\\n', {\n\t\tmode: 0o600,\n\t});\n\trenameSync(tmp, path);\n}\n\nexport function resolve_telemetry_enabled(\n\tconfig: TelemetryConfig = load_telemetry_config(),\n\toverride?: boolean,\n): boolean {\n\treturn override ?? config.enabled;\n}\n","import type {\n\tAgentEndEvent,\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n} from '@mariozechner/pi-coding-agent';\nimport { randomUUID } from 'node:crypto';\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport {\n\tload_telemetry_config,\n\tresolve_telemetry_db_path,\n\tresolve_telemetry_enabled,\n\tsave_telemetry_config,\n\ttype TelemetryConfig,\n} from './telemetry-config.js';\nimport type {\n\tTelemetryDatabase,\n\tTelemetryQueryFilters,\n\tTelemetryRunSummary,\n\tTelemetryStats,\n} from './telemetry-db.js';\n\ninterface TelemetryStore {\n\tinsert_run: TelemetryDatabase['insert_run'];\n\tfinish_run: TelemetryDatabase['finish_run'];\n\tinsert_turn: TelemetryDatabase['insert_turn'];\n\tfinish_turn: TelemetryDatabase['finish_turn'];\n\tinsert_tool_call: TelemetryDatabase['insert_tool_call'];\n\tnote_tool_update: TelemetryDatabase['note_tool_update'];\n\tfinish_tool_call: TelemetryDatabase['finish_tool_call'];\n\tinsert_provider_request: TelemetryDatabase['insert_provider_request'];\n\tfinish_provider_request: TelemetryDatabase['finish_provider_request'];\n\tget_stats: TelemetryDatabase['get_stats'];\n\tquery_runs: TelemetryDatabase['query_runs'];\n\tclose: TelemetryDatabase['close'];\n}\n\nexport interface CreateTelemetryExtensionOptions {\n\tenabled?: boolean;\n\tdb_path?: string;\n\tcwd?: string;\n\tload_store?: (db_path: string) => Promise<TelemetryStore>;\n\tnow?: () => number;\n}\n\ninterface EvalMetadata {\n\trun_id: string | null;\n\tcase_id: string | null;\n\tattempt: number | null;\n\tsuite: string | null;\n}\n\ninterface ActiveRun {\n\tid: string;\n}\n\ninterface ActiveTurn {\n\tid: string;\n}\n\nconst COMMANDS = [\n\t'status',\n\t'stats',\n\t'query',\n\t'export',\n\t'on',\n\t'off',\n\t'path',\n];\nconst DEFAULT_QUERY_LIMIT = 20;\n\nfunction parse_int(value: string | undefined): number | null {\n\tif (!value) return null;\n\tconst parsed = Number.parseInt(value, 10);\n\treturn Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction get_eval_metadata(): EvalMetadata {\n\treturn {\n\t\trun_id: process.env.MY_PI_EVAL_RUN_ID ?? null,\n\t\tcase_id: process.env.MY_PI_EVAL_CASE_ID ?? null,\n\t\tattempt: parse_int(process.env.MY_PI_EVAL_ATTEMPT),\n\t\tsuite: process.env.MY_PI_EVAL_SUITE ?? null,\n\t};\n}\n\nfunction get_model_identity(model: ExtensionContext['model']): {\n\tprovider: string | null;\n\tid: string | null;\n} {\n\tif (!model) {\n\t\treturn { provider: null, id: null };\n\t}\n\treturn {\n\t\tprovider:\n\t\t\ttypeof model.provider === 'string' ? model.provider : null,\n\t\tid: typeof model.id === 'string' ? model.id : null,\n\t};\n}\n\nfunction get_session_file(ctx: ExtensionContext): string | null {\n\tconst session_manager = ctx.sessionManager as {\n\t\tgetSessionFile?: () => string | undefined;\n\t};\n\treturn session_manager.getSessionFile?.() ?? null;\n}\n\nfunction safe_json_stringify(value: unknown): string | null {\n\tif (value === undefined) return null;\n\ttry {\n\t\treturn JSON.stringify(value);\n\t} catch {\n\t\treturn JSON.stringify({\n\t\t\ttype: typeof value,\n\t\t\tunserializable: true,\n\t\t});\n\t}\n}\n\nfunction summarize_value(value: unknown, depth = 0): unknown {\n\tif (value == null) return null;\n\tif (typeof value === 'string') {\n\t\treturn {\n\t\t\ttype: 'string',\n\t\t\tbytes: Buffer.byteLength(value, 'utf-8'),\n\t\t\tlines: value === '' ? 0 : value.split(/\\r?\\n/).length,\n\t\t};\n\t}\n\tif (\n\t\ttypeof value === 'number' ||\n\t\ttypeof value === 'boolean' ||\n\t\ttypeof value === 'bigint'\n\t) {\n\t\treturn value;\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn {\n\t\t\ttype: 'array',\n\t\t\tlength: value.length,\n\t\t\titems:\n\t\t\t\tdepth >= 1\n\t\t\t\t\t? undefined\n\t\t\t\t\t: value\n\t\t\t\t\t\t\t.slice(0, 5)\n\t\t\t\t\t\t\t.map((item) => summarize_value(item, depth + 1)),\n\t\t};\n\t}\n\tif (typeof value === 'object') {\n\t\tconst entries = Object.entries(value as Record<string, unknown>);\n\t\tconst summary: Record<string, unknown> = {\n\t\t\ttype: 'object',\n\t\t\tkeys: entries.map(([key]) => key).slice(0, 20),\n\t\t};\n\t\tif (depth < 1) {\n\t\t\tfor (const [key, child] of entries.slice(0, 10)) {\n\t\t\t\tif (\n\t\t\t\t\tkey === 'oldText' ||\n\t\t\t\t\tkey === 'newText' ||\n\t\t\t\t\tkey === 'content' ||\n\t\t\t\t\tkey === 'text'\n\t\t\t\t) {\n\t\t\t\t\tsummary[`${key}_summary`] = summarize_value(\n\t\t\t\t\t\tchild,\n\t\t\t\t\t\tdepth + 1,\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tsummary[key] = summarize_value(child, depth + 1);\n\t\t\t}\n\t\t}\n\t\treturn summary;\n\t}\n\treturn {\n\t\ttype: typeof value,\n\t};\n}\n\nfunction summarize_tool_args(\n\ttool_name: string,\n\targs: unknown,\n): string | null {\n\tif (!args || typeof args !== 'object') {\n\t\treturn safe_json_stringify(summarize_value(args));\n\t}\n\n\tconst input = args as Record<string, unknown>;\n\tswitch (tool_name) {\n\t\tcase 'bash':\n\t\t\treturn safe_json_stringify({\n\t\t\t\ttool: tool_name,\n\t\t\t\ttimeout: input.timeout ?? null,\n\t\t\t\tcommand: summarize_value(input.command),\n\t\t\t});\n\t\tcase 'read':\n\t\tcase 'write':\n\t\tcase 'edit':\n\t\t\treturn safe_json_stringify({\n\t\t\t\ttool: tool_name,\n\t\t\t\tpath: typeof input.path === 'string' ? input.path : null,\n\t\t\t\toffset:\n\t\t\t\t\ttypeof input.offset === 'number' ? input.offset : null,\n\t\t\t\tlimit: typeof input.limit === 'number' ? input.limit : null,\n\t\t\t\tcontent: summarize_value(input.content),\n\t\t\t\tedits: summarize_value(input.edits),\n\t\t\t});\n\t\tdefault:\n\t\t\treturn safe_json_stringify({\n\t\t\t\ttool: tool_name,\n\t\t\t\tsummary: summarize_value(args),\n\t\t\t});\n\t}\n}\n\nfunction summarize_tool_result(result: unknown): string | null {\n\treturn safe_json_stringify(summarize_value(result));\n}\n\nfunction summarize_headers(\n\theaders: Record<string, string>,\n): string | null {\n\treturn safe_json_stringify({\n\t\tkeys: Object.keys(headers).slice(0, 20),\n\t\tcount: Object.keys(headers).length,\n\t});\n}\n\nfunction summarize_provider_payload(payload: unknown): string | null {\n\treturn safe_json_stringify(summarize_value(payload));\n}\n\nfunction get_stop_reason(message: unknown): string | null {\n\tif (!message || typeof message !== 'object') return null;\n\tconst stop_reason = (message as { stopReason?: unknown })\n\t\t.stopReason;\n\treturn typeof stop_reason === 'string' ? stop_reason : null;\n}\n\nfunction get_error_message(message: unknown): string | null {\n\tif (!message || typeof message !== 'object') return null;\n\tconst error_message = (message as { errorMessage?: unknown })\n\t\t.errorMessage;\n\treturn typeof error_message === 'string' ? error_message : null;\n}\n\nexport function infer_run_outcome(event: AgentEndEvent): {\n\tsuccess: boolean | null;\n\terror_message: string | null;\n} {\n\tconst assistant_messages = event.messages.filter(\n\t\t(message) => message.role === 'assistant',\n\t);\n\tconst last_assistant = assistant_messages.at(-1);\n\tconst stop_reason = get_stop_reason(last_assistant);\n\tif (stop_reason === 'error') {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror_message:\n\t\t\t\tget_error_message(last_assistant) ?? 'agent error',\n\t\t};\n\t}\n\tif (stop_reason === 'aborted') {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror_message:\n\t\t\t\tget_error_message(last_assistant) ?? 'agent aborted',\n\t\t};\n\t}\n\treturn {\n\t\tsuccess: true,\n\t\terror_message: null,\n\t};\n}\n\nexport function format_telemetry_status(options: {\n\tsaved_enabled: boolean;\n\teffective_enabled: boolean;\n\toverride?: boolean;\n\tdb_path: string;\n}): string {\n\tconst override_label =\n\t\toptions.override === undefined\n\t\t\t? 'none'\n\t\t\t: options.override\n\t\t\t\t? '--telemetry'\n\t\t\t\t: '--no-telemetry';\n\n\treturn [\n\t\t`telemetry ${options.effective_enabled ? 'enabled' : 'disabled'} now`,\n\t\t`default ${options.saved_enabled ? 'enabled' : 'disabled'}`,\n\t\t`override ${override_label}`,\n\t\t`db ${options.db_path}`,\n\t].join('\\n');\n}\n\nfunction format_bytes(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) {\n\t\treturn `${(bytes / 1024).toFixed(1)} KiB`;\n\t}\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;\n}\n\nfunction format_timestamp(timestamp: number): string {\n\treturn new Date(timestamp).toISOString();\n}\n\nfunction format_duration(duration_ms: number | null): string {\n\tif (duration_ms === null) return 'open';\n\tif (duration_ms < 1000) return `${duration_ms}ms`;\n\tif (duration_ms < 60_000) {\n\t\treturn `${(duration_ms / 1000).toFixed(1)}s`;\n\t}\n\treturn `${(duration_ms / 60_000).toFixed(1)}m`;\n}\n\nfunction format_success(value: boolean | null): string {\n\tif (value === true) return 'success';\n\tif (value === false) return 'failure';\n\treturn 'unknown';\n}\n\nfunction tokenize_command_args(input: string): string[] {\n\tconst matches =\n\t\tinput.match(/\"(?:\\\\.|[^\"\\\\])*\"|'(?:\\\\.|[^'\\\\])*'|\\S+/g) ?? [];\n\treturn matches.map((token) => {\n\t\tif (\n\t\t\t(token.startsWith('\"') && token.endsWith('\"')) ||\n\t\t\t(token.startsWith(\"'\") && token.endsWith(\"'\"))\n\t\t) {\n\t\t\treturn token.slice(1, -1);\n\t\t}\n\t\treturn token;\n\t});\n}\n\nexport interface ParsedTelemetryCommand {\n\tsubcommand: string;\n\texport_path: string | null;\n\tfilters: TelemetryQueryFilters;\n\terrors: string[];\n}\n\nexport function parse_telemetry_command(\n\tinput: string,\n): ParsedTelemetryCommand {\n\tconst tokens = tokenize_command_args(input.trim());\n\tconst subcommand = tokens[0] ?? 'status';\n\tconst filters: TelemetryQueryFilters = {};\n\tlet export_path: string | null = null;\n\tconst errors: string[] = [];\n\n\tfor (const token of tokens.slice(1)) {\n\t\tconst equals_index = token.indexOf('=');\n\t\tif (equals_index === -1) {\n\t\t\tif (subcommand === 'export' && export_path === null) {\n\t\t\t\texport_path = token;\n\t\t\t} else {\n\t\t\t\terrors.push(`Unexpected argument: ${token}`);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst key = token.slice(0, equals_index);\n\t\tconst value = token.slice(equals_index + 1);\n\t\tswitch (key) {\n\t\t\tcase 'eval_run_id':\n\t\t\tcase 'run':\n\t\t\t\tfilters.eval_run_id = value;\n\t\t\t\tbreak;\n\t\t\tcase 'eval_case_id':\n\t\t\tcase 'case':\n\t\t\t\tfilters.eval_case_id = value;\n\t\t\t\tbreak;\n\t\t\tcase 'eval_suite':\n\t\t\tcase 'suite':\n\t\t\t\tfilters.eval_suite = value;\n\t\t\t\tbreak;\n\t\t\tcase 'success':\n\t\t\t\tif (value === 'true') filters.success = true;\n\t\t\t\telse if (value === 'false') filters.success = false;\n\t\t\t\telse if (value === 'null') filters.success = null;\n\t\t\t\telse {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Invalid success value: ${value}. Use true, false, or null`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'limit': {\n\t\t\t\tconst parsed = Number.parseInt(value, 10);\n\t\t\t\tif (!Number.isFinite(parsed) || parsed <= 0) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Invalid limit value: ${value}. Use a positive integer`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tfilters.limit = parsed;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\terrors.push(`Unknown filter: ${key}`);\n\t\t}\n\t}\n\n\tif (subcommand === 'query' && filters.limit === undefined) {\n\t\tfilters.limit = DEFAULT_QUERY_LIMIT;\n\t}\n\n\treturn {\n\t\tsubcommand,\n\t\texport_path,\n\t\tfilters,\n\t\terrors,\n\t};\n}\n\nfunction format_filter_summary(\n\tfilters: TelemetryQueryFilters,\n): string {\n\tconst parts: string[] = [];\n\tif (filters.eval_run_id !== undefined) {\n\t\tparts.push(`eval_run_id=${filters.eval_run_id}`);\n\t}\n\tif (filters.eval_case_id !== undefined) {\n\t\tparts.push(`eval_case_id=${filters.eval_case_id}`);\n\t}\n\tif (filters.eval_suite !== undefined) {\n\t\tparts.push(`eval_suite=${filters.eval_suite}`);\n\t}\n\tif (filters.success !== undefined) {\n\t\tparts.push(`success=${String(filters.success)}`);\n\t}\n\tif (filters.limit !== undefined) {\n\t\tparts.push(`limit=${filters.limit}`);\n\t}\n\treturn parts.length > 0 ? parts.join(' ') : 'none';\n}\n\nexport function format_telemetry_stats(options: {\n\tdb_path: string;\n\tstats: TelemetryStats;\n}): string {\n\treturn [\n\t\t`db ${options.db_path}`,\n\t\t`schema v${options.stats.schema_version}`,\n\t\t`runs ${options.stats.runs}`,\n\t\t`turns ${options.stats.turns}`,\n\t\t`tool_calls ${options.stats.tool_calls}`,\n\t\t`provider_requests ${options.stats.provider_requests}`,\n\t\t`db_bytes ${format_bytes(options.stats.db_bytes)}`,\n\t\t`wal_bytes ${format_bytes(options.stats.wal_bytes)}`,\n\t\t`total_bytes ${format_bytes(options.stats.total_bytes)}`,\n\t].join('\\n');\n}\n\nexport function format_telemetry_query_results(options: {\n\tdb_path: string;\n\tfilters: TelemetryQueryFilters;\n\truns: TelemetryRunSummary[];\n}): string {\n\tif (options.runs.length === 0) {\n\t\treturn [\n\t\t\t`db ${options.db_path}`,\n\t\t\t`filters ${format_filter_summary(options.filters)}`,\n\t\t\t'no matching runs',\n\t\t].join('\\n');\n\t}\n\n\treturn [\n\t\t`db ${options.db_path}`,\n\t\t`filters ${format_filter_summary(options.filters)}`,\n\t\t...options.runs.map((run) =>\n\t\t\t[\n\t\t\t\t`${format_timestamp(run.started_at)} ${run.id}`,\n\t\t\t\t`status=${format_success(run.success)}`,\n\t\t\t\t`duration=${format_duration(run.duration_ms)}`,\n\t\t\t\t`turns=${run.turn_count}`,\n\t\t\t\t`tools=${run.tool_call_count}`,\n\t\t\t\t`tool_errors=${run.tool_error_count}`,\n\t\t\t\t`provider_requests=${run.provider_request_count}`,\n\t\t\t\trun.eval_run_id ? `eval_run_id=${run.eval_run_id}` : null,\n\t\t\t\trun.eval_case_id ? `eval_case_id=${run.eval_case_id}` : null,\n\t\t\t\trun.eval_suite ? `eval_suite=${run.eval_suite}` : null,\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(' '),\n\t\t),\n\t].join('\\n');\n}\n\nfunction get_default_telemetry_export_path(cwd: string): string {\n\tconst stamp = new Date().toISOString().replace(/[:.]/g, '-');\n\treturn resolve(cwd, `telemetry-export-${stamp}.json`);\n}\n\nasync function default_load_store(\n\tdb_path: string,\n): Promise<TelemetryStore> {\n\tconst { TelemetryDatabase } = await import('./telemetry-db.js');\n\treturn TelemetryDatabase.open(db_path);\n}\n\nexport function create_telemetry_extension(\n\toptions: CreateTelemetryExtensionOptions = {},\n) {\n\treturn async function telemetry(pi: ExtensionAPI) {\n\t\tconst now = options.now ?? (() => Date.now());\n\t\tconst load_store = options.load_store ?? default_load_store;\n\t\tconst cwd = options.cwd ?? process.cwd();\n\t\tconst db_path = resolve_telemetry_db_path(cwd, options.db_path);\n\t\tlet config: TelemetryConfig = load_telemetry_config();\n\t\tlet store: TelemetryStore | null = null;\n\t\tlet effective_enabled = resolve_telemetry_enabled(\n\t\t\tconfig,\n\t\t\toptions.enabled,\n\t\t);\n\t\tlet current_model = {\n\t\t\tprovider: null as string | null,\n\t\t\tid: null as string | null,\n\t\t};\n\t\tlet active_run: ActiveRun | null = null;\n\t\tconst active_turns = new Map<number, ActiveTurn>();\n\t\tconst provider_request_ids: string[] = [];\n\n\t\tasync function ensure_store(): Promise<TelemetryStore | null> {\n\t\t\tif (!effective_enabled) return null;\n\t\t\tif (!store) {\n\t\t\t\tstore = await load_store(db_path);\n\t\t\t}\n\t\t\treturn store;\n\t\t}\n\n\t\tfunction finish_active_run_on_disable(reason: string): void {\n\t\t\tif (!store || !active_run) return;\n\t\t\tstore.finish_run({\n\t\t\t\tid: active_run.id,\n\t\t\t\tended_at: now(),\n\t\t\t\tsuccess: null,\n\t\t\t\terror_message: reason,\n\t\t\t});\n\t\t\tactive_run = null;\n\t\t\tactive_turns.clear();\n\t\t\tprovider_request_ids.length = 0;\n\t\t}\n\n\t\tfunction close_store(): void {\n\t\t\tif (!store) return;\n\t\t\tstore.close();\n\t\t\tstore = null;\n\t\t}\n\n\t\tfunction command_message(\n\t\t\tctx: ExtensionCommandContext,\n\t\t\tmessage: string,\n\t\t): void {\n\t\t\tif (ctx.hasUI) {\n\t\t\t\tctx.ui.notify(message);\n\t\t\t} else {\n\t\t\t\tconsole.error(message);\n\t\t\t}\n\t\t}\n\n\t\tpi.registerCommand('telemetry', {\n\t\t\tdescription:\n\t\t\t\t'Manage local SQLite telemetry for evals and debugging',\n\t\t\tgetArgumentCompletions: (prefix) => {\n\t\t\t\tconst trimmed = prefix.trim();\n\t\t\t\tconst first_token = trimmed.split(/\\s+/, 1)[0] ?? '';\n\t\t\t\treturn COMMANDS.filter((command) =>\n\t\t\t\t\tcommand.startsWith(first_token),\n\t\t\t\t).map((command) => ({ value: command, label: command }));\n\t\t\t},\n\t\t\thandler: async (args, ctx) => {\n\t\t\t\tconst parsed = parse_telemetry_command(args);\n\t\t\t\tconst subcommand = parsed.subcommand;\n\t\t\t\tif (!COMMANDS.includes(subcommand)) {\n\t\t\t\t\tcommand_message(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t`Unknown telemetry command: ${subcommand}. Use: ${COMMANDS.join(', ')}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (parsed.errors.length > 0) {\n\t\t\t\t\tcommand_message(ctx, parsed.errors.join('\\n'));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (subcommand === 'status') {\n\t\t\t\t\tcommand_message(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\tformat_telemetry_status({\n\t\t\t\t\t\t\tsaved_enabled: config.enabled,\n\t\t\t\t\t\t\teffective_enabled,\n\t\t\t\t\t\t\toverride: options.enabled,\n\t\t\t\t\t\t\tdb_path,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (subcommand === 'stats') {\n\t\t\t\t\tif (!existsSync(db_path)) {\n\t\t\t\t\t\tcommand_message(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t`No telemetry database at ${db_path}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst stats_store = store ?? (await load_store(db_path));\n\t\t\t\t\tconst should_close_after = stats_store !== store;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tcommand_message(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\tformat_telemetry_stats({\n\t\t\t\t\t\t\t\tdb_path,\n\t\t\t\t\t\t\t\tstats: stats_store.get_stats(),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif (should_close_after) {\n\t\t\t\t\t\t\tstats_store.close();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (subcommand === 'query' || subcommand === 'export') {\n\t\t\t\t\tif (!existsSync(db_path)) {\n\t\t\t\t\t\tcommand_message(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t`No telemetry database at ${db_path}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst query_store = store ?? (await load_store(db_path));\n\t\t\t\t\tconst should_close_after = query_store !== store;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst runs = query_store.query_runs(parsed.filters);\n\t\t\t\t\t\tif (subcommand === 'query') {\n\t\t\t\t\t\t\tcommand_message(\n\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\tformat_telemetry_query_results({\n\t\t\t\t\t\t\t\t\tdb_path,\n\t\t\t\t\t\t\t\t\tfilters: parsed.filters,\n\t\t\t\t\t\t\t\t\truns,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst export_path = resolve(\n\t\t\t\t\t\t\tcwd,\n\t\t\t\t\t\t\tparsed.export_path ??\n\t\t\t\t\t\t\t\tget_default_telemetry_export_path(cwd),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmkdirSync(dirname(export_path), { recursive: true });\n\t\t\t\t\t\twriteFileSync(\n\t\t\t\t\t\t\texport_path,\n\t\t\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\texported_at: new Date().toISOString(),\n\t\t\t\t\t\t\t\t\tdb_path,\n\t\t\t\t\t\t\t\t\tschema_version:\n\t\t\t\t\t\t\t\t\t\tquery_store.get_stats().schema_version,\n\t\t\t\t\t\t\t\t\tfilters: parsed.filters,\n\t\t\t\t\t\t\t\t\truns,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t'utf-8',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcommand_message(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t`Exported ${runs.length} telemetry run${runs.length === 1 ? '' : 's'} to ${export_path}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif (should_close_after) {\n\t\t\t\t\t\t\tquery_store.close();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (subcommand === 'path') {\n\t\t\t\t\tcommand_message(ctx, db_path);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst next_enabled = subcommand === 'on';\n\t\t\t\tconfig = { ...config, enabled: next_enabled };\n\t\t\t\tsave_telemetry_config(config);\n\n\t\t\t\tif (options.enabled !== undefined) {\n\t\t\t\t\tcommand_message(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t`Saved default telemetry ${next_enabled ? 'enabled' : 'disabled'}.`,\n\t\t\t\t\t\t\t`Current process still uses ${options.enabled ? '--telemetry' : '--no-telemetry'}.`,\n\t\t\t\t\t\t].join(' '),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\teffective_enabled = next_enabled;\n\t\t\t\tif (effective_enabled) {\n\t\t\t\t\tawait ensure_store();\n\t\t\t\t\tcommand_message(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t`Telemetry enabled. Writing to ${db_path}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tfinish_active_run_on_disable('telemetry disabled');\n\t\t\t\tclose_store();\n\t\t\t\tcommand_message(ctx, 'Telemetry disabled.');\n\t\t\t},\n\t\t});\n\n\t\tpi.on('model_select', async (event) => {\n\t\t\tcurrent_model = get_model_identity(event.model);\n\t\t});\n\n\t\tpi.on('agent_start', async (_event, ctx) => {\n\t\t\tconst active_store = await ensure_store();\n\t\t\tif (!active_store) return;\n\n\t\t\tconst run_id = randomUUID();\n\t\t\tconst eval_metadata = get_eval_metadata();\n\t\t\tconst model_identity = ctx.model\n\t\t\t\t? get_model_identity(ctx.model)\n\t\t\t\t: current_model;\n\t\t\tactive_store.insert_run({\n\t\t\t\tid: run_id,\n\t\t\t\tsession_file: get_session_file(ctx),\n\t\t\t\tcwd: ctx.cwd,\n\t\t\t\tstarted_at: now(),\n\t\t\t\tmodel_provider: model_identity.provider,\n\t\t\t\tmodel_id: model_identity.id,\n\t\t\t\teval_run_id: eval_metadata.run_id,\n\t\t\t\teval_case_id: eval_metadata.case_id,\n\t\t\t\teval_attempt: eval_metadata.attempt,\n\t\t\t\teval_suite: eval_metadata.suite,\n\t\t\t});\n\t\t\tactive_run = {\n\t\t\t\tid: run_id,\n\t\t\t};\n\t\t\tactive_turns.clear();\n\t\t\tprovider_request_ids.length = 0;\n\t\t});\n\n\t\tpi.on('agent_end', async (event) => {\n\t\t\tif (!store || !active_run) return;\n\t\t\tconst outcome = infer_run_outcome(event);\n\t\t\tstore.finish_run({\n\t\t\t\tid: active_run.id,\n\t\t\t\tended_at: now(),\n\t\t\t\tsuccess: outcome.success,\n\t\t\t\terror_message: outcome.error_message,\n\t\t\t});\n\t\t\tactive_run = null;\n\t\t\tactive_turns.clear();\n\t\t\tprovider_request_ids.length = 0;\n\t\t});\n\n\t\tpi.on('turn_start', async (event) => {\n\t\t\tif (!store || !active_run) return;\n\t\t\tconst turn_id = `${active_run.id}:turn:${event.turnIndex}`;\n\t\t\tactive_turns.set(event.turnIndex, {\n\t\t\t\tid: turn_id,\n\t\t\t});\n\t\t\tstore.insert_turn({\n\t\t\t\tid: turn_id,\n\t\t\t\trun_id: active_run.id,\n\t\t\t\tturn_index: event.turnIndex,\n\t\t\t\tstarted_at: event.timestamp,\n\t\t\t});\n\t\t});\n\n\t\tpi.on('turn_end', async (event) => {\n\t\t\tconst active_turn = active_turns.get(event.turnIndex);\n\t\t\tif (!store || !active_turn) return;\n\t\t\tstore.finish_turn({\n\t\t\t\tid: active_turn.id,\n\t\t\t\tended_at: now(),\n\t\t\t\ttool_result_count: event.toolResults.length,\n\t\t\t\tstop_reason: get_stop_reason(event.message),\n\t\t\t});\n\t\t\tactive_turns.delete(event.turnIndex);\n\t\t});\n\n\t\tpi.on('tool_execution_start', async (event) => {\n\t\t\tif (!store || !active_run) return;\n\t\t\tconst current_turn = [...active_turns.values()].at(-1);\n\t\t\tstore.insert_tool_call({\n\t\t\t\ttool_call_id: event.toolCallId,\n\t\t\t\trun_id: active_run.id,\n\t\t\t\tturn_id: current_turn?.id ?? null,\n\t\t\t\ttool_name: event.toolName,\n\t\t\t\tstarted_at: now(),\n\t\t\t\targs_summary_json: summarize_tool_args(\n\t\t\t\t\tevent.toolName,\n\t\t\t\t\tevent.args,\n\t\t\t\t),\n\t\t\t});\n\t\t});\n\n\t\tpi.on('tool_execution_update', async (event) => {\n\t\t\tif (!store || !active_run) return;\n\t\t\tstore.note_tool_update(event.toolCallId);\n\t\t});\n\n\t\tpi.on('tool_execution_end', async (event) => {\n\t\t\tif (!store || !active_run) return;\n\t\t\tstore.finish_tool_call({\n\t\t\t\ttool_call_id: event.toolCallId,\n\t\t\t\tended_at: now(),\n\t\t\t\tis_error: event.isError,\n\t\t\t\tresult_summary_json: summarize_tool_result(event.result),\n\t\t\t\terror_message:\n\t\t\t\t\tevent.isError && event.result != null\n\t\t\t\t\t\t? safe_json_stringify(summarize_value(event.result))\n\t\t\t\t\t\t: null,\n\t\t\t});\n\t\t});\n\n\t\tpi.on('before_provider_request', async (event) => {\n\t\t\tif (!store || !active_run) return;\n\t\t\tconst request_id = randomUUID();\n\t\t\tconst current_turn = [...active_turns.values()].at(-1);\n\t\t\tstore.insert_provider_request({\n\t\t\t\tid: request_id,\n\t\t\t\trun_id: active_run.id,\n\t\t\t\tturn_id: current_turn?.id ?? null,\n\t\t\t\tstarted_at: now(),\n\t\t\t\tpayload_summary_json: summarize_provider_payload(\n\t\t\t\t\tevent.payload,\n\t\t\t\t),\n\t\t\t});\n\t\t\tprovider_request_ids.push(request_id);\n\t\t});\n\n\t\tpi.on('after_provider_response', async (event) => {\n\t\t\tif (!store || !active_run) return;\n\t\t\tconst request_id = provider_request_ids.shift();\n\t\t\tif (!request_id) return;\n\t\t\tstore.finish_provider_request({\n\t\t\t\tid: request_id,\n\t\t\t\tended_at: now(),\n\t\t\t\tstatus_code: event.status,\n\t\t\t\theaders_json: summarize_headers(event.headers),\n\t\t\t});\n\t\t});\n\n\t\tpi.on('session_shutdown', async () => {\n\t\t\tif (store && active_run) {\n\t\t\t\tstore.finish_run({\n\t\t\t\t\tid: active_run.id,\n\t\t\t\t\tended_at: now(),\n\t\t\t\t\tsuccess: null,\n\t\t\t\t\terror_message: 'session shutdown',\n\t\t\t\t});\n\t\t\t}\n\t\t\tclose_store();\n\t\t\tactive_run = null;\n\t\t\tactive_turns.clear();\n\t\t\tprovider_request_ids.length = 0;\n\t\t});\n\t};\n}\n\nexport default create_telemetry_extension();\n","// Composable programmatic API for my-pi\n// Extension loading patterns inspired by pi-vs-claude-code\n\nimport {\n\tInteractiveMode,\n\tSessionManager,\n\tSettingsManager,\n\tcreateAgentSessionFromServices,\n\tcreateAgentSessionRuntime,\n\tcreateAgentSessionServices,\n\tgetAgentDir,\n\trunPrintMode,\n\ttype ExtensionFactory,\n\ttype LoadExtensionsResult,\n} from '@mariozechner/pi-coding-agent';\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport chain_extension from './extensions/chain.js';\nimport {\n\tBUILTIN_EXTENSIONS,\n\tis_builtin_extension_active,\n\tload_builtin_extensions_config,\n\ttype BuiltinExtensionKey,\n} from './extensions/config.js';\nimport { create_extensions_extension } from './extensions/extensions.js';\nimport filter_output_extension from './extensions/filter-output.js';\nimport handoff_extension from './extensions/handoff.js';\nimport lsp_extension from './extensions/lsp.js';\nimport mcp_extension from './extensions/mcp.js';\nimport prompt_presets_extension from './extensions/prompt-presets.js';\nimport recall_extension from './extensions/recall.js';\nimport session_name_extension from './extensions/session-name.js';\nimport skills_extension from './extensions/skills.js';\nimport { create_telemetry_extension } from './extensions/telemetry.js';\nimport { create_skills_manager } from './skills/manager.js';\n\nexport interface CreateMyPiOptions {\n\tcwd?: string;\n\tagent_dir?: string;\n\textensions?: string[];\n\textensionFactories?: ExtensionFactory[];\n\tmcp?: boolean;\n\tskills?: boolean;\n\tchain?: boolean;\n\tfilter_output?: boolean;\n\thandoff?: boolean;\n\trecall?: boolean;\n\tprompt_presets?: boolean;\n\tlsp?: boolean;\n\tsession_name?: boolean;\n\ttelemetry?: boolean;\n\ttelemetry_db_path?: string;\n\tmodel?: string;\n\tsystem_prompt?: string;\n\tappend_system_prompt?: string;\n}\n\nconst BUILTIN_EXTENSION_FACTORIES: Record<\n\tBuiltinExtensionKey,\n\tExtensionFactory\n> = {\n\tmcp: mcp_extension,\n\tskills: skills_extension,\n\tchain: chain_extension,\n\t'filter-output': filter_output_extension,\n\thandoff: handoff_extension,\n\trecall: recall_extension,\n\t'prompt-presets': prompt_presets_extension,\n\tlsp: lsp_extension,\n\t'session-name': session_name_extension,\n};\n\nconst MODULE_DIR = dirname(fileURLToPath(import.meta.url));\nconst PACKAGE_THEME_DIR = resolve(MODULE_DIR, '..', 'themes');\nconst PI_AGENT_DIR_ENV = 'PI_CODING_AGENT_DIR';\n\nfunction resolve_agent_dir(cwd: string, agent_dir?: string): string {\n\treturn agent_dir ? resolve(cwd, agent_dir) : getAgentDir();\n}\n\nfunction get_force_disabled_builtins(\n\toptions: Pick<\n\t\tCreateMyPiOptions,\n\t\t| 'mcp'\n\t\t| 'skills'\n\t\t| 'chain'\n\t\t| 'filter_output'\n\t\t| 'handoff'\n\t\t| 'recall'\n\t\t| 'prompt_presets'\n\t\t| 'lsp'\n\t\t| 'session_name'\n\t>,\n): ReadonlySet<BuiltinExtensionKey> {\n\tconst force_disabled = new Set<BuiltinExtensionKey>();\n\tif (!options.mcp) force_disabled.add('mcp');\n\tif (!options.skills) force_disabled.add('skills');\n\tif (!options.chain) force_disabled.add('chain');\n\tif (!options.filter_output) force_disabled.add('filter-output');\n\tif (!options.handoff) force_disabled.add('handoff');\n\tif (!options.recall) force_disabled.add('recall');\n\tif (!options.prompt_presets) force_disabled.add('prompt-presets');\n\tif (!options.lsp) force_disabled.add('lsp');\n\tif (!options.session_name) force_disabled.add('session-name');\n\treturn force_disabled;\n}\n\nfunction create_builtin_extension_factory(\n\tkey: BuiltinExtensionKey,\n\textension: ExtensionFactory,\n\tforce_disabled: ReadonlySet<BuiltinExtensionKey>,\n): ExtensionFactory {\n\treturn async (pi) => {\n\t\tconst config = load_builtin_extensions_config();\n\t\tif (!is_builtin_extension_active(config, key, force_disabled)) {\n\t\t\treturn;\n\t\t}\n\t\tawait extension(pi);\n\t};\n}\n\nfunction create_extensions_override(\n\tmanaged_inline_paths: string[],\n): (base: LoadExtensionsResult) => LoadExtensionsResult {\n\tconst managed_paths = new Set(managed_inline_paths);\n\treturn (base) => {\n\t\tconst managed = new Map(\n\t\t\tbase.extensions.map((extension) => [extension.path, extension]),\n\t\t);\n\t\tconst ordered_managed = managed_inline_paths\n\t\t\t.map((path) => managed.get(path))\n\t\t\t.filter(\n\t\t\t\t(\n\t\t\t\t\textension,\n\t\t\t\t): extension is LoadExtensionsResult['extensions'][number] =>\n\t\t\t\t\tBoolean(extension),\n\t\t\t);\n\t\tconst others = base.extensions.filter(\n\t\t\t(extension) => !managed_paths.has(extension.path),\n\t\t);\n\t\treturn {\n\t\t\t...base,\n\t\t\textensions: [...ordered_managed, ...others],\n\t\t};\n\t};\n}\n\nexport async function create_my_pi(options: CreateMyPiOptions = {}) {\n\tconst {\n\t\tcwd = process.cwd(),\n\t\tagent_dir,\n\t\textensions = [],\n\t\textensionFactories: user_factories = [],\n\t\tmcp = true,\n\t\tskills = true,\n\t\tchain = true,\n\t\tfilter_output = true,\n\t\thandoff = true,\n\t\trecall = true,\n\t\tprompt_presets = true,\n\t\tlsp = true,\n\t\tsession_name = true,\n\t\ttelemetry,\n\t\ttelemetry_db_path,\n\t\tmodel,\n\t\tsystem_prompt,\n\t\tappend_system_prompt,\n\t} = options;\n\n\tconst effective_agent_dir = resolve_agent_dir(cwd, agent_dir);\n\tif (agent_dir) {\n\t\tprocess.env[PI_AGENT_DIR_ENV] = effective_agent_dir;\n\t}\n\n\tconst resolved_extensions = extensions.map((p) => resolve(cwd, p));\n\tconst force_disabled = get_force_disabled_builtins({\n\t\tmcp,\n\t\tskills,\n\t\tchain,\n\t\tfilter_output,\n\t\thandoff,\n\t\trecall,\n\t\tprompt_presets,\n\t\tlsp,\n\t\tsession_name,\n\t});\n\tconst managed_extension_factories: ExtensionFactory[] = [\n\t\tcreate_telemetry_extension({\n\t\t\tenabled: telemetry,\n\t\t\tdb_path: telemetry_db_path,\n\t\t\tcwd,\n\t\t}),\n\t\tcreate_extensions_extension({ force_disabled }),\n\t\t...BUILTIN_EXTENSIONS.map((extension) =>\n\t\t\tcreate_builtin_extension_factory(\n\t\t\t\textension.key,\n\t\t\t\tBUILTIN_EXTENSION_FACTORIES[extension.key],\n\t\t\t\tforce_disabled,\n\t\t\t),\n\t\t),\n\t];\n\tconst managed_inline_paths = managed_extension_factories.map(\n\t\t(_, index) => `<inline:${index + 1}>`,\n\t);\n\n\tconst create_runtime = async ({\n\t\tcwd: runtime_cwd,\n\t\tsessionManager,\n\t\tsessionStartEvent,\n\t}: {\n\t\tcwd: string;\n\t\tsessionManager: SessionManager;\n\t\tsessionStartEvent?: unknown;\n\t}) => {\n\t\tconst settings_manager = model\n\t\t\t? (() => {\n\t\t\t\t\tconst sm = SettingsManager.create(\n\t\t\t\t\t\truntime_cwd,\n\t\t\t\t\t\teffective_agent_dir,\n\t\t\t\t\t);\n\t\t\t\t\tsm.setDefaultModel(model);\n\t\t\t\t\treturn sm;\n\t\t\t\t})()\n\t\t\t: undefined;\n\n\t\tconst services = await createAgentSessionServices({\n\t\t\tcwd: runtime_cwd,\n\t\t\tagentDir: effective_agent_dir,\n\t\t\t...(settings_manager\n\t\t\t\t? { settingsManager: settings_manager }\n\t\t\t\t: {}),\n\t\t\tresourceLoaderOptions: {\n\t\t\t\t...(system_prompt !== undefined\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tsystemPromptOverride: () => system_prompt,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\t...(append_system_prompt !== undefined\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tappendSystemPromptOverride: (base: string[]) => [\n\t\t\t\t\t\t\t\t...base,\n\t\t\t\t\t\t\t\tappend_system_prompt,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\tadditionalExtensionPaths: [...resolved_extensions],\n\t\t\t\tadditionalThemePaths: [PACKAGE_THEME_DIR],\n\t\t\t\textensionFactories: [\n\t\t\t\t\t...managed_extension_factories,\n\t\t\t\t\t...user_factories,\n\t\t\t\t],\n\t\t\t\textensionsOverride: create_extensions_override(\n\t\t\t\t\tmanaged_inline_paths,\n\t\t\t\t),\n\t\t\t\tskillsOverride: (base: any) => {\n\t\t\t\t\tconst config = load_builtin_extensions_config();\n\t\t\t\t\tif (\n\t\t\t\t\t\t!is_builtin_extension_active(\n\t\t\t\t\t\t\tconfig,\n\t\t\t\t\t\t\t'skills',\n\t\t\t\t\t\t\tforce_disabled,\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn base;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst skills_manager = create_skills_manager();\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...base,\n\t\t\t\t\t\tskills: base.skills.filter((skill: any) =>\n\t\t\t\t\t\t\tskills_manager.is_enabled_by_skill(\n\t\t\t\t\t\t\t\tskill.name,\n\t\t\t\t\t\t\t\tskill.filePath,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t} as any,\n\t\t});\n\n\t\treturn {\n\t\t\t...(await createAgentSessionFromServices({\n\t\t\t\tservices,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: sessionStartEvent as any,\n\t\t\t})),\n\t\t\tservices,\n\t\t\tdiagnostics: services.diagnostics,\n\t\t};\n\t};\n\n\treturn createAgentSessionRuntime(create_runtime, {\n\t\tcwd,\n\t\tagentDir: effective_agent_dir,\n\t\tsessionManager: SessionManager.create(cwd),\n\t});\n}\n\nexport { InteractiveMode, runPrintMode };\n\nexport type {\n\tAgentSessionRuntime,\n\tExtensionFactory,\n\tInteractiveModeOptions,\n\tPrintModeOptions,\n} from '@mariozechner/pi-coding-agent';\n"],"mappings":"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"}
|