my-pi 0.0.7 → 0.0.8

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-BA6XuDOE.js","names":["DEFAULT_CONFIG","ENABLED","DISABLED","to_setting_item","sets_equal","#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","mcp_extension","skills_extension","chain_extension","filter_output_extension","handoff_extension","recall_extension","prompt_presets_extension"],"sources":["../src/extensions/chain.ts","../src/extensions/config.ts","../src/extensions/extensions.ts","../src/extensions/filter-output.ts","../src/extensions/handoff.ts","../src/mcp/client.ts","../src/mcp/config.ts","../src/extensions/mcp.ts","../src/extensions/prompt-presets.ts","../src/extensions/recall.ts","../src/skills/config.ts","../src/skills/scanner.ts","../src/skills/importer.ts","../src/skills/manager.ts","../src/extensions/skills.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\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: 'Session handoff export and /handoff command',\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];\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{\n\t\tname: 'AWS Secret Key',\n\t\tpattern:\n\t\t\t/(?:SecretAccessKey|aws_secret_access_key)\\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: /-----BEGIN\\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/(?:password|passwd|secret|token)\\s*[:=]\\s*[\"']?[^\\s\"']{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];\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\t// Reset lastIndex for global regexes\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\n// Default export for Pi Package / additionalExtensionPaths loading\nexport default async function filter_output(pi: ExtensionAPI) {\n\tlet totalRedacted = 0;\n\n\t// Intercept tool results to redact secrets before the LLM sees them\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 — extract session context for a new session\n// Inspired by jayshah5696/pi-agent-extensions\n\nimport type { ExtensionAPI } from '@mariozechner/pi-coding-agent';\nimport { writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\n// Default export for Pi Package / additionalExtensionPaths loading\nexport default async function handoff(pi: ExtensionAPI) {\n\tconst history: Array<{\n\t\trole: string;\n\t\tsummary: string;\n\t\ttimestamp: number;\n\t}> = [];\n\n\t// Track conversation turns\n\tpi.on('message_end', async (event) => {\n\t\tconst msg = event.message as unknown as Record<string, unknown>;\n\t\tif (!msg) return;\n\n\t\tconst content = msg.content as\n\t\t\t| Array<{ type: string; text?: string }>\n\t\t\t| undefined;\n\t\tif (!Array.isArray(content)) return;\n\n\t\tconst text = content\n\t\t\t.filter((c) => c.type === 'text')\n\t\t\t.map((c) => c.text || '')\n\t\t\t.join('\\n');\n\n\t\tif (!text) return;\n\n\t\tconst summary =\n\t\t\ttext.length > 200 ? text.slice(0, 200) + '...' : text;\n\n\t\thistory.push({\n\t\t\trole: (msg.role as string) || 'unknown',\n\t\t\tsummary,\n\t\t\ttimestamp: Date.now(),\n\t\t});\n\t});\n\n\tpi.registerCommand('handoff', {\n\t\tdescription:\n\t\t\t'Export session context as a handoff prompt for a new session',\n\t\thandler: async (args, ctx) => {\n\t\t\tconst task = args.trim();\n\n\t\t\tif (history.length === 0) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t'No conversation history to hand off',\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 context = history\n\t\t\t\t.map((h) => `[${h.role}] ${h.summary}`)\n\t\t\t\t.join('\\n\\n');\n\n\t\t\tconst handoff = `## Handoff from Previous Session\n\n### Context\nThe previous session covered the following:\n\n${context}\n\n### Task\n${task || 'Continue from where the previous session left off.'}\n\n### Instructions\n- Review the context above to understand what was done\n- Do NOT repeat work that was already completed\n- Focus on the task described above\n`;\n\n\t\t\t// Write to file\n\t\t\tconst filename = `handoff-${Date.now()}.md`;\n\t\t\tconst filepath = join(ctx.cwd, filename);\n\t\t\twriteFileSync(filepath, handoff, 'utf-8');\n\n\t\t\tctx.ui.notify(\n\t\t\t\t`Handoff written to ${filename}\\n\\nUse: my-pi < ${filename}`,\n\t\t\t);\n\t\t},\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}\n\n// Default export for Pi Package / additionalExtensionPaths loading\nexport default async function mcp(pi: ExtensionAPI) {\n\tconst cwd = process.cwd();\n\tconst servers = new Map<string, ServerState>();\n\tconst configs = load_mcp_config(cwd);\n\n\t// Connect all MCP servers in parallel for faster startup\n\tconst results = await Promise.allSettled(\n\t\tconfigs.map(async (config) => {\n\t\t\tconst client = new McpClient(config);\n\t\t\tawait client.connect();\n\t\t\tconst mcp_tools = await client.listTools();\n\t\t\treturn { config, client, mcp_tools };\n\t\t}),\n\t);\n\n\tfor (const result of results) {\n\t\tif (result.status === 'rejected') {\n\t\t\tconsole.error(`MCP server failed: ${result.reason}`);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst { config, client, mcp_tools } = result.value;\n\t\tconst tool_names: string[] = [];\n\n\t\tfor (const mcp_tool of mcp_tools) {\n\t\t\tconst tool_name = `mcp__${config.name}__${mcp_tool.name}`;\n\t\t\ttool_names.push(tool_name);\n\n\t\t\tpi.registerTool(\n\t\t\t\tdefineTool({\n\t\t\t\t\tname: tool_name,\n\t\t\t\t\tlabel: `${config.name}: ${mcp_tool.name}`,\n\t\t\t\t\tdescription: mcp_tool.description || mcp_tool.name,\n\t\t\t\t\tparameters: (mcp_tool.inputSchema || {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t}) as Parameters<typeof defineTool>[0]['parameters'],\n\t\t\t\t\texecute: async (_id, params) => {\n\t\t\t\t\t\tconst result = (await client.callTool(\n\t\t\t\t\t\t\tmcp_tool.name,\n\t\t\t\t\t\t\tparams as Record<string, unknown>,\n\t\t\t\t\t\t)) as {\n\t\t\t\t\t\t\tcontent?: Array<{\n\t\t\t\t\t\t\t\ttype: string;\n\t\t\t\t\t\t\t\ttext?: string;\n\t\t\t\t\t\t\t}>;\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tconst text =\n\t\t\t\t\t\t\tresult?.content?.map((c) => c.text || '').join('\\n') ||\n\t\t\t\t\t\t\tJSON.stringify(result);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcontent: [{ type: 'text' as const, text }],\n\t\t\t\t\t\t\tdetails: {},\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\tservers.set(config.name, {\n\t\t\tconfig,\n\t\t\tclient,\n\t\t\ttool_names,\n\t\t\tenabled: true,\n\t\t});\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\tconst status = state.enabled ? 'enabled' : 'disabled';\n\t\t\t\t\t\tlines.push(\n\t\t\t\t\t\t\t`${sname} (${status}) — ${state.tool_names.length} tools`,\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) {\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\tconst active = pi.getActiveTools();\n\t\t\t\t\tpi.setActiveTools([...active, ...server.tool_names]);\n\t\t\t\t\tctx.ui.notify(`Enabled ${name}`);\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\tconst tool_set = new Set(server.tool_names);\n\t\t\t\t\tpi.setActiveTools(\n\t\t\t\t\t\tpi.getActiveTools().filter((t) => !tool_set.has(t)),\n\t\t\t\t\t);\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\tfor (const server of servers.values()) {\n\t\t\tawait server.client.disconnect();\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 { execFileSync } 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\n// Default export for Pi Package / additionalExtensionPaths loading\nexport default async function recall(pi: ExtensionAPI) {\n\t// Sync on startup if db exists\n\tif (existsSync(DEFAULT_DB_PATH)) {\n\t\ttry {\n\t\t\texecFileSync('npx', ['pirecall', 'sync', '--json'], {\n\t\t\t\tencoding: 'utf-8',\n\t\t\t\ttimeout: 30_000,\n\t\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\t});\n\t\t} catch {\n\t\t\t// Non-critical — db may just not have new data\n\t\t}\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","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","// 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 mcp_extension from './extensions/mcp.js';\nimport prompt_presets_extension from './extensions/prompt-presets.js';\nimport recall_extension from './extensions/recall.js';\nimport skills_extension from './extensions/skills.js';\nimport { create_skills_manager } from './skills/manager.js';\n\nexport interface CreateMyPiOptions {\n\tcwd?: 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\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};\n\nconst MODULE_DIR = dirname(fileURLToPath(import.meta.url));\nconst PACKAGE_THEME_DIR = resolve(MODULE_DIR, '..', 'themes');\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>,\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\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\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\tmodel,\n\t\tsystem_prompt,\n\t\tappend_system_prompt,\n\t} = options;\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});\n\tconst managed_extension_factories: ExtensionFactory[] = [\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(runtime_cwd);\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\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: getAgentDir(),\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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"}
package/dist/api.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as create_my_pi, r as runPrintMode, t as InteractiveMode } from "./api-DtthDVIa.js";
1
+ import { n as create_my_pi, r as runPrintMode, t as InteractiveMode } from "./api-BA6XuDOE.js";
2
2
  export { InteractiveMode, create_my_pi, runPrintMode };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as create_my_pi } from "./api-DtthDVIa.js";
2
+ import { n as create_my_pi } from "./api-BA6XuDOE.js";
3
3
  import { InteractiveMode, runPrintMode } from "@mariozechner/pi-coding-agent";
4
4
  import { defineCommand, runMain } from "citty";
5
5
  import { readFileSync } from "node:fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-pi",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "Personal pi coding agent wrapper with MCP tool integration",
5
5
  "keywords": [
6
6
  "cli",
@@ -37,9 +37,9 @@
37
37
  "./cli": "./dist/index.js"
38
38
  },
39
39
  "dependencies": {
40
- "@mariozechner/pi-ai": "^0.67.2",
41
- "@mariozechner/pi-coding-agent": "^0.67.2",
42
- "@mariozechner/pi-tui": "^0.67.2",
40
+ "@mariozechner/pi-ai": "^0.67.3",
41
+ "@mariozechner/pi-coding-agent": "^0.67.3",
42
+ "@mariozechner/pi-tui": "^0.67.3",
43
43
  "@sinclair/typebox": "^0.34.49",
44
44
  "citty": "^0.2.2"
45
45
  },
@@ -9,9 +9,11 @@ import { join } from 'node:path';
9
9
  import { afterEach, describe, expect, it } from 'vitest';
10
10
  import {
11
11
  DEFAULT_PROMPT_PRESETS,
12
+ load_persisted_prompt_state,
12
13
  merge_prompt_presets,
13
14
  normalize_prompt_presets,
14
15
  remove_project_prompt_preset,
16
+ save_persisted_prompt_state,
15
17
  save_project_prompt_presets,
16
18
  } from './prompt-presets.js';
17
19
 
@@ -114,4 +116,40 @@ describe('project preset persistence', () => {
114
116
  expect(result.remaining).toBe(0);
115
117
  expect(existsSync(join(cwd, '.pi', 'presets.json'))).toBe(false);
116
118
  });
119
+
120
+ it('persists the active prompt selection per project', () => {
121
+ const root = mkdtempSync(join(tmpdir(), 'my-pi-preset-state-'));
122
+ dirs.push(root);
123
+
124
+ const state_path = join(root, 'prompt-preset-state.json');
125
+ const project_a = join(root, 'project-a');
126
+ const project_b = join(root, 'project-b');
127
+
128
+ save_persisted_prompt_state(
129
+ project_a,
130
+ { base_name: 'terse', layer_names: ['bullets'] },
131
+ state_path,
132
+ );
133
+ save_persisted_prompt_state(
134
+ project_b,
135
+ {
136
+ base_name: null,
137
+ layer_names: ['include-risks', 'bullets', 'include-risks'],
138
+ },
139
+ state_path,
140
+ );
141
+
142
+ expect(
143
+ load_persisted_prompt_state(project_a, state_path),
144
+ ).toEqual({
145
+ base_name: 'terse',
146
+ layer_names: ['bullets'],
147
+ });
148
+ expect(
149
+ load_persisted_prompt_state(project_b, state_path),
150
+ ).toEqual({
151
+ base_name: null,
152
+ layer_names: ['bullets', 'include-risks'],
153
+ });
154
+ });
117
155
  });