my-pi 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{api-B6KnhtN9.js → api-eJaobq0e.js} +48 -8
- package/dist/api-eJaobq0e.js.map +1 -0
- package/dist/api.js +1 -1
- package/dist/index.js +15 -4
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/extensions/chain.ts +76 -7
- package/dist/api-B6KnhtN9.js.map +0 -1
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { InteractiveMode as InteractiveMode$1, SessionManager, SettingsManager, createAgentSessionFromServices, createAgentSessionRuntime, createAgentSessionServices, defineTool, getAgentDir, parseFrontmatter, runPrintMode as runPrintMode$1 } from "@mariozechner/pi-coding-agent";
|
|
2
2
|
import { cpSync, existsSync, globSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
4
5
|
import { Type } from "@sinclair/typebox";
|
|
5
6
|
import { execFileSync, spawn } from "node:child_process";
|
|
6
7
|
import { homedir } from "node:os";
|
|
7
8
|
import { Container, SettingsList, Text } from "@mariozechner/pi-tui";
|
|
8
9
|
import { createHash } from "node:crypto";
|
|
9
10
|
//#region src/extensions/chain.ts
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
12
|
function parse_chain_yaml(raw) {
|
|
11
13
|
const chains = [];
|
|
12
14
|
let current = null;
|
|
@@ -88,15 +90,25 @@ function scan_agent_dirs(cwd) {
|
|
|
88
90
|
}
|
|
89
91
|
return agents;
|
|
90
92
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
+
const AGENT_STEP_TIMEOUT_MS = 300 * 1e3;
|
|
94
|
+
function run_agent_step(agent_def, task, model) {
|
|
95
|
+
const bin = join(__dirname, "..", "index.js");
|
|
93
96
|
const args = [
|
|
94
97
|
"--no-builtin",
|
|
95
|
-
"
|
|
98
|
+
"--json",
|
|
99
|
+
"--prompt",
|
|
96
100
|
task
|
|
97
101
|
];
|
|
102
|
+
if (model) args.push("--model", model);
|
|
98
103
|
const chunks = [];
|
|
99
104
|
return new Promise((res) => {
|
|
105
|
+
let settled = false;
|
|
106
|
+
const resolve_once = (result) => {
|
|
107
|
+
if (settled) return;
|
|
108
|
+
settled = true;
|
|
109
|
+
clearTimeout(timer);
|
|
110
|
+
res(result);
|
|
111
|
+
};
|
|
100
112
|
const proc = spawn(process.execPath, [bin, ...args], {
|
|
101
113
|
stdio: [
|
|
102
114
|
"ignore",
|
|
@@ -108,6 +120,13 @@ function run_agent_step(agent_def, task) {
|
|
|
108
120
|
MY_PI_AGENT_SYSTEM_PROMPT: agent_def.systemPrompt
|
|
109
121
|
}
|
|
110
122
|
});
|
|
123
|
+
const timer = setTimeout(() => {
|
|
124
|
+
proc.kill("SIGTERM");
|
|
125
|
+
resolve_once({
|
|
126
|
+
output: `Agent step timed out after ${AGENT_STEP_TIMEOUT_MS / 1e3}s`,
|
|
127
|
+
exitCode: 1
|
|
128
|
+
});
|
|
129
|
+
}, AGENT_STEP_TIMEOUT_MS);
|
|
111
130
|
proc.stdout.setEncoding("utf-8");
|
|
112
131
|
proc.stdout.on("data", (chunk) => {
|
|
113
132
|
chunks.push(chunk);
|
|
@@ -115,22 +134,43 @@ function run_agent_step(agent_def, task) {
|
|
|
115
134
|
proc.stderr.setEncoding("utf-8");
|
|
116
135
|
proc.stderr.on("data", () => {});
|
|
117
136
|
proc.on("close", (code) => {
|
|
118
|
-
|
|
119
|
-
|
|
137
|
+
const raw = chunks.join("");
|
|
138
|
+
const text_parts = [];
|
|
139
|
+
for (const line of raw.split("\n")) {
|
|
140
|
+
if (!line.trim()) continue;
|
|
141
|
+
try {
|
|
142
|
+
const event = JSON.parse(line);
|
|
143
|
+
if (event?.role === "assistant" && Array.isArray(event?.content)) {
|
|
144
|
+
for (const c of event.content) if (c.type === "text" && c.text) text_parts.push(c.text);
|
|
145
|
+
}
|
|
146
|
+
} catch {
|
|
147
|
+
text_parts.push(line);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
resolve_once({
|
|
151
|
+
output: text_parts.join("\n").trim() || raw.trim(),
|
|
120
152
|
exitCode: code ?? 1
|
|
121
153
|
});
|
|
122
154
|
});
|
|
123
155
|
proc.on("error", (err) => {
|
|
124
|
-
|
|
156
|
+
resolve_once({
|
|
125
157
|
output: `Error spawning agent: ${err.message}`,
|
|
126
158
|
exitCode: 1
|
|
127
159
|
});
|
|
128
160
|
});
|
|
129
161
|
});
|
|
130
162
|
}
|
|
163
|
+
function parse_model_from_argv() {
|
|
164
|
+
const argv = process.argv;
|
|
165
|
+
for (let i = 0; i < argv.length; i++) {
|
|
166
|
+
if ((argv[i] === "--model" || argv[i] === "-m") && i + 1 < argv.length) return argv[i + 1];
|
|
167
|
+
if (argv[i]?.startsWith("--model=")) return argv[i].slice(8);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
131
170
|
async function chain(pi) {
|
|
132
171
|
const cwd = process.cwd();
|
|
133
172
|
const agents = scan_agent_dirs(cwd);
|
|
173
|
+
const current_model = parse_model_from_argv();
|
|
134
174
|
let chains = [];
|
|
135
175
|
let active_chain = null;
|
|
136
176
|
const chain_paths = [
|
|
@@ -180,7 +220,7 @@ async function chain(pi) {
|
|
|
180
220
|
}
|
|
181
221
|
};
|
|
182
222
|
}
|
|
183
|
-
const result = await run_agent_step(agent_def, step.prompt.replace(/\$INPUT/g, input).replace(/\$ORIGINAL/g, original));
|
|
223
|
+
const result = await run_agent_step(agent_def, step.prompt.replace(/\$INPUT/g, input).replace(/\$ORIGINAL/g, original), current_model);
|
|
184
224
|
if (result.exitCode !== 0) {
|
|
185
225
|
const msg = `Step ${i + 1} (${step.agent}) failed:\n${result.output}`;
|
|
186
226
|
results.push(msg);
|
|
@@ -1890,4 +1930,4 @@ async function create_my_pi(options = {}) {
|
|
|
1890
1930
|
//#endregion
|
|
1891
1931
|
export { create_my_pi as n, runPrintMode$1 as r, InteractiveMode$1 as t };
|
|
1892
1932
|
|
|
1893
|
-
//# sourceMappingURL=api-
|
|
1933
|
+
//# sourceMappingURL=api-eJaobq0e.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-eJaobq0e.js","names":["DEFAULT_CONFIG","ENABLED","DISABLED","to_setting_item","sets_equal","#config","#proc","#buffer","#pending","#request","#send","#nextId","mcp_extension","skills_extension","chain_extension","filter_output_extension","handoff_extension","recall_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/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\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];\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 McpServerConfig {\n\tname: string;\n\tcommand: string;\n\targs?: string[];\n\tenv?: Record<string, string>;\n}\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\n\tconstructor(config: McpServerConfig) {\n\t\tthis.#config = config;\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tconst { command, args = [], env } = this.#config;\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\tconst msg = JSON.parse(line) as JsonRpcResponse;\n\t\t\t\t\tif (msg.id != null && this.#pending.has(msg.id)) {\n\t\t\t\t\t\tconst p = this.#pending.get(msg.id)!;\n\t\t\t\t\t\tthis.#pending.delete(msg.id);\n\t\t\t\t\t\tif (msg.error) {\n\t\t\t\t\t\t\tp.reject(\n\t\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t\t`MCP error ${msg.error.code}: ${msg.error.message}`,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tp.resolve(msg.result);\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// ignore non-JSON lines\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// Initialize handshake\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\t// Send initialized notification (no response expected)\n\t\tthis.#send({\n\t\t\tjsonrpc: '2.0',\n\t\t\tmethod: 'notifications/initialized',\n\t\t} as unknown as JsonRpcRequest);\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.#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\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 });\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\t#send(msg: JsonRpcRequest) {\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","import { existsSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { McpServerConfig } from './client.js';\n\ninterface McpConfigFile {\n\tmcpServers: Record<\n\t\tstring,\n\t\t{\n\t\t\tcommand: string;\n\t\t\targs?: string[];\n\t\t\tenv?: Record<string, string>;\n\t\t}\n\t>;\n}\n\nfunction read_config(path: string): McpConfigFile['mcpServers'] {\n\tif (!existsSync(path)) return {};\n\tconst raw = readFileSync(path, 'utf-8');\n\tconst config = JSON.parse(raw) as McpConfigFile;\n\treturn config.mcpServers || {};\n}\n\nexport function load_mcp_config(cwd: string): McpServerConfig[] {\n\t// Global: ~/.pi/agent/mcp.json\n\tconst global_servers = read_config(\n\t\tjoin(homedir(), '.pi', 'agent', 'mcp.json'),\n\t);\n\n\t// Project: ./mcp.json (overrides global by name)\n\tconst project_servers = read_config(join(cwd, 'mcp.json'));\n\n\tconst merged = { ...global_servers, ...project_servers };\n\n\treturn Object.entries(merged).map(([name, server]) => ({\n\t\tname,\n\t\tcommand: server.command,\n\t\targs: server.args,\n\t\tenv: server.env,\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","// 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 { resolve } from 'node:path';\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 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\tmodel?: 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};\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>,\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\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\tmodel,\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});\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\tadditionalExtensionPaths: [...resolved_extensions],\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-
|
|
1
|
+
import { n as create_my_pi, r as runPrintMode, t as InteractiveMode } from "./api-eJaobq0e.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-
|
|
2
|
+
import { n as create_my_pi } from "./api-eJaobq0e.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";
|
|
@@ -75,11 +75,12 @@ runMain(defineCommand({
|
|
|
75
75
|
model: {
|
|
76
76
|
type: "string",
|
|
77
77
|
alias: "m",
|
|
78
|
-
description: "Model to use (e.g. claude-sonnet-4-5-20241022)"
|
|
78
|
+
description: "Model to use (e.g. claude-sonnet-4-5-20241022, gpt-5.4)"
|
|
79
79
|
},
|
|
80
80
|
prompt: {
|
|
81
|
-
type: "
|
|
82
|
-
|
|
81
|
+
type: "string",
|
|
82
|
+
alias: "p",
|
|
83
|
+
description: "Prompt text (alternative to positional argument)",
|
|
83
84
|
required: false
|
|
84
85
|
}
|
|
85
86
|
},
|
|
@@ -87,7 +88,17 @@ runMain(defineCommand({
|
|
|
87
88
|
const cwd = process.cwd();
|
|
88
89
|
const extension_paths = parse_extension_paths(process.argv);
|
|
89
90
|
let prompt = args.prompt;
|
|
91
|
+
if (!prompt) {
|
|
92
|
+
const positionals = args._;
|
|
93
|
+
if (positionals && positionals.length > 0) prompt = positionals[0];
|
|
94
|
+
}
|
|
90
95
|
if (!prompt && !process.stdin.isTTY) prompt = await read_stdin();
|
|
96
|
+
if (args.model && /[/\\]/.test(args.model)) {
|
|
97
|
+
console.error(`Error: Invalid model "${args.model}". Use bare model names without provider prefixes.`);
|
|
98
|
+
console.error(` Examples: claude-sonnet-4-5-20241022, gpt-5.4, mistral-large`);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
if (args.print || args.json || prompt) process.stderr.write(`my-pi: connecting to ${args.model || "default model"}...\n`);
|
|
91
102
|
const runtime = await create_my_pi({
|
|
92
103
|
cwd,
|
|
93
104
|
extensions: extension_paths,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// CLI for my-pi — composable pi coding agent\n// Extension stacking patterns inspired by https://github.com/disler/pi-vs-claude-code\n\nimport {\n\tInteractiveMode,\n\trunPrintMode,\n} from '@mariozechner/pi-coding-agent';\nimport { defineCommand, runMain } from 'citty';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { create_my_pi } from './api.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(\n\treadFileSync(join(__dirname, '..', 'package.json'), 'utf-8'),\n);\n\n// citty can't handle repeatable args, so parse -e from argv directly\n// (citty uses strict: false, so unknown flags are silently ignored)\nfunction parse_extension_paths(argv: string[]): string[] {\n\tconst paths: string[] = [];\n\tfor (let i = 0; i < argv.length; i++) {\n\t\tif (\n\t\t\t(argv[i] === '-e' || argv[i] === '--extension') &&\n\t\t\ti + 1 < argv.length\n\t\t) {\n\t\t\tpaths.push(resolve(argv[++i]));\n\t\t}\n\t}\n\treturn paths;\n}\n\nasync function read_stdin(): Promise<string> {\n\tconst chunks: Buffer[] = [];\n\tfor await (const chunk of process.stdin) {\n\t\tchunks.push(chunk as Buffer);\n\t}\n\treturn Buffer.concat(chunks).toString('utf-8').trim();\n}\n\nconst main = defineCommand({\n\tmeta: {\n\t\tname: 'my-pi',\n\t\tversion: pkg.version,\n\t\tdescription:\n\t\t\t'Composable pi coding agent with MCP tools and extension stacking',\n\t},\n\targs: {\n\t\tprint: {\n\t\t\ttype: 'boolean',\n\t\t\talias: 'P',\n\t\t\tdescription: 'Print mode (non-interactive, one-shot)',\n\t\t\tdefault: false,\n\t\t},\n\t\tjson: {\n\t\t\ttype: 'boolean',\n\t\t\talias: 'j',\n\t\t\tdescription: 'Output NDJSON events (for agent consumption)',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-builtin': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable all built-in extensions',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-mcp': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable built-in MCP extension',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-skills': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable built-in skills extension',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-chain': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable built-in chain extension',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-filter': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable secret redaction in tool output',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-handoff': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable handoff extension',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-recall': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable recall extension',\n\t\t\tdefault: false,\n\t\t},\n\t\tmodel: {\n\t\t\ttype: 'string',\n\t\t\talias: 'm',\n\t\t\tdescription
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// CLI for my-pi — composable pi coding agent\n// Extension stacking patterns inspired by https://github.com/disler/pi-vs-claude-code\n\nimport {\n\tInteractiveMode,\n\trunPrintMode,\n} from '@mariozechner/pi-coding-agent';\nimport { defineCommand, runMain } from 'citty';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { create_my_pi } from './api.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(\n\treadFileSync(join(__dirname, '..', 'package.json'), 'utf-8'),\n);\n\n// citty can't handle repeatable args, so parse -e from argv directly\n// (citty uses strict: false, so unknown flags are silently ignored)\nfunction parse_extension_paths(argv: string[]): string[] {\n\tconst paths: string[] = [];\n\tfor (let i = 0; i < argv.length; i++) {\n\t\tif (\n\t\t\t(argv[i] === '-e' || argv[i] === '--extension') &&\n\t\t\ti + 1 < argv.length\n\t\t) {\n\t\t\tpaths.push(resolve(argv[++i]));\n\t\t}\n\t}\n\treturn paths;\n}\n\nasync function read_stdin(): Promise<string> {\n\tconst chunks: Buffer[] = [];\n\tfor await (const chunk of process.stdin) {\n\t\tchunks.push(chunk as Buffer);\n\t}\n\treturn Buffer.concat(chunks).toString('utf-8').trim();\n}\n\nconst main = defineCommand({\n\tmeta: {\n\t\tname: 'my-pi',\n\t\tversion: pkg.version,\n\t\tdescription:\n\t\t\t'Composable pi coding agent with MCP tools and extension stacking',\n\t},\n\targs: {\n\t\tprint: {\n\t\t\ttype: 'boolean',\n\t\t\talias: 'P',\n\t\t\tdescription: 'Print mode (non-interactive, one-shot)',\n\t\t\tdefault: false,\n\t\t},\n\t\tjson: {\n\t\t\ttype: 'boolean',\n\t\t\talias: 'j',\n\t\t\tdescription: 'Output NDJSON events (for agent consumption)',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-builtin': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable all built-in extensions',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-mcp': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable built-in MCP extension',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-skills': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable built-in skills extension',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-chain': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable built-in chain extension',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-filter': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable secret redaction in tool output',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-handoff': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable handoff extension',\n\t\t\tdefault: false,\n\t\t},\n\t\t'no-recall': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Disable recall extension',\n\t\t\tdefault: false,\n\t\t},\n\t\tmodel: {\n\t\t\ttype: 'string',\n\t\t\talias: 'm',\n\t\t\tdescription:\n\t\t\t\t'Model to use (e.g. claude-sonnet-4-5-20241022, gpt-5.4)',\n\t\t},\n\t\tprompt: {\n\t\t\ttype: 'string',\n\t\t\talias: 'p',\n\t\t\tdescription: 'Prompt text (alternative to positional argument)',\n\t\t\trequired: false,\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst cwd = process.cwd();\n\t\tconst extension_paths = parse_extension_paths(process.argv);\n\n\t\t// Resolve prompt: named --prompt flag > positional > stdin\n\t\tlet prompt = args.prompt;\n\t\tif (!prompt) {\n\t\t\t// Check for positional arguments (after citty strips flags)\n\t\t\tconst positionals = (args as any)._ as string[] | undefined;\n\t\t\tif (positionals && positionals.length > 0) {\n\t\t\t\tprompt = positionals[0];\n\t\t\t}\n\t\t}\n\t\tif (!prompt && !process.stdin.isTTY) {\n\t\t\tprompt = await read_stdin();\n\t\t}\n\n\t\t// Model validation (issue #5)\n\t\tif (args.model && /[/\\\\]/.test(args.model)) {\n\t\t\tconsole.error(\n\t\t\t\t`Error: Invalid model \"${args.model}\". Use bare model names without provider prefixes.`,\n\t\t\t);\n\t\t\tconsole.error(\n\t\t\t\t` Examples: claude-sonnet-4-5-20241022, gpt-5.4, mistral-large`,\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Startup feedback so silence = broken (issue #3)\n\t\tif (args.print || args.json || prompt) {\n\t\t\tprocess.stderr.write(\n\t\t\t\t`my-pi: connecting to ${args.model || 'default model'}...\\n`,\n\t\t\t);\n\t\t}\n\n\t\tconst runtime = await create_my_pi({\n\t\t\tcwd,\n\t\t\textensions: extension_paths,\n\t\t\tmcp: !args['no-builtin'] && !args['no-mcp'],\n\t\t\tskills: !args['no-builtin'] && !args['no-skills'],\n\t\t\tchain: !args['no-builtin'] && !args['no-chain'],\n\t\t\tfilter_output: !args['no-builtin'] && !args['no-filter'],\n\t\t\thandoff: !args['no-builtin'] && !args['no-handoff'],\n\t\t\trecall: !args['no-builtin'] && !args['no-recall'],\n\t\t\tmodel: args.model,\n\t\t});\n\n\t\tif (args.print || args.json || prompt) {\n\t\t\tconst code = await runPrintMode(runtime, {\n\t\t\t\tmode: args.json ? 'json' : 'text',\n\t\t\t\tinitialMessage: prompt || '',\n\t\t\t\tinitialImages: [],\n\t\t\t\tmessages: [],\n\t\t\t});\n\t\t\tprocess.exit(code);\n\t\t} else if (!process.stdout.isTTY) {\n\t\t\tconsole.log(\n\t\t\t\t`my-pi v${pkg.version} — composable pi coding agent\\n`,\n\t\t\t);\n\t\t\tconsole.log('Usage:');\n\t\t\tconsole.log(\n\t\t\t\t' my-pi \"prompt\" One-shot print mode',\n\t\t\t);\n\t\t\tconsole.log(\n\t\t\t\t' my-pi Interactive TUI mode',\n\t\t\t);\n\t\t\tconsole.log(\n\t\t\t\t' my-pi -P \"prompt\" Explicit print mode',\n\t\t\t);\n\t\t\tconsole.log(\n\t\t\t\t' my-pi --json \"prompt\" NDJSON output for agents',\n\t\t\t);\n\t\t\tconsole.log(\n\t\t\t\t' my-pi -e ext.ts Stack an extension',\n\t\t\t);\n\t\t\tconsole.log(\n\t\t\t\t' my-pi -e a.ts -e b.ts Stack multiple extensions',\n\t\t\t);\n\t\t\tconsole.log(\n\t\t\t\t' echo \"prompt\" | my-pi --json Pipe stdin as prompt',\n\t\t\t);\n\t\t\tconsole.log(\n\t\t\t\t' my-pi -m claude-haiku-4-5-20241022 Set initial model',\n\t\t\t);\n\t\t\tconsole.log(\n\t\t\t\t' my-pi --no-builtin -e ext.ts Skip all built-in extensions',\n\t\t\t);\n\t\t} else {\n\t\t\tconst mode = new InteractiveMode(runtime, {\n\t\t\t\tmigratedProviders: [],\n\t\t\t\tmodelFallbackMessage: undefined,\n\t\t\t\tinitialMessage: undefined,\n\t\t\t\tinitialImages: [],\n\t\t\t\tinitialMessages: [],\n\t\t\t});\n\t\t\tawait mode.run();\n\t\t}\n\t},\n});\n\nvoid runMain(main);\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "my-pi",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Personal pi coding agent wrapper with MCP tool integration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"./cli": "./dist/index.js"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@mariozechner/pi-ai": "^0.
|
|
31
|
-
"@mariozechner/pi-coding-agent": "^0.
|
|
32
|
-
"@mariozechner/pi-tui": "^0.
|
|
30
|
+
"@mariozechner/pi-ai": "^0.67.1",
|
|
31
|
+
"@mariozechner/pi-coding-agent": "^0.67.1",
|
|
32
|
+
"@mariozechner/pi-tui": "^0.67.1",
|
|
33
33
|
"@sinclair/typebox": "^0.34.49",
|
|
34
34
|
"citty": "^0.2.2"
|
|
35
35
|
},
|
package/src/extensions/chain.ts
CHANGED
|
@@ -9,7 +9,10 @@ import {
|
|
|
9
9
|
import { Type } from '@sinclair/typebox';
|
|
10
10
|
import { spawn } from 'node:child_process';
|
|
11
11
|
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
12
|
-
import { join, resolve } from 'node:path';
|
|
12
|
+
import { dirname, join, resolve } from 'node:path';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
16
|
|
|
14
17
|
// ── Types ───────────────────────────────────────
|
|
15
18
|
|
|
@@ -154,17 +157,35 @@ function scan_agent_dirs(cwd: string): Map<string, AgentDef> {
|
|
|
154
157
|
|
|
155
158
|
// ── Run a single agent step via my-pi print mode ─
|
|
156
159
|
|
|
160
|
+
const AGENT_STEP_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
161
|
+
|
|
157
162
|
function run_agent_step(
|
|
158
163
|
agent_def: AgentDef,
|
|
159
164
|
task: string,
|
|
165
|
+
model?: string,
|
|
160
166
|
): Promise<{ output: string; exitCode: number }> {
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
const
|
|
167
|
+
// Resolve bin path: prefer known dist location over process.argv[1]
|
|
168
|
+
// (process.argv[1] may point to a wrapper like codex, not my-pi)
|
|
169
|
+
const bin = join(__dirname, '..', 'index.js');
|
|
170
|
+
const args = ['--no-builtin', '--json', '--prompt', task];
|
|
171
|
+
if (model) {
|
|
172
|
+
args.push('--model', model);
|
|
173
|
+
}
|
|
164
174
|
|
|
165
175
|
const chunks: string[] = [];
|
|
166
176
|
|
|
167
177
|
return new Promise((res) => {
|
|
178
|
+
let settled = false;
|
|
179
|
+
const resolve_once = (result: {
|
|
180
|
+
output: string;
|
|
181
|
+
exitCode: number;
|
|
182
|
+
}) => {
|
|
183
|
+
if (settled) return;
|
|
184
|
+
settled = true;
|
|
185
|
+
clearTimeout(timer);
|
|
186
|
+
res(result);
|
|
187
|
+
};
|
|
188
|
+
|
|
168
189
|
const proc = spawn(process.execPath, [bin, ...args], {
|
|
169
190
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
170
191
|
env: {
|
|
@@ -173,6 +194,14 @@ function run_agent_step(
|
|
|
173
194
|
},
|
|
174
195
|
});
|
|
175
196
|
|
|
197
|
+
const timer = setTimeout(() => {
|
|
198
|
+
proc.kill('SIGTERM');
|
|
199
|
+
resolve_once({
|
|
200
|
+
output: `Agent step timed out after ${AGENT_STEP_TIMEOUT_MS / 1000}s`,
|
|
201
|
+
exitCode: 1,
|
|
202
|
+
});
|
|
203
|
+
}, AGENT_STEP_TIMEOUT_MS);
|
|
204
|
+
|
|
176
205
|
proc.stdout!.setEncoding('utf-8');
|
|
177
206
|
proc.stdout!.on('data', (chunk: string) => {
|
|
178
207
|
chunks.push(chunk);
|
|
@@ -182,14 +211,36 @@ function run_agent_step(
|
|
|
182
211
|
proc.stderr!.on('data', () => {});
|
|
183
212
|
|
|
184
213
|
proc.on('close', (code) => {
|
|
185
|
-
|
|
186
|
-
|
|
214
|
+
// Parse NDJSON events to extract assistant text content
|
|
215
|
+
const raw = chunks.join('');
|
|
216
|
+
const text_parts: string[] = [];
|
|
217
|
+
for (const line of raw.split('\n')) {
|
|
218
|
+
if (!line.trim()) continue;
|
|
219
|
+
try {
|
|
220
|
+
const event = JSON.parse(line);
|
|
221
|
+
if (
|
|
222
|
+
event?.role === 'assistant' &&
|
|
223
|
+
Array.isArray(event?.content)
|
|
224
|
+
) {
|
|
225
|
+
for (const c of event.content) {
|
|
226
|
+
if (c.type === 'text' && c.text) {
|
|
227
|
+
text_parts.push(c.text);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
} catch {
|
|
232
|
+
// not JSON — use raw line
|
|
233
|
+
text_parts.push(line);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
resolve_once({
|
|
237
|
+
output: text_parts.join('\n').trim() || raw.trim(),
|
|
187
238
|
exitCode: code ?? 1,
|
|
188
239
|
});
|
|
189
240
|
});
|
|
190
241
|
|
|
191
242
|
proc.on('error', (err) => {
|
|
192
|
-
|
|
243
|
+
resolve_once({
|
|
193
244
|
output: `Error spawning agent: ${err.message}`,
|
|
194
245
|
exitCode: 1,
|
|
195
246
|
});
|
|
@@ -200,9 +251,26 @@ function run_agent_step(
|
|
|
200
251
|
// ── Extension ──────────────────────────────────
|
|
201
252
|
|
|
202
253
|
// Default export for Pi Package / additionalExtensionPaths loading
|
|
254
|
+
function parse_model_from_argv(): string | undefined {
|
|
255
|
+
const argv = process.argv;
|
|
256
|
+
for (let i = 0; i < argv.length; i++) {
|
|
257
|
+
if (
|
|
258
|
+
(argv[i] === '--model' || argv[i] === '-m') &&
|
|
259
|
+
i + 1 < argv.length
|
|
260
|
+
) {
|
|
261
|
+
return argv[i + 1];
|
|
262
|
+
}
|
|
263
|
+
if (argv[i]?.startsWith('--model=')) {
|
|
264
|
+
return argv[i].slice('--model='.length);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return undefined;
|
|
268
|
+
}
|
|
269
|
+
|
|
203
270
|
export default async function chain(pi: ExtensionAPI) {
|
|
204
271
|
const cwd = process.cwd();
|
|
205
272
|
const agents = scan_agent_dirs(cwd);
|
|
273
|
+
const current_model = parse_model_from_argv();
|
|
206
274
|
let chains: ChainDef[] = [];
|
|
207
275
|
let active_chain: ChainDef | null = null;
|
|
208
276
|
|
|
@@ -292,6 +360,7 @@ export default async function chain(pi: ExtensionAPI) {
|
|
|
292
360
|
const result = await run_agent_step(
|
|
293
361
|
agent_def,
|
|
294
362
|
resolved_prompt,
|
|
363
|
+
current_model,
|
|
295
364
|
);
|
|
296
365
|
|
|
297
366
|
if (result.exitCode !== 0) {
|
package/dist/api-B6KnhtN9.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"api-B6KnhtN9.js","names":["DEFAULT_CONFIG","ENABLED","DISABLED","to_setting_item","sets_equal","#config","#proc","#buffer","#pending","#request","#send","#nextId","mcp_extension","skills_extension","chain_extension","filter_output_extension","handoff_extension","recall_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/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 { join, resolve } from 'node:path';\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\nfunction run_agent_step(\n\tagent_def: AgentDef,\n\ttask: string,\n): Promise<{ output: string; exitCode: number }> {\n\t// Use the current process (my-pi) in print mode\n\tconst bin = process.argv[1];\n\tconst args = ['--no-builtin', '-P', task];\n\n\tconst chunks: string[] = [];\n\n\treturn new Promise((res) => {\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\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\tres({\n\t\t\t\toutput: chunks.join('').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\tres({\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\nexport default async function chain(pi: ExtensionAPI) {\n\tconst cwd = process.cwd();\n\tconst agents = scan_agent_dirs(cwd);\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);\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\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];\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 McpServerConfig {\n\tname: string;\n\tcommand: string;\n\targs?: string[];\n\tenv?: Record<string, string>;\n}\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\n\tconstructor(config: McpServerConfig) {\n\t\tthis.#config = config;\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tconst { command, args = [], env } = this.#config;\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\tconst msg = JSON.parse(line) as JsonRpcResponse;\n\t\t\t\t\tif (msg.id != null && this.#pending.has(msg.id)) {\n\t\t\t\t\t\tconst p = this.#pending.get(msg.id)!;\n\t\t\t\t\t\tthis.#pending.delete(msg.id);\n\t\t\t\t\t\tif (msg.error) {\n\t\t\t\t\t\t\tp.reject(\n\t\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t\t`MCP error ${msg.error.code}: ${msg.error.message}`,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tp.resolve(msg.result);\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// ignore non-JSON lines\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// Initialize handshake\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\t// Send initialized notification (no response expected)\n\t\tthis.#send({\n\t\t\tjsonrpc: '2.0',\n\t\t\tmethod: 'notifications/initialized',\n\t\t} as unknown as JsonRpcRequest);\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.#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\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 });\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\t#send(msg: JsonRpcRequest) {\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","import { existsSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { McpServerConfig } from './client.js';\n\ninterface McpConfigFile {\n\tmcpServers: Record<\n\t\tstring,\n\t\t{\n\t\t\tcommand: string;\n\t\t\targs?: string[];\n\t\t\tenv?: Record<string, string>;\n\t\t}\n\t>;\n}\n\nfunction read_config(path: string): McpConfigFile['mcpServers'] {\n\tif (!existsSync(path)) return {};\n\tconst raw = readFileSync(path, 'utf-8');\n\tconst config = JSON.parse(raw) as McpConfigFile;\n\treturn config.mcpServers || {};\n}\n\nexport function load_mcp_config(cwd: string): McpServerConfig[] {\n\t// Global: ~/.pi/agent/mcp.json\n\tconst global_servers = read_config(\n\t\tjoin(homedir(), '.pi', 'agent', 'mcp.json'),\n\t);\n\n\t// Project: ./mcp.json (overrides global by name)\n\tconst project_servers = read_config(join(cwd, 'mcp.json'));\n\n\tconst merged = { ...global_servers, ...project_servers };\n\n\treturn Object.entries(merged).map(([name, server]) => ({\n\t\tname,\n\t\tcommand: server.command,\n\t\targs: server.args,\n\t\tenv: server.env,\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","// 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 { resolve } from 'node:path';\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 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\tmodel?: 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};\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>,\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\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\tmodel,\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});\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\tadditionalExtensionPaths: [...resolved_extensions],\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":";;;;;;;;;AAmCA,SAAS,iBAAiB,KAAyB;CAClD,MAAM,SAAqB,EAAE;CAC7B,IAAI,UAA2B;CAC/B,IAAI,eAAiC;AAErC,MAAK,MAAM,QAAQ,IAAI,MAAM,KAAK,EAAE;EACnC,MAAM,cAAc,KAAK,MAAM,eAAe;AAC9C,MAAI,aAAa;AAChB,OAAI,WAAW,cAAc;AAC5B,YAAQ,MAAM,KAAK,aAAa;AAChC,mBAAe;;AAEhB,aAAU;IACT,MAAM,YAAY,GAAG,MAAM;IAC3B,aAAa;IACb,OAAO,EAAE;IACT;AACD,UAAO,KAAK,QAAQ;AACpB;;EAGD,MAAM,aAAa,KAAK,MAAM,2BAA2B;AACzD,MAAI,cAAc,WAAW,CAAC,cAAc;GAC3C,IAAI,OAAO,WAAW,GAAG,MAAM;AAC/B,OACE,KAAK,WAAW,KAAI,IAAI,KAAK,SAAS,KAAI,IAC1C,KAAK,WAAW,IAAI,IAAI,KAAK,SAAS,IAAI,CAE3C,QAAO,KAAK,MAAM,GAAG,GAAG;AAEzB,WAAQ,cAAc;AACtB;;AAGD,MAAI,KAAK,MAAM,iBAAiB,IAAI,QAAS;EAE7C,MAAM,cAAc,KAAK,MAAM,yBAAyB;AACxD,MAAI,eAAe,SAAS;AAC3B,OAAI,aAAc,SAAQ,MAAM,KAAK,aAAa;AAClD,kBAAe;IACd,OAAO,YAAY,GAAG,MAAM;IAC5B,QAAQ;IACR;AACD;;EAGD,MAAM,eAAe,KAAK,MAAM,sBAAsB;AACtD,MAAI,gBAAgB,cAAc;GACjC,IAAI,SAAS,aAAa,GAAG,MAAM;AACnC,OACE,OAAO,WAAW,KAAI,IAAI,OAAO,SAAS,KAAI,IAC9C,OAAO,WAAW,IAAI,IAAI,OAAO,SAAS,IAAI,CAE/C,UAAS,OAAO,MAAM,GAAG,GAAG;AAE7B,YAAS,OAAO,QAAQ,QAAQ,KAAK;AACrC,gBAAa,SAAS;AACtB;;;AAIF,KAAI,WAAW,aACd,SAAQ,MAAM,KAAK,aAAa;AAGjC,QAAO;;AAKR,SAAS,iBAAiB,UAAmC;AAC5D,KAAI;EAEH,MAAM,EAAE,aAAa,SAAS,iBADlB,aAAa,UAAU,QAAQ,CAKpC;AAEP,MAAI,CAAC,aAAa,KAAM,QAAO;AAE/B,SAAO;GACN,MAAM,YAAY;GAClB,aAAa,YAAY,eAAe;GACxC,OAAO,YAAY,SAAS;GAC5B,cAAc,KAAK,MAAM;GACzB;SACM;AACP,SAAO;;;AAIT,SAAS,gBAAgB,KAAoC;CAC5D,MAAM,OAAO;EACZ,KAAK,KAAK,SAAS;EACnB,KAAK,KAAK,WAAW,SAAS;EAC9B,KAAK,KAAK,OAAO,SAAS;EAC1B;CAED,MAAM,yBAAS,IAAI,KAAuB;AAE1C,MAAK,MAAM,OAAO,MAAM;AACvB,MAAI,CAAC,WAAW,IAAI,CAAE;AACtB,MAAI;AACH,QAAK,MAAM,QAAQ,YAAY,IAAI,EAAE;AACpC,QAAI,CAAC,KAAK,SAAS,MAAM,CAAE;IAC3B,MAAM,MAAM,iBAAiB,QAAQ,KAAK,KAAK,CAAC;AAChD,QAAI,OAAO,CAAC,OAAO,IAAI,IAAI,KAAK,aAAa,CAAC,CAC7C,QAAO,IAAI,IAAI,KAAK,aAAa,EAAE,IAAI;;UAGlC;;AAKT,QAAO;;AAKR,SAAS,eACR,WACA,MACgD;CAEhD,MAAM,MAAM,QAAQ,KAAK;CACzB,MAAM,OAAO;EAAC;EAAgB;EAAM;EAAK;CAEzC,MAAM,SAAmB,EAAE;AAE3B,QAAO,IAAI,SAAS,QAAQ;EAC3B,MAAM,OAAO,MAAM,QAAQ,UAAU,CAAC,KAAK,GAAG,KAAK,EAAE;GACpD,OAAO;IAAC;IAAU;IAAQ;IAAO;GACjC,KAAK;IACJ,GAAG,QAAQ;IACX,2BAA2B,UAAU;IACrC;GACD,CAAC;AAEF,OAAK,OAAQ,YAAY,QAAQ;AACjC,OAAK,OAAQ,GAAG,SAAS,UAAkB;AAC1C,UAAO,KAAK,MAAM;IACjB;AAEF,OAAK,OAAQ,YAAY,QAAQ;AACjC,OAAK,OAAQ,GAAG,cAAc,GAAG;AAEjC,OAAK,GAAG,UAAU,SAAS;AAC1B,OAAI;IACH,QAAQ,OAAO,KAAK,GAAG,CAAC,MAAM;IAC9B,UAAU,QAAQ;IAClB,CAAC;IACD;AAEF,OAAK,GAAG,UAAU,QAAQ;AACzB,OAAI;IACH,QAAQ,yBAAyB,IAAI;IACrC,UAAU;IACV,CAAC;IACD;GACD;;AAMH,eAA8B,MAAM,IAAkB;CACrD,MAAM,MAAM,QAAQ,KAAK;CACzB,MAAM,SAAS,gBAAgB,IAAI;CACnC,IAAI,SAAqB,EAAE;CAC3B,IAAI,eAAgC;CAGpC,MAAM,cAAc;EACnB,KAAK,KAAK,OAAO,UAAU,mBAAmB;EAC9C,KAAK,KAAK,OAAO,UAAU,cAAc;EACzC,KAAK,KAAK,WAAW,UAAU,cAAc;EAC7C;AAED,MAAK,MAAM,QAAQ,YAClB,KAAI,WAAW,KAAK,CACnB,KAAI;AACH,WAAS,iBAAiB,aAAa,MAAM,QAAQ,CAAC;AACtD;SACO;AAMV,KAAI,OAAO,SAAS,EACnB,gBAAe,OAAO;AAKvB,IAAG,aACF,WAAW;EACV,MAAM;EACN,OAAO;EACP,aACC;EACD,YAAY,KAAK,OAAO,EACvB,MAAM,KAAK,OAAO,EACjB,aAAa,4CACb,CAAC,EACF,CAAC;EACF,SAAS,OACR,KACA,WAIK;GACL,MAAM,EAAE,SAAS;AAEjB,OAAI,CAAC,aACJ,QAAO;IACN,SAAS,CACR;KACC,MAAM;KACN,MAAM;KACN,CACD;IACD,SAAS;KACR,OAAO;KACP,OAAO;KACP;IACD;GAGF,IAAI,QAAQ;GACZ,MAAM,WAAW;GACjB,MAAM,UAAoB,EAAE;AAE5B,QAAK,IAAI,IAAI,GAAG,IAAI,aAAa,MAAM,QAAQ,KAAK;IACnD,MAAM,OAAO,aAAa,MAAM;IAChC,MAAM,YAAY,OAAO,IAAI,KAAK,MAAM,aAAa,CAAC;AAEtD,QAAI,CAAC,WAAW;KACf,MAAM,MAAM,QAAQ,IAAI,EAAE,WAAW,KAAK,MAAM,0BAA0B,MAAM,KAAK,OAAO,MAAM,CAAC,CAAC,KAAK,KAAK;AAC9G,aAAQ,KAAK,IAAI;AACjB,YAAO;MACN,SAAS,CAAC;OAAE,MAAM;OAAiB,MAAM;OAAK,CAAC;MAC/C,SAAS;OACR,OAAO,aAAa;OACpB,OAAO;OACP;MACD;;IAOF,MAAM,SAAS,MAAM,eACpB,WALuB,KAAK,OAC3B,QAAQ,YAAY,MAAM,CAC1B,QAAQ,eAAe,SAAS,CAKjC;AAED,QAAI,OAAO,aAAa,GAAG;KAC1B,MAAM,MAAM,QAAQ,IAAI,EAAE,IAAI,KAAK,MAAM,aAAa,OAAO;AAC7D,aAAQ,KAAK,IAAI;AACjB,YAAO;MACN,SAAS,CAAC;OAAE,MAAM;OAAiB,MAAM;OAAK,CAAC;MAC/C,SAAS;OACR,OAAO,aAAa;OACpB,OAAO,IAAI;OACX;MACD;;AAGF,YAAQ,KACP,WAAW,IAAI,EAAE,IAAI,KAAK,MAAM,IAAI,OAAO,SAC3C;AACD,YAAQ,OAAO;;AAIhB,UAAO;IACN,SAAS,CAAC;KAAE,MAAM;KAAiB,MAFpB,QAAQ,KAAK,cAAc;KAEQ,CAAC;IACnD,SAAS;KACR,OAAO,aAAa;KACpB,OAAO,aAAa,MAAM;KAC1B;IACD;;EAEF,CAAC,CACF;AAID,IAAG,gBAAgB,SAAS;EAC3B,aAAa;EACb,yBAAyB,WAAW;GACnC,MAAM,QAAQ,OAAO,MAAM,CAAC,MAAM,MAAM;AACxC,OAAI,MAAM,UAAU,EAEnB,QADa,CAAC,QAAQ,GAAG,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC,CAEjD,QAAQ,MAAM,EAAE,WAAW,MAAM,MAAM,GAAG,CAAC,CAC3C,KAAK,OAAO;IAAE,OAAO;IAAG,OAAO;IAAG,EAAE;AAEvC,UAAO;;EAER,SAAS,OAAO,MAAM,QAAQ;GAC7B,MAAM,MAAM,KAAK,MAAM;AAEvB,OAAI,CAAC,OAAO,QAAQ,QAAQ;AAC3B,QAAI,OAAO,WAAW,GAAG;AACxB,SAAI,GAAG,OACN,8DACA,UACA;AACD;;IAED,MAAM,QAAQ,OAAO,KAAK,MAAM;KAC/B,MAAM,SAAS,EAAE,SAAS,cAAc,OAAO,OAAO;KACtD,MAAM,QAAQ,EAAE,MAAM,KAAK,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO;AACtD,YAAO,GAAG,EAAE,OAAO,OAAO,IAAI,EAAE,eAAe;MAC9C;AACF,QAAI,GAAG,OAAO,MAAM,KAAK,KAAK,CAAC;AAC/B;;GAGD,MAAM,cAAc,OAAO,MACzB,MAAM,EAAE,KAAK,aAAa,KAAK,IAAI,aAAa,CACjD;AACD,OAAI,CAAC,aAAa;AACjB,QAAI,GAAG,OACN,kBAAkB,IAAI,qBACtB,UACA;AACD;;AAGD,kBAAe;GACf,MAAM,OAAO,YAAY,MAAM,KAAK,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO;AAC/D,OAAI,GAAG,OAAO,iBAAiB,YAAY,KAAK,IAAI,KAAK,GAAG;;EAE7D,CAAC;AAIF,IAAG,GACF,sBACA,OAAO,UAAoC;AAC1C,MAAI,CAAC,gBAAgB,OAAO,WAAW,EAAG,QAAO,EAAE;EAEnD,MAAM,OAAO,aAAa,MACxB,KAAK,MAAM,EAAE,MAAM,CACnB,KAAK,OAAO;EAEd,MAAM,YAAY,aAAa,MAC7B,KAAK,GAAG,MAAM;GAEd,MAAM,OADM,OAAO,IAAI,EAAE,MAAM,aAAa,CAAC,EAC3B,eAAe;AACjC,UAAO,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,OAAO;IACpC,CACD,KAAK,KAAK;EAEZ,MAAM,aAAa,OACjB,KAAK,MAAM;GACX,MAAM,SACL,EAAE,SAAS,cAAc,OAAO,cAAc;AAC/C,UAAO,KAAK,EAAE,OAAO,OAAO,IAAI,EAAE;IACjC,CACD,KAAK,KAAK;AAGZ,SAAO,EACN,cACC,MAAM,eACN;;;;;;oBAMe,aAAa,KAAK;EACpC,aAAa,YAAY;QACnB,KAAK;;EAEX,UAAU;;;EAGV,WAAW;;;;;;;;;;;;oCAaT;GAEF;AAID,IAAG,gBAAgB,UAAU;EAC5B,aAAa;EACb,SAAS,OAAO,OAAO,QAAQ;AAC9B,OAAI,OAAO,SAAS,GAAG;AACtB,QAAI,GAAG,OACN,+DACA,UACA;AACD;;GAED,MAAM,QAAQ,MAAM,KAAK,OAAO,QAAQ,CAAC,CAAC,KACxC,MACA,GAAG,EAAE,KAAK,IAAI,EAAE,eAAe,mBAAmB,IAAI,EAAE,MAAM,GAC/D;AACD,OAAI,GAAG,OAAO,MAAM,KAAK,KAAK,CAAC;;EAEhC,CAAC;;;;ACnaH,MAAMA,mBAA0C;CAC/C,SAAS;CACT,SAAS,EAAE;CACX;AAED,MAAa,qBAA6C;CACzD;EACC,KAAK;EACL,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,CAAC,MAAM;EAChB;CACD;EACC,KAAK;EACL,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,CAAC,UAAU,QAAQ;EAC5B;CACD;EACC,KAAK;EACL,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,CAAC,SAAS,SAAS;EAC5B;CACD;EACC,KAAK;EACL,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;GACR;GACA;GACA;GACA;GACA;EACD;CACD;EACC,KAAK;EACL,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,CAAC,UAAU;EACpB;CACD;EACC,KAAK;EACL,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,CAAC,SAAS;EACnB;CACD;AAED,SAAgB,qCAA6C;AAG5D,QAAO,KADN,QAAQ,IAAI,mBAAmB,KAAK,SAAS,EAAE,UAAU,EACzC,SAAS,kBAAkB;;AAG7C,SAAgB,iCAA0D;CACzE,MAAM,OAAO,oCAAoC;AACjD,KAAI,CAAC,WAAW,KAAK,CAAE,QAAO,EAAE,GAAGA,kBAAgB;AAEnD,KAAI;EACH,MAAM,MAAM,aAAa,MAAM,QAAQ;EACvC,MAAM,SAAS,KAAK,MACnB,IACA;EACD,MAAM,UAA8C,EAAE;AACtD,OAAK,MAAM,aAAa,oBAAoB;GAC3C,MAAM,QAAQ,OAAO,UAAU,UAAU;AACzC,OAAI,OAAO,UAAU,UACpB,SAAQ,UAAU,OAAO;;AAI3B,SAAO;GACN,SAAS,OAAO,WAAW;GAC3B;GACA;SACM;AACP,SAAO,EAAE,GAAGA,kBAAgB;;;AAI9B,SAAgB,+BACf,QACO;CACP,MAAM,OAAO,oCAAoC;CACjD,MAAM,MAAM,QAAQ,KAAK;AACzB,KAAI,CAAC,WAAW,IAAI,CACnB,WAAU,KAAK;EAAE,WAAW;EAAM,MAAM;EAAO,CAAC;CAGjD,MAAM,MAAM,GAAG,KAAK,OAAO,KAAK,KAAK;AACrC,eAAc,KAAK,KAAK,UAAU,QAAQ,MAAM,IAAK,GAAG,MAAM,EAC7D,MAAM,KACN,CAAC;AACF,YAAW,KAAK,KAAK;;AAGtB,SAAgB,6BACf,QACA,KACU;AACV,QAAO,OAAO,QAAQ,QAAQ;;AAG/B,SAAgB,4BACf,QACA,KACA,iCAAmD,IAAI,KAAK,EAClD;AACV,QACC,6BAA6B,QAAQ,IAAI,IACzC,CAAC,eAAe,IAAI,IAAI;;AAI1B,SAAgB,iCACf,iCAAmD,IAAI,KAAK,EAC5D,SAAkC,gCAAgC,EACxC;AAC1B,QAAO,mBAAmB,KAAK,cAAc;EAC5C,MAAM,gBAAgB,6BACrB,QACA,UAAU,IACV;EACD,MAAM,SAAS,eAAe,IAAI,UAAU,IAAI;AAChD,SAAO;GACN,GAAG;GACH;GACA,mBAAmB,iBAAiB,CAAC;GACrC,iBAAiB;GACjB;GACA;;AAGH,SAAgB,uBACf,OACmC;CACnC,MAAM,aAAa,MAAM,MAAM,CAAC,aAAa;AAC7C,KAAI,CAAC,WAAY,QAAO,KAAA;AAExB,QAAO,mBAAmB,MAAM,cAC/B;EAAC,UAAU;EAAK,UAAU;EAAO,GAAG,UAAU;EAAQ,CAAC,MACrD,UAAU,MAAM,aAAa,KAAK,WACnC,CACD;;;;AC1KF,MAAMC,YAAU;AAChB,MAAMC,aAAW;AAMjB,SAAS,sBACR,gBACmC;AACnC,QAAO,IAAI,IAAI,kBAAkB,EAAE,CAAC;;AAGrC,SAAS,uBACR,OACS;AACT,KAAI,MAAM,kBACT,QAAO;AAER,KAAI,MAAM,gBACT,QAAO,+BAA+B,MAAM;AAE7C,QAAO;;AAGR,SAAS,uBACR,QACA,SACS;CACT,MAAM,QAAkB,EAAE;AAC1B,KAAI,SAAS,QACZ,OAAM,KAAK,QAAQ,SAAS,GAAG;CAGhC,MAAM,cAAc,OAAO,QACzB,UAAU,MAAM,kBACjB,CAAC;CACF,MAAM,eAAe,OAAO,SAAS;AACrC,OAAM,KACL,GAAG,OAAO,OAAO,wBAAwB,YAAY,gBAAgB,aAAa,iBAClF,GACA;AAED,MAAK,MAAM,SAAS,QAAQ;AAC3B,QAAM,KACL,GAAG,MAAM,gBAAgBD,YAAUC,WAAS,GAAG,MAAM,QACrD;AACD,QAAM,KAAK,YAAY,MAAM,MAAM;AACnC,QAAM,KACL,qBAAqB,MAAM,gBAAgB,YAAY,aACvD;AACD,QAAM,KACL,wBAAwB,uBAAuB,MAAM,GACrD;AACD,QAAM,KAAK,OAAO,MAAM,cAAc;;AAGvC,QAAO,MAAM,KAAK,KAAK;;AAGxB,SAASC,kBAAgB,OAA2C;CACnE,MAAM,eAAe;EACpB,MAAM;EACN,MAAM;EACN,oBAAoB,uBAAuB,MAAM;EACjD,qBAAqB,MAAM;EAC3B;AAED,QAAO;EACN,IAAI,MAAM;EACV,OAAO,MAAM;EACb,aAAa,aAAa,KAAK,KAAK;EACpC,cAAc,MAAM,gBAAgBF,YAAUC;EAC9C,QAAQ,CAACD,WAASC,WAAS;EAC3B;;AAGF,SAASE,aACR,GACA,GACU;AACV,KAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAC9B,MAAK,MAAM,SAAS,EACnB,KAAI,CAAC,EAAE,IAAI,MAAM,CAAE,QAAO;AAE3B,QAAO;;AAGR,SAAS,cACR,QACA,OAC0B;CAC1B,MAAM,aAAa,MAAM,MAAM,CAAC,aAAa;AAC7C,KAAI,CAAC,WAAY,QAAO;AAExB,QAAO,OAAO,QAAQ,UACrB;EACC,MAAM;EACN,MAAM;EACN,MAAM;EACN,GAAG,MAAM;EACT,CAAC,MAAM,UAAU,MAAM,aAAa,CAAC,SAAS,WAAW,CAAC,CAC3D;;AAGF,SAAS,uBACR,KACA,SACO;CACP,MAAM,SAAS,gCAAgC;AAC/C,QAAO,QAAQ,OAAO;AACtB,gCAA+B,OAAO;;AAGvC,SAAgB,4BACf,UAAoC,EAAE,EACrC;CACD,MAAM,iBAAiB,sBACtB,QAAQ,eACR;AAED,QAAO,eAAe,WAAW,IAAkB;EAClD,MAAM,OAAO;GAAC;GAAQ;GAAU;GAAW;GAAU;GAAS;AAE9D,KAAG,gBAAgB,cAAc;GAChC,aAAa;GACb,yBAAyB,WAAW;IACnC,MAAM,QAAQ,OAAO,MAAM,CAAC,MAAM,MAAM;AACxC,QAAI,MAAM,UAAU,EACnB,QAAO,KACL,QAAQ,QAAQ,IAAI,WAAW,MAAM,MAAM,GAAG,CAAC,CAC/C,KAAK,SAAS;KAAE,OAAO;KAAK,OAAO;KAAK,EAAE;AAG7C,QAAI;KAAC;KAAU;KAAW;KAAS,CAAC,SAAS,MAAM,GAAG,EAAE;KACvD,MAAM,IAAI,MAAM,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC,aAAa;AAChD,YAAO,iCAAiC,eAAe,CACrD,QACC,UACA,MAAM,IAAI,aAAa,CAAC,SAAS,EAAE,IACnC,MAAM,MAAM,aAAa,CAAC,SAAS,EAAE,CACtC,CACA,MAAM,GAAG,GAAG,CACZ,KAAK,WAAW;MAChB,OAAO,GAAG,MAAM,GAAG,GAAG,MAAM;MAC5B,OAAO,GAAG,MAAM,IAAI,GAAG,MAAM,gBAAgBH,YAAUC;MACvD,EAAE;;AAGL,WAAO;;GAER,SAAS,OAAO,MAAM,QAAQ;IAC7B,MAAM,UAAU,KAAK,MAAM;AAE3B,QAAI,CAAC,WAAW,IAAI,OAAO;KAC1B,MAAM,SACL,iCAAiC,eAAe;KACjD,MAAM,kBAAkB,IAAI,IAC3B,OACE,QAAQ,UAAU,MAAM,cAAc,CACtC,KAAK,UAAU,MAAM,IAAI,CAC3B;KACD,MAAM,kBAAkB,IAAI,IAAI,gBAAgB;AAEhD,WAAM,IAAI,GAAG,QAAQ,KAAK,OAAO,KAAK,SAAS;MAC9C,MAAM,QAAQ,OAAO,IAAIC,kBAAgB;MACzC,MAAM,YAAY,IAAI,WAAW;AAEjC,gBAAU,SAAS;OAClB,cAAc;QACb,MAAM,gBAAgB,gBAAgB;QACtC,MAAM,iBAAiB,OAAO,SAAS;QACvC,MAAM,cAAc,CAAC,GAAG,gBAAgB,CAAC,QACvC,QACA,CAAC,eAAe,IAAI,IAA2B,CAChD,CAAC;QACF,MAAM,eAAe,OAAO,SAAS;AACrC,eAAO;SACN,MAAM,GACL,UACA,MAAM,KAAK,sBAAsB,CACjC;SACD,MAAM,GACL,SACA,GAAG,cAAc,mBAAmB,eAAe,oBAAoB,YAAY,iBAAiB,aAAa,eACjH;SACD;SACA;;OAEF,kBAAkB;OAClB,CAAC;MAEF,MAAM,gBAAgB,IAAI,aACzB,OACA,KAAK,IAAI,KAAK,IAAI,MAAM,SAAS,GAAG,EAAE,EAAE,GAAG,EAC3C;OACC,QAAQ,MAAM,GAAG,UAAU,IAAI;OAC/B,QAAQ,MAAM,aACb,WAAW,MAAM,GAAG,UAAU,KAAK,GAAG;OACvC,QAAQ,MAAM,aAAa;QAC1B,MAAM,QAAQ,SAASF,YAAU,YAAY;QAC7C,MAAM,WAAW,MAAM,GAAG,OAAO,KAAK;AACtC,eAAO,WACJ,MAAM,KAAK,MAAM,GAAG,UAAU,SAAS,CAAC,GACxC;;OAEJ,cAAc,SAAS,MAAM,GAAG,SAAS,KAAK;OAC9C,OAAO,SAAS,MAAM,GAAG,OAAO,KAAK;OACrC,GACA,IAAI,cAAc;OAClB,MAAM,MAAM;OACZ,MAAM,UAAU,cAAcA;AAC9B,WAAI,QACH,iBAAgB,IAAI,IAAI;WAExB,iBAAgB,OAAO,IAAI;AAE5B,8BAAuB,KAAK,QAAQ;eAE/B,KAAK,KAAA,EAAU,EACrB,EAAE,cAAc,MAAM,CACtB;AAED,gBAAU,SAAS,cAAc;AACjC,gBAAU,SACT,IAAI,KACH,MAAM,GACL,OACA,qGACA,EACD,GACA,EACA,CACD;AAED,aAAO;OACN,OAAO,OAAe;AACrB,eAAO,UAAU,OAAO,MAAM;;OAE/B,aAAa;AACZ,kBAAU,YAAY;;OAEvB,YAAY,MAAc;AACzB,sBAAc,YAAY,KAAK;AAC/B,YAAI,eAAe;;OAEpB;OACA;AAEF,SAAI,CAACG,aAAW,iBAAiB,gBAAgB,EAAE;AAClD,UAAI,GAAG,OACN,eAAe,OAAO,IACnB,0HACA,qDACH,OACA;AACD,YAAM,IAAI,QAAQ;AAClB;;AAGD;;IAGD,MAAM,CAAC,KAAK,GAAG,SAAS,WAAW,QAAQ,MAAM,MAAM;IACvD,MAAM,MAAM,KAAK,KAAK,IAAI;IAC1B,MAAM,SACL,iCAAiC,eAAe;AAEjD,YAAQ,KAAR;KACC,KAAK;AACJ,UAAI,GAAG,OACN,uBAAuB,QAAQ,EAC9B,SAAS,uBACT,CAAC,CACF;AACD;KAED,KAAK;KACL,KAAK;KACL,KAAK,UAAU;AACd,UAAI,CAAC,KAAK;AACT,WAAI,GAAG,OACN,sBAAsB,IAAI,SAC1B,UACA;AACD;;MAGD,MAAM,YAAY,uBAAuB,IAAI;AAC7C,UAAI,CAAC,WAAW;AACf,WAAI,GAAG,OACN,sBAAsB,IAAI,SAAS,mBAAmB,KAAK,SAAS,KAAK,IAAI,CAAC,KAAK,KAAK,IACxF,UACA;AACD;;MAGD,MAAM,gBAAgB,OAAO,MAC3B,UAAU,MAAM,QAAQ,UAAU,IACnC;MACD,MAAM,eACL,QAAQ,WACL,OACA,QAAQ,YACP,QACA,CAAC,eAAe;AACrB,6BAAuB,UAAU,KAAK,aAAa;AAEnD,UAAI,GAAG,OACN,gBAAgB,eAAe,IAAI,UAAU,IAAI,GAC9C,WAAW,UAAU,IAAI,sDAAsD,UAAU,SAAS,oDAClG,GAAG,UAAU,IAAI,GAAG,eAAe,YAAY,WAAW,qBAC7D;AACD;;KAED,KAAK,UAAU;AACd,UAAI,CAAC,KAAK;AACT,WAAI,GAAG,OACN,qCACA,UACA;AACD;;MAED,MAAM,UAAU,cAAc,QAAQ,IAAI;AAC1C,UAAI,QAAQ,WAAW,GAAG;AACzB,WAAI,GAAG,OACN,oCAAoC,IAAI,GACxC;AACD;;AAED,UAAI,GAAG,OACN,uBAAuB,SAAS,EAC/B,SAAS,iCAAiC,IAAI,IAC9C,CAAC,CACF;AACD;;KAED,QACC,KAAI,GAAG,OACN,YAAY,IAAI,SAAS,KAAK,KAAK,KAAK,IACxC,UACA;;;GAGJ,CAAC;;;AAIW,6BAA6B;;;ACnW5C,MAAM,kBAAmC;CACxC;EAAE,MAAM;EAAkB,SAAS;EAAqB;CACxD;EACC,MAAM;EACN,SACC;EACD;CACD;EACC,MAAM;EACN,SAAS;EACT;CACD;EACC,MAAM;EACN,SAAS;EACT;CACD;EACC,MAAM;EACN,SAAS;EACT;CACD;EACC,MAAM;EACN,SAAS;EACT;CACD;EACC,MAAM;EACN,SACC;EACD;CACD;EACC,MAAM;EACN,SAAS;EACT;CACD;EACC,MAAM;EACN,SAAS;EACT;CACD;EACC,MAAM;EACN,SACC;EACD;CACD;EACC,MAAM;EACN,SAAS;EACT;CACD;EACC,MAAM;EACN,SAAS;EACT;CACD;EACC,MAAM;EACN,SAAS;EACT;CACD;EACC,MAAM;EACN,SAAS;EACT;CACD;EACC,MAAM;EACN,SAAS;EACT;CACD;AAED,SAAS,OAAO,MAAmD;CAClE,IAAI,QAAQ;CACZ,IAAI,SAAS;AAEb,MAAK,MAAM,MAAM,iBAAiB;AAEjC,KAAG,QAAQ,YAAY;AACvB,WAAS,OAAO,QAAQ,GAAG,UAAU,UAAU;AAC9C;AAEA,UAAO,GADQ,MAAM,MAAM,GAAG,EAAE,GACb,IAAI,OAAO,KAAK,IAAI,MAAM,SAAS,GAAG,GAAG,CAAC,CAAC,YAAY,GAAG,KAAK;IACjF;;AAGH,QAAO;EAAE,UAAU;EAAQ;EAAO;;AAInC,eAA8B,cAAc,IAAkB;CAC7D,IAAI,gBAAgB;AAGpB,IAAG,GAAG,eAAwB,OAAO,UAAe;AACnD,MAAI,CAAC,MAAM,QAAS;EAEpB,IAAI,WAAW;EACf,MAAM,aAAa,MAAM,QAAQ,KAC/B,SAA0C;AAC1C,OAAI,KAAK,SAAS,UAAU,CAAC,KAAK,KAAM,QAAO;GAC/C,MAAM,EAAE,UAAU,UAAU,OAAO,KAAK,KAAK;AAC7C,OAAI,QAAQ,GAAG;AACd,eAAW;AACX,qBAAiB;;AAElB,UAAO;IAAE,GAAG;IAAM,MAAM;IAAU;IAEnC;AAED,MAAI,SACH,QAAO,EAAE,SAAS,YAAY;GAE9B;AAEF,IAAG,gBAAgB,gBAAgB;EAClC,aAAa;EACb,SAAS,OAAO,OAAO,QAAQ;AAC9B,OAAI,GAAG,OACN,kCAAkC,gBAClC;;EAEF,CAAC;;;;ACnHH,eAA8B,QAAQ,IAAkB;CACvD,MAAM,UAID,EAAE;AAGP,IAAG,GAAG,eAAe,OAAO,UAAU;EACrC,MAAM,MAAM,MAAM;AAClB,MAAI,CAAC,IAAK;EAEV,MAAM,UAAU,IAAI;AAGpB,MAAI,CAAC,MAAM,QAAQ,QAAQ,CAAE;EAE7B,MAAM,OAAO,QACX,QAAQ,MAAM,EAAE,SAAS,OAAO,CAChC,KAAK,MAAM,EAAE,QAAQ,GAAG,CACxB,KAAK,KAAK;AAEZ,MAAI,CAAC,KAAM;EAEX,MAAM,UACL,KAAK,SAAS,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,QAAQ;AAElD,UAAQ,KAAK;GACZ,MAAO,IAAI,QAAmB;GAC9B;GACA,WAAW,KAAK,KAAK;GACrB,CAAC;GACD;AAEF,IAAG,gBAAgB,WAAW;EAC7B,aACC;EACD,SAAS,OAAO,MAAM,QAAQ;GAC7B,MAAM,OAAO,KAAK,MAAM;AAExB,OAAI,QAAQ,WAAW,GAAG;AACzB,QAAI,GAAG,OACN,uCACA,UACA;AACD;;GAOD,MAAM,UAAU;;;;;EAJA,QACd,KAAK,MAAM,IAAI,EAAE,KAAK,IAAI,EAAE,UAAU,CACtC,KAAK,OAAO,CAOP;;;EAGR,QAAQ,qDAAqD;;;;;;;GAS5D,MAAM,WAAW,WAAW,KAAK,KAAK,CAAC;AAEvC,iBADiB,KAAK,IAAI,KAAK,SAAS,EAChB,SAAS,QAAQ;AAEzC,OAAI,GAAG,OACN,sBAAsB,SAAS,mBAAmB,WAClD;;EAEF,CAAC;;;;ACxDH,IAAa,YAAb,MAAuB;CACtB,QAA6B;CAC7B;CACA,UAAU;CACV,2BAAW,IAAI,KAMZ;CACH,UAAU;CAEV,YAAY,QAAyB;AACpC,QAAA,SAAe;;CAGhB,MAAM,UAAyB;EAC9B,MAAM,EAAE,SAAS,OAAO,EAAE,EAAE,QAAQ,MAAA;AAEpC,QAAA,OAAa,MAAM,SAAS,MAAM;GACjC,OAAO;IAAC;IAAQ;IAAQ;IAAO;GAC/B,KAAK;IAAE,GAAG,QAAQ;IAAK,GAAG;IAAK;GAC/B,CAAC;AAEF,QAAA,KAAW,OAAQ,YAAY,OAAO;AACtC,QAAA,KAAW,OAAQ,GAAG,SAAS,UAAkB;AAChD,SAAA,UAAgB;GAChB,MAAM,QAAQ,MAAA,OAAa,MAAM,KAAK;AACtC,SAAA,SAAe,MAAM,KAAK,IAAI;AAE9B,QAAK,MAAM,QAAQ,OAAO;AACzB,QAAI,CAAC,KAAK,MAAM,CAAE;AAClB,QAAI;KACH,MAAM,MAAM,KAAK,MAAM,KAAK;AAC5B,SAAI,IAAI,MAAM,QAAQ,MAAA,QAAc,IAAI,IAAI,GAAG,EAAE;MAChD,MAAM,IAAI,MAAA,QAAc,IAAI,IAAI,GAAG;AACnC,YAAA,QAAc,OAAO,IAAI,GAAG;AAC5B,UAAI,IAAI,MACP,GAAE,uBACD,IAAI,MACH,aAAa,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,UAC1C,CACD;UAED,GAAE,QAAQ,IAAI,OAAO;;YAGhB;;IAIR;AAGF,QAAM,MAAA,QAAc,cAAc;GACjC,iBAAiB;GACjB,cAAc,EAAE;GAChB,YAAY;IAAE,MAAM;IAAS,SAAS;IAAS;GAC/C,CAAC;AAGF,QAAA,KAAW;GACV,SAAS;GACT,QAAQ;GACR,CAA8B;;CAGhC,MAAM,YAAoC;AAIzC,UAHgB,MAAM,MAAA,QAAc,cAAc,EAAE,CAAC,EAGvC;;CAGf,MAAM,SACL,MACA,MACmB;AACnB,SAAO,MAAA,QAAc,cAAc;GAClC;GACA,WAAW;GACX,CAAC;;CAGH,MAAM,aAA4B;AACjC,MAAI,MAAA,MAAY;AACf,SAAA,KAAW,MAAM;AACjB,SAAA,OAAa;;AAEd,QAAA,QAAc,OAAO;;CAGtB,SAAS,QAAgB,QAAmC;AAC3D,SAAO,IAAI,SAAS,SAAS,WAAW;GACvC,MAAM,KAAK,MAAA;AACX,SAAA,QAAc,IAAI,IAAI;IAAE;IAAS;IAAQ,CAAC;AAC1C,SAAA,KAAW;IAAE,SAAS;IAAO;IAAI;IAAQ;IAAQ,CAAC;AAElD,oBAAiB;AAChB,QAAI,MAAA,QAAc,IAAI,GAAG,EAAE;AAC1B,WAAA,QAAc,OAAO,GAAG;AACxB,4BAAO,IAAI,MAAM,eAAe,OAAO,YAAY,CAAC;;MAEnD,IAAO;IACT;;CAGH,MAAM,KAAqB;AAC1B,MAAI,CAAC,MAAA,MAAY,OAAO,SACvB,OAAM,IAAI,MAAM,2BAA2B;AAE5C,QAAA,KAAW,MAAM,MAAM,KAAK,UAAU,IAAI,GAAG,KAAK;;;;;AC7HpD,SAAS,YAAY,MAA2C;AAC/D,KAAI,CAAC,WAAW,KAAK,CAAE,QAAO,EAAE;CAChC,MAAM,MAAM,aAAa,MAAM,QAAQ;AAEvC,QADe,KAAK,MAAM,IAAI,CAChB,cAAc,EAAE;;AAG/B,SAAgB,gBAAgB,KAAgC;CAE/D,MAAM,iBAAiB,YACtB,KAAK,SAAS,EAAE,OAAO,SAAS,WAAW,CAC3C;CAGD,MAAM,kBAAkB,YAAY,KAAK,KAAK,WAAW,CAAC;CAE1D,MAAM,SAAS;EAAE,GAAG;EAAgB,GAAG;EAAiB;AAExD,QAAO,OAAO,QAAQ,OAAO,CAAC,KAAK,CAAC,MAAM,aAAa;EACtD;EACA,SAAS,OAAO;EAChB,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,EAAE;;;;ACxBJ,eAA8B,IAAI,IAAkB;CACnD,MAAM,MAAM,QAAQ,KAAK;CACzB,MAAM,0BAAU,IAAI,KAA0B;CAC9C,MAAM,UAAU,gBAAgB,IAAI;CAGpC,MAAM,UAAU,MAAM,QAAQ,WAC7B,QAAQ,IAAI,OAAO,WAAW;EAC7B,MAAM,SAAS,IAAI,UAAU,OAAO;AACpC,QAAM,OAAO,SAAS;AAEtB,SAAO;GAAE;GAAQ;GAAQ,WADP,MAAM,OAAO,WAAW;GACN;GACnC,CACF;AAED,MAAK,MAAM,UAAU,SAAS;AAC7B,MAAI,OAAO,WAAW,YAAY;AACjC,WAAQ,MAAM,sBAAsB,OAAO,SAAS;AACpD;;EAGD,MAAM,EAAE,QAAQ,QAAQ,cAAc,OAAO;EAC7C,MAAM,aAAuB,EAAE;AAE/B,OAAK,MAAM,YAAY,WAAW;GACjC,MAAM,YAAY,QAAQ,OAAO,KAAK,IAAI,SAAS;AACnD,cAAW,KAAK,UAAU;AAE1B,MAAG,aACF,WAAW;IACV,MAAM;IACN,OAAO,GAAG,OAAO,KAAK,IAAI,SAAS;IACnC,aAAa,SAAS,eAAe,SAAS;IAC9C,YAAa,SAAS,eAAe;KACpC,MAAM;KACN,YAAY,EAAE;KACd;IACD,SAAS,OAAO,KAAK,WAAW;KAC/B,MAAM,SAAU,MAAM,OAAO,SAC5B,SAAS,MACT,OACA;AAWD,YAAO;MACN,SAAS,CAAC;OAAE,MAAM;OAAiB,MAJnC,QAAQ,SAAS,KAAK,MAAM,EAAE,QAAQ,GAAG,CAAC,KAAK,KAAK,IACpD,KAAK,UAAU,OAAO;OAGmB,CAAC;MAC1C,SAAS,EAAE;MACX;;IAEF,CAAC,CACF;;AAGF,UAAQ,IAAI,OAAO,MAAM;GACxB;GACA;GACA;GACA,SAAS;GACT,CAAC;;AAGH,IAAG,gBAAgB,OAAO;EACzB,aAAa;EACb,yBAAyB,WAAW;GACnC,MAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,OAAI,MAAM,UAAU,EACnB,QAAO;IAAC;IAAQ;IAAU;IAAU,CAClC,QAAQ,MAAM,EAAE,WAAW,OAAO,CAAC,CACnC,KAAK,OAAO;IAAE,OAAO;IAAG,OAAO;IAAG,EAAE;AAEvC,OAAI,MAAM,OAAO,YAAY,MAAM,OAAO,WAAW;IACpD,MAAM,cAAc,MAAM,MAAM;AAChC,WAAO,MAAM,KAAK,QAAQ,MAAM,CAAC,CAC/B,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC,CACxC,KAAK,OAAO;KACZ,OAAO,GAAG,MAAM,GAAG,GAAG;KACtB,OAAO;KACP,EAAE;;AAEL,UAAO;;EAER,SAAS,OAAO,MAAM,QAAQ;GAC7B,MAAM,CAAC,KAAK,GAAG,QAAQ,KAAK,MAAM,CAAC,MAAM,MAAM;GAC/C,MAAM,OAAO,KAAK,KAAK,IAAI;AAE3B,WAAQ,OAAO,QAAf;IACC,KAAK,QAAQ;AACZ,SAAI,QAAQ,SAAS,GAAG;AACvB,UAAI,GAAG,OAAO,4BAA4B;AAC1C;;KAED,MAAM,QAAkB,EAAE;AAC1B,UAAK,MAAM,CAAC,OAAO,UAAU,QAAQ,SAAS,EAAE;MAC/C,MAAM,SAAS,MAAM,UAAU,YAAY;AAC3C,YAAM,KACL,GAAG,MAAM,IAAI,OAAO,MAAM,MAAM,WAAW,OAAO,QAClD;;AAEF,SAAI,GAAG,OAAO,MAAM,KAAK,KAAK,CAAC;AAC/B;;IAED,KAAK,UAAU;KACd,MAAM,SAAS,QAAQ,IAAI,KAAK;AAChC,SAAI,CAAC,QAAQ;AACZ,UAAI,GAAG,OAAO,mBAAmB,QAAQ,UAAU;AACnD;;AAED,SAAI,OAAO,SAAS;AACnB,UAAI,GAAG,OAAO,GAAG,KAAK,kBAAkB;AACxC;;AAED,YAAO,UAAU;KACjB,MAAM,SAAS,GAAG,gBAAgB;AAClC,QAAG,eAAe,CAAC,GAAG,QAAQ,GAAG,OAAO,WAAW,CAAC;AACpD,SAAI,GAAG,OAAO,WAAW,OAAO;AAChC;;IAED,KAAK,WAAW;KACf,MAAM,SAAS,QAAQ,IAAI,KAAK;AAChC,SAAI,CAAC,QAAQ;AACZ,UAAI,GAAG,OAAO,mBAAmB,QAAQ,UAAU;AACnD;;AAED,SAAI,CAAC,OAAO,SAAS;AACpB,UAAI,GAAG,OAAO,GAAG,KAAK,mBAAmB;AACzC;;AAED,YAAO,UAAU;KACjB,MAAM,WAAW,IAAI,IAAI,OAAO,WAAW;AAC3C,QAAG,eACF,GAAG,gBAAgB,CAAC,QAAQ,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CACnD;AACD,SAAI,GAAG,OAAO,YAAY,OAAO;AACjC;;IAED,QACC,KAAI,GAAG,OACN,uBAAuB,IAAI,kCAC3B,UACA;;;EAGJ,CAAC;AAEF,IAAG,GAAG,oBAAoB,YAAY;AACrC,OAAK,MAAM,UAAU,QAAQ,QAAQ,CACpC,OAAM,OAAO,OAAO,YAAY;GAEhC;;;;ACnKH,MAAM,kBAAkB,KAAK,QAAQ,IAAI,MAAO,OAAO,cAAc;AAGrE,eAA8B,OAAO,IAAkB;AAEtD,KAAI,WAAW,gBAAgB,CAC9B,KAAI;AACH,eAAa,OAAO;GAAC;GAAY;GAAQ;GAAS,EAAE;GACnD,UAAU;GACV,SAAS;GACT,OAAO;IAAC;IAAQ;IAAQ;IAAO;GAC/B,CAAC;SACK;AAMT,IAAG,GACF,sBACA,OAAO,UAAoC;AAC1C,SAAO,EACN,cACC,MAAM,eACN;;;;;;;;;;;;;;;;;gDAkBD;GAEF;;;;ACpCF,MAAM,iBAA+B;CACpC,SAAS;CACT,SAAS,EAAE;CACX,UAAU;CACV;AAED,SAAgB,kBAA0B;AAGzC,QAAO,KADN,QAAQ,IAAI,mBAAmB,KAAK,SAAS,EAAE,UAAU,EACzC,SAAS,cAAc;;AAGzC,SAAgB,qBAAmC;CAClD,MAAM,OAAO,iBAAiB;AAC9B,KAAI,CAAC,WAAW,KAAK,CAAE,QAAO,EAAE,GAAG,gBAAgB;AAEnD,KAAI;EACH,MAAM,MAAM,aAAa,MAAM,QAAQ;EACvC,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,SAAO;GACN,SAAS,OAAO,WAAW;GAC3B,SAAS,OAAO,WAAW,EAAE;GAC7B,UAAU,OAAO,YAAY;GAC7B;SACM;AACP,SAAO,EAAE,GAAG,gBAAgB;;;AAI9B,SAAgB,mBAAmB,QAA4B;CAC9D,MAAM,OAAO,iBAAiB;CAC9B,MAAM,MAAM,QAAQ,KAAK;AACzB,KAAI,CAAC,WAAW,IAAI,CACnB,WAAU,KAAK;EAAE,WAAW;EAAM,MAAM;EAAO,CAAC;CAGjD,MAAM,MAAM,GAAG,KAAK,OAAO,KAAK,KAAK;AACrC,eAAc,KAAK,KAAK,UAAU,QAAQ,MAAM,IAAK,GAAG,MAAM,EAC7D,MAAM,KACN,CAAC;AACF,YAAW,KAAK,KAAK;;AAGtB,SAAgB,eAAe,MAAc,QAAwB;AACpE,QAAO,GAAG,KAAK,GAAG;;AAGnB,SAAgB,iBACf,QACA,KACU;AACV,KAAI,OAAO,OAAO,QAAS,QAAO,OAAO,QAAQ;AACjD,QAAO,OAAO,aAAa;;;;AC5D5B,MAAa,uBAAuB;AAgDpC,SAAS,yBAAsD;CAC9D,MAAM,OAAO,KACZ,SAAS,EACT,WACA,WACA,yBACA;AACD,KAAI,CAAC,WAAW,KAAK,CAAE,QAAO;AAE9B,KAAI;AACH,SAAO,KAAK,MACX,aAAa,MAAM,QAAQ,CAC3B;SACM;AACP,SAAO;;;AAIT,SAAS,eACR,YAC+C;AAC/C,KAAI;EAEH,MAAM,EAAE,gBACP,iBAFe,aAAa,YAAY,QAAQ,CAEL;EAC5C,MAAM,cAAc,aAAa;AACjC,MAAI,CAAC,YAAa,QAAO;AAGzB,SAAO;GAAE,MADI,aAAa,QAAQ,SAAS,QAAQ,WAAW,CAAC;GAChD,aAAa,YAAY,MAAM;GAAE;SACzC;AACP,SAAO;;;AAIT,SAAS,qBACR,UACoC;CACpC,MAAM,gBAAgB,KAAK,UAAU,qBAAqB;AAC1D,KAAI,CAAC,WAAW,cAAc,CAAE,QAAO,KAAA;AAEvC,KAAI;AACH,SAAO,KAAK,MACX,aAAa,eAAe,QAAQ,CACpC;SACM;AACP;;;AAIF,SAAS,oBACR,KACA,SAMoB;AACpB,KAAI,CAAC,WAAW,IAAI,CAAE,QAAO,EAAE;CAE/B,MAAM,UAA6B,EAAE;CACrC,MAAM,SAAS,KAAK,KAAK,WAAW;AAIpC,MAFC,QAAQ,6BAA6B,SAEL,WAAW,OAAO,EAAE;EACpD,MAAM,SAAS,eAAe,OAAO;AACrC,MAAI,OACH,SAAQ,KAAK;GACZ,GAAG;GACH,WAAW;GACX,SAAS;GACT,QAAQ,QAAQ;GAChB,MAAM,QAAQ;GACd,QAAQ,QAAQ;GAChB,aACC,QAAQ,SAAS,YACd,qBAAqB,IAAI,GACzB,KAAA;GACJ,CAAC;AAEH,SAAO;;AAGR,KAAI;EACH,MAAM,UAAU,SAAS,cAAc,EAAE,KAAK,KAAK,CAAC;AACpD,OAAK,MAAM,SAAS,SAAS;GAC5B,MAAM,YAAY,QAAQ,KAAK,MAAM;GACrC,MAAM,SAAS,eAAe,UAAU;AACxC,OAAI,QAAQ;IACX,MAAM,WAAW,QAAQ,UAAU;AACnC,YAAQ,KAAK;KACZ,GAAG;KACH,WAAW;KACX,SAAS;KACT,QAAQ,QAAQ;KAChB,MAAM,QAAQ;KACd,QAAQ,QAAQ;KAChB,aACC,QAAQ,SAAS,YACd,qBAAqB,SAAS,GAC9B,KAAA;KACJ,CAAC;;;SAGG;AAIR,QAAO;;AAGR,SAAS,qBACR,QACoB;CACpB,MAAM,uBAAO,IAAI,KAAa;CAC9B,MAAM,UAA6B,EAAE;AAErC,MAAK,MAAM,SAAS,QAAQ;AAC3B,MAAI,KAAK,IAAI,MAAM,UAAU,CAAE;AAC/B,OAAK,IAAI,MAAM,UAAU;AACzB,UAAQ,KAAK,MAAM;;AAGpB,QAAO;;AAGR,SAAgB,sBAAyC;CACxD,MAAM,SAA4B,EAAE;AAEpC,MAAK,MAAM,SAAS,oBACnB,KAAK,SAAS,EAAE,WAAW,SAAS,EACpC;EACC,QAAQ;EACR,MAAM;EACN,CACD,CACA,QAAO,KAAK,MAAM;AAGnB,MAAK,MAAM,SAAS,oBACnB,KAAK,SAAS,EAAE,OAAO,SAAS,SAAS,EACzC;EACC,QAAQ;EACR,MAAM;EACN,2BAA2B;EAC3B,CACD,CACA,QAAO,KAAK,MAAM;AAGnB,QAAO,qBAAqB,OAAO;;AAGpC,SAAgB,yBAA4C;CAC3D,MAAM,SAA4B,EAAE;CACpC,MAAM,UAAU,wBAAwB;AACxC,KAAI,CAAC,SAAS,QAAS,QAAO;AAE9B,MAAK,MAAM,CAAC,WAAW,YAAY,OAAO,QACzC,QAAQ,QACR,EAAE;EACF,MAAM,QAAQ,QAAQ;AACtB,MAAI,CAAC,OAAO,eAAe,CAAC,WAAW,MAAM,YAAY,CACxD;EAED,MAAM,SAAS,UAAU;EACzB,MAAM,SAA4B;GACjC,UAAU;GACV,aAAa,MAAM;GACnB,SAAS,MAAM;GACf,cAAc,MAAM;GACpB;AAED,OAAK,MAAM,SAAS,oBACnB,KAAK,MAAM,aAAa,SAAS,EACjC;GACC;GACA,MAAM;GACN;GACA,CACD,CACA,QAAO,KAAK,MAAM;AAGnB,OAAK,MAAM,SAAS,oBACnB,KAAK,MAAM,aAAa,OAAO,SAAS,EACxC;GACC;GACA,MAAM;GACN;GACA,CACD,CACA,QAAO,KAAK,MAAM;EAGnB,MAAM,oBAAoB,KAAK,MAAM,aAAa,WAAW;AAC7D,MAAI,WAAW,kBAAkB,EAAE;GAClC,MAAM,SAAS,eAAe,kBAAkB;AAChD,OAAI,OACH,QAAO,KAAK;IACX,GAAG;IACH,WAAW;IACX,SAAS,MAAM;IACf;IACA,MAAM;IACN;IACA,CAAC;;;AAKL,QAAO,qBAAqB,OAAO;;;;AC1PpC,MAAM,0BAA0B;AAEhC,SAAS,yBAAiC;AACzC,QAAO,KAAK,SAAS,EAAE,OAAO,SAAS,SAAS;;AAGjD,SAAS,WAAW,MAAoB;AACvC,WAAU,MAAM;EAAE,WAAW;EAAM,MAAM;EAAO,CAAC;;AAGlD,SAAS,uBAAuB,KAAuB;CACtD,MAAM,QAAkB,EAAE;AAE1B,MAAK,MAAM,SAAS,YAAY,KAAK,EAAE,eAAe,MAAM,CAAC,EAAE;EAC9D,MAAM,YAAY,KAAK,KAAK,MAAM,KAAK;AACvC,MAAI,MAAM,SAAA,qBAA+B;AACzC,MAAI,MAAM,aAAa,EAAE;AACxB,SAAM,KAAK,GAAG,uBAAuB,UAAU,CAAC;AAChD;;AAED,MAAI,MAAM,QAAQ,CACjB,OAAM,KAAK,UAAU;;AAIvB,QAAO,MAAM,MAAM,GAAG,MAAM,EAAE,cAAc,EAAE,CAAC;;AAGhD,SAAS,eAAe,KAAqB;CAC5C,MAAM,OAAO,WAAW,SAAS;AACjC,MAAK,MAAM,QAAQ,uBAAuB,IAAI,EAAE;AAC/C,OAAK,OAAO,SAAS,KAAK,KAAK,CAAC;AAChC,OAAK,OAAO,KAAK;AACjB,OAAK,OAAO,aAAa,KAAK,CAAC;AAC/B,OAAK,OAAO,KAAK;;AAElB,QAAO,KAAK,OAAO,MAAM;;AAG1B,SAAS,cACR,UACoC;CACpC,MAAM,OAAO,KAAK,UAAU,qBAAqB;AACjD,KAAI,CAAC,WAAW,KAAK,CAAE,QAAO,KAAA;AAE9B,KAAI;AACH,SAAO,KAAK,MACX,aAAa,MAAM,QAAQ,CAC3B;SACM;AACP;;;AAIF,SAAS,eACR,UACA,UACO;AACP,eACC,KAAK,UAAU,qBAAqB,EACpC,KAAK,UAAU,UAAU,MAAM,IAAK,GAAG,MACvC,EAAE,MAAM,KAAO,CACf;;AAGF,SAAS,kBACR,YACA,UACO;CACP,MAAM,aAAa,QAAQ,SAAS;AACpC,YAAW,WAAW;CACtB,MAAM,UAAU,KACf,YACA,IAAI,QAAQ,SAAS,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,KAAK,KAAK,GACxD;AAED,QAAO,SAAS;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;AACjD,QAAO,YAAY,SAAS;EAC3B,WAAW;EACX,oBAAoB;EACpB,kBAAkB;EAClB,CAAC;AACF,QAAO,UAAU;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;AAClD,QAAO,SAAS,UAAU;EACzB,WAAW;EACX,oBAAoB;EACpB,kBAAkB;EAClB,CAAC;AACF,QAAO,SAAS;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;;AAQlD,SAAgB,sBACf,OACoB;AACpB,KAAI,MAAM,SAAS,WAClB,OAAM,IAAI,MAAM,SAAS,MAAM,KAAK,oBAAoB;CAGzD,MAAM,eAAe,wBAAwB;AAC7C,YAAW,aAAa;CAExB,MAAM,YAAY,KAAK,cAAc,MAAM,KAAK;AAEhD,KADiB,WAAW,UAAU,EACxB;AAEb,MAAI,CADkB,SAAS,UAAU,CACtB,aAAa,CAC/B,OAAM,IAAI,MAAM,GAAG,UAAU,gCAAgC;AAI9D,MAAI,CADsB,cAAc,UAAU,CAEjD,OAAM,IAAI,MACT,qDAAqD,YACrD;;AAIH,mBAAkB,MAAM,SAAS,UAAU;CAE3C,MAAM,gBAAgB,eAAe,MAAM,QAAQ;CACnD,MAAM,gBAAgB,eAAe,UAAU;CAC/C,MAAM,uBAAM,IAAI,MAAM,EAAC,aAAa;CACpC,MAAM,WAAkC;EACvC,SAAS;EACT,QAAQ,MAAM;EACd,qBAAqB,MAAM;EAC3B,mBAAmB,MAAM;EACzB,uBAAuB,MAAM,QAAQ;EACrC,kBAAkB,MAAM,QAAQ;EAChC,yBAAyB,MAAM,QAAQ;EACvC,aAAa;EACb,gBAAgB;EAChB;EACA;EACA;AAED,gBAAe,WAAW,SAAS;AACnC,QAAO;EACN,UAAU;EACV;EACA;;AASF,SAAgB,oBACf,OACkB;AAClB,KAAI,MAAM,SAAS,aAAa,CAAC,MAAM,YACtC,OAAM,IAAI,MACT,SAAS,MAAM,KAAK,+BACpB;CAGF,MAAM,WAAW,MAAM;AACvB,KAAI,CAAC,WAAW,SAAS,kBAAkB,CAC1C,OAAM,IAAI,MACT,qCAAqC,SAAS,oBAC9C;AAIF,KADqB,eAAe,MAAM,QAAQ,KAC7B,SAAS,cAC7B,OAAM,IAAI,MACT,oBAAoB,MAAM,KAAK,8BAA8B,MAAM,UACnE;CAGF,MAAM,gBAAgB,eAAe,SAAS,kBAAkB;AAChE,KAAI,kBAAkB,SAAS,cAC9B,QAAO;EACN,UAAU,MAAM;EAChB;EACA,SAAS;EACT;AAGF,mBAAkB,SAAS,mBAAmB,MAAM,QAAQ;CAC5D,MAAM,gBAAgB,eAAe,MAAM,QAAQ;CACnD,MAAM,UAAiC;EACtC,GAAG;EACH,iCAAgB,IAAI,MAAM,EAAC,aAAa;EACxC;EACA;EACA;AACD,gBAAe,MAAM,SAAS,QAAQ;AAEtC,QAAO;EACN,UAAU,MAAM;EAChB,UAAU;EACV,SAAS;EACT;;;;AChLF,SAAS,kBAAkB,OAAgC;AAC1D,QAAO,eAAe,MAAM,MAAM,MAAM,OAAO;;AAGhD,SAAS,2BACR,QACA,aACkB;CAClB,MAAM,YAAY,OAAO,MACvB,UAAU,kBAAkB,MAAM,KAAK,YACxC;AACD,KAAI,UAAW,QAAO;CAEtB,MAAM,UAAU,OAAO,QACrB,UAAU,MAAM,SAAS,YAC1B;AACD,KAAI,QAAQ,WAAW,EACtB,QAAO,QAAQ;AAEhB,KAAI,QAAQ,SAAS,EACpB,OAAM,IAAI,MACT,yBAAyB,YAAY,6BACrC;AAGF,OAAM,IAAI,MAAM,kBAAkB,cAAc;;AAGjD,SAAgB,wBAAuC;CACtD,IAAI,SAAuB,oBAAoB;CAC/C,IAAI,gBAA0C;CAC9C,IAAI,mBAA6C;CAEjD,SAAS,cAAiC;AACzC,MAAI,CAAC,cACJ,iBAAgB,qBAAqB;AAEtC,SAAO;;CAGR,SAAS,iBAAoC;AAC5C,MAAI,CAAC,iBACJ,oBAAmB,wBAAwB;AAE5C,SAAO;;CAGR,SAAS,WAAW,OAAsC;EACzD,MAAM,MAAM,kBAAkB,MAAM;AACpC,SAAO;GACN,GAAG;GACH;GACA,SACC,MAAM,SAAS,YACZ,iBAAiB,QAAQ,IAAI,GAC7B;GACJ;;CAGF,SAAS,6BAA6C;AACrD,SAAO,aAAa,CAClB,QAAQ,UACR,iBAAiB,QAAQ,kBAAkB,MAAM,CAAC,CAClD,CACA,IAAI,WAAW;;AAGlB,QAAO;EACN,WAA2B;AAC1B,UAAO,aAAa,CAAC,IAAI,WAAW;;EAGrC,sBAAsC;AACrC,UAAO,gBAAgB,CAAC,IAAI,WAAW;;EAGxC,oBAAoB,MAAc,UAA2B;GAC5D,MAAM,aAAa,aAAa;GAChC,MAAM,QAAQ,WAAW,MAAM,MAAM,EAAE,cAAc,SAAS;AAC9D,OAAI,MACH,QAAO,iBAAiB,QAAQ,kBAAkB,MAAM,CAAC;GAG1D,MAAM,UAAU,WAAW,MAAM,MAAM,EAAE,SAAS,KAAK;AACvD,OAAI,QACH,QAAO,iBAAiB,QAAQ,kBAAkB,QAAQ,CAAC;AAK5D,UAAO;;EAGR,0BAAoC;AACnC,UAAO,4BAA4B,CAAC,KAClC,UAAU,MAAM,QACjB;;EAGF,OAAO,KAAsB;AAC5B,UAAO,QAAQ,OAAO;AACtB,sBAAmB,OAAO;AAC1B,UAAO;;EAGR,QAAQ,KAAsB;AAC7B,UAAO,QAAQ,OAAO;AACtB,sBAAmB,OAAO;AAC1B,UAAO;;EAGR,OAAO,KAAsB;GAC5B,MAAM,UAAU,iBAAiB,QAAQ,IAAI;AAC7C,UAAO,QAAQ,OAAO,CAAC;AACvB,sBAAmB,OAAO;AAC1B,UAAO,CAAC;;EAGT,OAAO,OAA+B;GACrC,MAAM,IAAI,MAAM,aAAa;AAC7B,UAAO,KAAK,UAAU,CAAC,QACrB,MACA,EAAE,KAAK,aAAa,CAAC,SAAS,EAAE,IAChC,EAAE,YAAY,aAAa,CAAC,SAAS,EAAE,IACvC,EAAE,OAAO,aAAa,CAAC,SAAS,EAAE,CACnC;;EAGF,kBAAkB,OAA+B;GAChD,MAAM,IAAI,MAAM,aAAa;AAC7B,UAAO,KAAK,qBAAqB,CAAC,QAChC,MACA,EAAE,KAAK,aAAa,CAAC,SAAS,EAAE,IAChC,EAAE,YAAY,aAAa,CAAC,SAAS,EAAE,IACvC,EAAE,OAAO,aAAa,CAAC,SAAS,EAAE,CACnC;;EAGF,aAAa,QAA8C;AAC1D,UAAO,WAAW;AAClB,sBAAmB,OAAO;;EAG3B,aAAa,aAAqB;GACjC,MAAM,QAAQ,2BACb,gBAAgB,EAChB,YACA;GACD,MAAM,SAAS,sBAAsB,MAAM;GAC3C,MAAM,cAAc,eAAe,MAAM,MAAM,YAAY;AAC3D,UAAO,QAAQ,eAAe;AAC9B,sBAAmB,OAAO;AAC1B,QAAK,SAAS;AACd,UAAO;IACN,GAAG;IACH,KAAK;IACL;;EAGF,WAAW,aAAqB;GAC/B,MAAM,QAAQ,2BACb,aAAa,EACb,YACA;GACD,MAAM,SAAS,oBAAoB,MAAM;AACzC,QAAK,SAAS;AACd,UAAO;IACN,GAAG;IACH,KAAK,kBAAkB,MAAM;IAC7B;;EAGF,UAAgB;AACf,mBAAgB;AAChB,sBAAmB;AACnB,YAAS,oBAAoB;;EAE9B;;;;AChNF,MAAM,UAAU;AAChB,MAAM,WAAW;AACjB,MAAM,OAAO;AACb,MAAM,iBAAiB;AAEvB,SAAS,YAAY,QAAwC;AAC5D,QAAO,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM;EACjC,MAAM,UAAU,EAAE,KAAK,cAAc,EAAE,KAAK;AAC5C,MAAI,YAAY,EAAG,QAAO;EAC1B,MAAM,YAAY,EAAE,OAAO,cAAc,EAAE,OAAO;AAClD,MAAI,cAAc,EAAG,QAAO;AAC5B,SAAO,EAAE,IAAI,cAAc,EAAE,IAAI;GAChC;;AAGH,SAAS,6BACR,gBACA,OAC2B;CAC3B,MAAM,cAAc,eAAe,MACjC,cACA,UAAU,aAAa,WAAW,MAAM,WACvC,UAAU,YAAY,wBACtB,MAAM,aACN,UAAU,YAAY,sBAAsB,MAAM,SACpD;AACD,KAAI,YAAa,QAAO;AAExB,QAAO,eAAe,MACpB,cACA,UAAU,aAAa,WAAW,MAAM,UACxC,UAAU,SAAS,MAAM,KAC1B;;AAGF,SAAS,qBACR,gBACA,OAKC;CACD,MAAM,WAAW,6BAChB,gBACA,MACA;AACD,KAAI,UAAU,aAAa;EAC1B,MAAM,kBAAkB,QACvB,MAAM,QAAQ,WACd,SAAS,YAAY,oBACrB,MAAM,OAAO,YAAY,SAAS,YAAY,iBAC9C;EACD,MAAM,cAAc,QACnB,MAAM,QAAQ,gBACd,SAAS,YAAY,2BACrB,MAAM,OAAO,iBACZ,SAAS,YAAY,wBACtB;AAED,MAAI,mBAAmB,YACtB,QAAO;GACN,OAAO;GACP,QAAQ;GACR,QAAQ;GACR;AAGF,SAAO;GACN,OAAO;GACP,QAAQ,uBAAuB,SAAS;GACxC,QAAQ;GACR;;CAGF,MAAM,mBAAmB,eAAe,MACtC,cAAc,UAAU,SAAS,MAAM,KACxC;AACD,KAAI,iBACH,QAAO;EACN,OAAO;EACP,QAAQ,sBAAsB,iBAAiB;EAC/C,QAAQ;EACR;AAGF,QAAO;EACN,OAAO;EACP,QAAQ;EACR,QAAQ;EACR;;AAGF,SAAS,gBAAgB,OAAkC;CAC1D,MAAM,eAAe;EACpB,GAAG,MAAM,OAAO,KAAK,MAAM;EAC3B,MAAM;EACN,MAAM;EACN;AACD,KAAI,MAAM,aAAa,iBACtB,cAAa,KACZ,aAAa,MAAM,YAAY,mBAAmB,MAAM,YAAY,0BAA0B,MAAM,MAAM,YAAY,wBAAwB,MAAM,GAAG,GAAG,KAAK,KAC/J;AAGF,QAAO;EACN,IAAI,MAAM;EACV,OAAO,MAAM;EACb,aAAa,aAAa,KAAK,KAAK;EACpC,cAAc,MAAM,UAAU,UAAU;EACxC,QAAQ,CAAC,SAAS,SAAS;EAC3B;;AAGF,SAAS,2BACR,gBACA,OACc;CACd,MAAM,QAAQ,qBAAqB,gBAAgB,MAAM;CACzD,MAAM,eAAe;EACpB,GAAG,MAAM,OAAO,KAAK,MAAM;EAC3B,MAAM;EACN,MAAM;EACN;AACD,KAAI,MAAM,QAAQ,QACjB,cAAa,KACZ,WAAW,MAAM,OAAO,UAAU,MAAM,OAAO,eAAe,MAAM,MAAM,OAAO,aAAa,MAAM,GAAG,GAAG,KAAK,KAC/G;AAGF,KAAI,MAAM,WAAW,SACpB,QAAO;EACN,IAAI,MAAM;EACV,OAAO,MAAM;EACb,aAAa,aAAa,KAAK,KAAK;EACpC,cAAc;EACd,QAAQ,CAAC,SAAS,SAAS;EAC3B;AAGF,KAAI,MAAM,WAAW,QAAQ;AAC5B,eAAa,KAAK,gBAAgB;AAClC,SAAO;GACN,IAAI,MAAM;GACV,OAAO,MAAM;GACb,aAAa,aAAa,KAAK,KAAK;GACpC,cAAc;GACd,QAAQ,CAAC,KAAK;GACd;;AAGF,cAAa,KAAK,MAAM,OAAO;AAC/B,QAAO;EACN,IAAI,MAAM;EACV,OAAO,MAAM;EACb,aAAa,aAAa,KAAK,KAAK;EACpC,cAAc;EACd;;AAGF,SAAS,WACR,GACA,GACU;AACV,KAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAC9B,MAAK,MAAM,SAAS,EACnB,KAAI,CAAC,EAAE,IAAI,MAAM,CAAE,QAAO;AAE3B,QAAO;;AAIR,eAA8B,OAAO,IAAkB;CACtD,MAAM,MAAM,uBAAuB;CAEnC,MAAM,OAAO;EAAC;EAAU;EAAQ;EAAW;EAAW;AAEtD,IAAG,gBAAgB,UAAU;EAC5B,aAAa;EACb,yBAAyB,WAAW;GACnC,MAAM,QAAQ,OAAO,MAAM,CAAC,MAAM,MAAM;AACxC,OAAI,MAAM,UAAU,EACnB,QAAO,KACL,QAAQ,MAAM,EAAE,WAAW,MAAM,MAAM,GAAG,CAAC,CAC3C,KAAK,OAAO;IAAE,OAAO;IAAG,OAAO;IAAG,EAAE;AAGvC,OAAI,MAAM,OAAO,UAAU;IAC1B,MAAM,IAAI,MAAM,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC,aAAa;AAChD,WAAO,YAAY,IAAI,qBAAqB,CAAC,CAC3C,QACC,MACA,EAAE,IAAI,aAAa,CAAC,SAAS,EAAE,IAC/B,EAAE,KAAK,aAAa,CAAC,SAAS,EAAE,CACjC,CACA,MAAM,GAAG,GAAG,CACZ,KAAK,OAAO;KACZ,OAAO,GAAG,MAAM,GAAG,GAAG,EAAE;KACxB,OAAO,EAAE;KACT,EAAE;;AAGL,OAAI,MAAM,OAAO,QAAQ;IACxB,MAAM,IAAI,MAAM,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC,aAAa;AAChD,WAAO,YACN,IACE,UAAU,CACV,QAAQ,UAAU,QAAQ,MAAM,YAAY,CAAC,CAC/C,CACC,QACC,MACA,EAAE,IAAI,aAAa,CAAC,SAAS,EAAE,IAC/B,EAAE,KAAK,aAAa,CAAC,SAAS,EAAE,CACjC,CACA,MAAM,GAAG,GAAG,CACZ,KAAK,OAAO;KACZ,OAAO,GAAG,MAAM,GAAG,GAAG,EAAE;KACxB,OAAO,EAAE;KACT,EAAE;;AAGL,UAAO;;EAER,SAAS,OAAO,MAAM,QAAQ;GAC7B,MAAM,UAAU,KAAK,MAAM;AAE3B,OAAI,CAAC,WAAW,IAAI,OAAO;IAC1B,MAAM,aAAa,YAAY,IAAI,UAAU,CAAC;IAC9C,MAAM,aAAa,YAAY,IAAI,qBAAqB,CAAC;AACzD,QAAI,WAAW,WAAW,KAAK,WAAW,WAAW,GAAG;AACvD,SAAI,GAAG,OAAO,wCAAwC;AACtD;;IAGD,MAAM,kBAAkB,IAAI,IAC3B,WACE,QAAQ,UAAU,MAAM,QAAQ,CAChC,KAAK,UAAU,MAAM,IAAI,CAC3B;IACD,MAAM,kBAAkB,IAAI,IAAI,gBAAgB;IAChD,MAAM,iCAAiB,IAAI,KAAa;IACxC,IAAI,gBAA+B;IAEnC,MAAM,gBAAgB,WAAW,IAAI,gBAAgB;IACrD,MAAM,mBAAmB,WAAW,KAAK,UACxC,2BAA2B,YAAY,MAAM,CAC7C;IAED,MAAM,YAA2B,EAAE;AACnC,QAAI,cAAc,SAAS,GAAG;AAC7B,eAAU,KAAK;MACd,IAAI;MACJ,OAAO,eAAe,cAAc,OAAO;MAC3C,aAAa;MACb,cAAc;MACd,CAAC;AACF,eAAU,KAAK,GAAG,cAAc;;AAEjC,QAAI,iBAAiB,SAAS,GAAG;AAChC,eAAU,KAAK;MACd,IAAI;MACJ,OAAO,kBAAkB,iBAAiB,OAAO;MACjD,aAAa;MACb,cAAc;MACd,CAAC;AACF,eAAU,KAAK,GAAG,iBAAiB;;IAGpC,MAAM,eAAe,IAAI,IAAI,WAAW,KAAK,MAAM,EAAE,IAAI,CAAC;IAC1D,MAAM,iBAAiB,IAAI,IAC1B,WAAW,KAAK,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CACjC;AAED,UAAM,IAAI,GAAG,QAAQ,KAAK,OAAO,KAAK,SAAS;KAC9C,MAAM,OAAO,IAAI,aAChB,WACA,KAAK,IAAI,KAAK,IAAI,UAAU,SAAS,GAAG,EAAE,EAAE,GAAG,EAC/C;MACC,QAAQ,MAAM,GAAG,UAAU,IAAI;MAC/B,QAAQ,MAAM,aAAa;AAC1B,WAAI,KAAK,WAAW,KAAK,IAAI,KAAK,SAAS,KAAK,CAC/C,QAAO,MAAM,GAAG,OAAO,MAAM,KAAK,KAAK,CAAC;AAEzC,cAAO,WAAW,MAAM,GAAG,UAAU,KAAK,GAAG;;MAE9C,QAAQ,MAAM,aAAa;OAC1B,MAAM,QACL,SAAS,UACL,YACD,SAAS,OACP,YACD,SAAS,iBACP,YACA;OACP,MAAM,WAAW,MAAM,GAAG,OAAO,KAAK;AACtC,cAAO,WACJ,MAAM,KAAK,MAAM,GAAG,UAAU,SAAS,CAAC,GACxC;;MAEJ,cAAc,SAAS,MAAM,GAAG,SAAS,KAAK;MAC9C,OAAO,SAAS,MAAM,GAAG,OAAO,KAAK;MACrC,GACA,IAAI,cAAc;AAClB,UAAI,GAAG,WAAW,YAAY,CAAE;AAEhC,UAAI,aAAa,IAAI,GAAG,EAAE;AACzB,WAAI,cAAc,SAAS;AAC1B,wBAAgB,IAAI,GAAG;AACvB,YAAI,OAAO,GAAG;cACR;AACN,wBAAgB,OAAO,GAAG;AAC1B,YAAI,QAAQ,GAAG;;AAEhB;;MAGD,MAAM,eAAe,eAAe,IAAI,GAAG;AAC3C,UAAI,CAAC,aAAc;MAEnB,MAAM,QAAQ,qBACb,YACA,aACA;AAED,UAAI,MAAM,WAAW,UAAU;AAC9B,WAAI,cAAc,QACjB,gBAAe,IAAI,GAAG;WAEtB,gBAAe,OAAO,GAAG;AAE1B;;AAGD,UAAI,MAAM,WAAW,QAAQ;OAC5B,MAAM,iBAAiB,6BACtB,YACA,aACA;AACD,WAAI,CAAC,gBAAgB;AACpB,YAAI,GAAG,OACN,qBAAqB,aAAa,KAAK,iBACvC,UACA;AACD;;AAED,WAAI;AAEH,YADe,IAAI,WAAW,eAAe,IAAI,CACtC,SAAS;AACnB,yBAAgB,UAAU,aAAa,KAAK;AAC5C,cAAK,KAAA,EAAU;cAEf,KAAI,GAAG,OACN,GAAG,aAAa,KAAK,0BACrB,OACA;gBAEM,OAAO;AACf,YAAI,GAAG,OACN,iBAAiB,QACd,MAAM,UACN,OAAO,MAAM,EAChB,UACA;;;cAIE,KAAK,KAAA,EAAU,EACrB,EAAE,cAAc,MAAM,CACtB;KAED,MAAM,YAAY,IAAI,WAAW;AAEjC,eAAU,SAAS;MAClB,cAAc;OACb,MAAM,UAAU,gBAAgB;OAChC,MAAM,WAAW,WAAW,SAAS;OACrC,MAAM,SAAS,eAAe;OAC9B,MAAM,QAAQ,CACb,GAAG,QAAQ,WACX,GAAG,SAAS,WACZ;AACD,WAAI,WAAW,SAAS,EACvB,OAAM,KAAK,GAAG,WAAW,OAAO,aAAa;AAE9C,WAAI,SAAS,EACZ,OAAM,KAAK,GAAG,OAAO,oBAAoB;AAE1C,cAAO;QACN,MAAM,GAAG,UAAU,MAAM,KAAK,SAAS,CAAC;QACxC,MAAM,GAAG,SAAS,MAAM,KAAK,MAAM,CAAC;QACpC;QACA;;MAEF,kBAAkB;MAClB,CAAC;AAEF,eAAU,SAAS;MAClB,OAAO,OAAe;AACrB,cAAO,KAAK,OAAO,MAAM;;MAE1B,aAAa;AACZ,YAAK,YAAY;;MAElB,CAAC;AAEF,eAAU,SACT,IAAI,KACH,MAAM,GACL,OACA,6CACA,EACD,GACA,EACA,CACD;AAED,YAAO;MACN,OAAO,OAAe;AACrB,cAAO,UAAU,OAAO,MAAM;;MAE/B,aAAa;AACZ,iBAAU,YAAY;;MAEvB,YAAY,MAAc;AACzB,YAAK,YAAY,KAAK;AACtB,WAAI,eAAe;;MAEpB;MACA;AAEF,QAAI,eAAe,OAAO,GAAG;KAC5B,MAAM,iBAA2B,EAAE;AACnC,UAAK,MAAM,OAAO,eACjB,KAAI;AACH,UAAI,aAAa,IAAI;AACrB,qBAAe,KAAK,IAAI;cAChB,OAAO;AACf,UAAI,GAAG,OACN,iBAAiB,QACd,MAAM,UACN,OAAO,MAAM,EAChB,UACA;;AAGH,SAAI,eAAe,SAAS,EAC3B,iBAAgB,YAAY,eAAe,OAAO;;AAIpD,QAAI,eAAe;AAClB,SAAI,GAAG,OAAO,eAAe,OAAO;AACpC,WAAM,IAAI,QAAQ;AAClB;;AAGD,QAAI,CAAC,WAAW,iBAAiB,gBAAgB,EAAE;AAClD,SAAI,GAAG,OACN,wCACA,OACA;AACD,WAAM,IAAI,QAAQ;AAClB;;AAGD;;GAGD,MAAM,CAAC,KAAK,GAAG,SAAS,WAAW,QAAQ,MAAM,MAAM;GACvD,MAAM,MAAM,KAAK,KAAK,IAAI;AAE1B,WAAQ,KAAR;IACC,KAAK;AACJ,SAAI,CAAC,KAAK;AACT,UAAI,GAAG,OACN,oCACA,UACA;AACD;;AAED,SAAI;MACH,MAAM,SAAS,IAAI,aAAa,IAAI;AACpC,UAAI,GAAG,OACN,YAAY,IAAI,MAAM,OAAO,SAAS,iBACtC,OACA;AACD,YAAM,IAAI,QAAQ;AAClB;cACQ,OAAO;AACf,UAAI,GAAG,OACN,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EACtD,UACA;AACD;;IAGF,KAAK;AACJ,SAAI,CAAC,KAAK;AACT,UAAI,GAAG,OACN,kCACA,UACA;AACD;;AAED,SAAI;MACH,MAAM,SAAS,IAAI,WAAW,IAAI;AAClC,UAAI,GAAG,OACN,OAAO,UACJ,UAAU,IAAI,kBACd,GAAG,IAAI,0BACV,OACA;AACD,UAAI,OAAO,QACV,OAAM,IAAI,QAAQ;AAEnB;cACQ,OAAO;AACf,UAAI,GAAG,OACN,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EACtD,UACA;AACD;;IAGF,KAAK;AACJ,SAAI,SAAS;AACb,SAAI,GAAG,OACN,cAAc,IAAI,UAAU,CAAC,OAAO,mBAAmB,IAAI,qBAAqB,CAAC,OAAO,0BACxF;AACD;IAED,KAAK;AACJ,SAAI,QAAQ,iBAAiB,QAAQ,gBAAgB;AACpD,UAAI,GAAG,OACN,sDACA,UACA;AACD;;AAED,SAAI,aAAa,IAAI;AACrB,SAAI,GAAG,OAAO,mBAAmB,MAAM;AACvC;IAED,QACC,KAAI,GAAG,OACN,YAAY,IAAI,SAAS,KAAK,KAAK,KAAK,IACxC,UACA;;;EAGJ,CAAC;;;;ACtgBH,MAAM,8BAGF;CACEQ;CACGC;CACDC;CACP,iBAAiBC;CACRC;CACDC;CACR;AAED,SAAS,4BACR,SASmC;CACnC,MAAM,iCAAiB,IAAI,KAA0B;AACrD,KAAI,CAAC,QAAQ,IAAK,gBAAe,IAAI,MAAM;AAC3C,KAAI,CAAC,QAAQ,OAAQ,gBAAe,IAAI,SAAS;AACjD,KAAI,CAAC,QAAQ,MAAO,gBAAe,IAAI,QAAQ;AAC/C,KAAI,CAAC,QAAQ,cAAe,gBAAe,IAAI,gBAAgB;AAC/D,KAAI,CAAC,QAAQ,QAAS,gBAAe,IAAI,UAAU;AACnD,KAAI,CAAC,QAAQ,OAAQ,gBAAe,IAAI,SAAS;AACjD,QAAO;;AAGR,SAAS,iCACR,KACA,WACA,gBACmB;AACnB,QAAO,OAAO,OAAO;AAEpB,MAAI,CAAC,4BADU,gCAAgC,EACN,KAAK,eAAe,CAC5D;AAED,QAAM,UAAU,GAAG;;;AAIrB,SAAS,2BACR,sBACuD;CACvD,MAAM,gBAAgB,IAAI,IAAI,qBAAqB;AACnD,SAAQ,SAAS;EAChB,MAAM,UAAU,IAAI,IACnB,KAAK,WAAW,KAAK,cAAc,CAAC,UAAU,MAAM,UAAU,CAAC,CAC/D;EACD,MAAM,kBAAkB,qBACtB,KAAK,SAAS,QAAQ,IAAI,KAAK,CAAC,CAChC,QAEC,cAEA,QAAQ,UAAU,CACnB;EACF,MAAM,SAAS,KAAK,WAAW,QAC7B,cAAc,CAAC,cAAc,IAAI,UAAU,KAAK,CACjD;AACD,SAAO;GACN,GAAG;GACH,YAAY,CAAC,GAAG,iBAAiB,GAAG,OAAO;GAC3C;;;AAIH,eAAsB,aAAa,UAA6B,EAAE,EAAE;CACnE,MAAM,EACL,MAAM,QAAQ,KAAK,EACnB,aAAa,EAAE,EACf,oBAAoB,iBAAiB,EAAE,EACvC,MAAM,MACN,SAAS,MACT,QAAQ,MACR,gBAAgB,MAChB,UAAU,MACV,SAAS,MACT,UACG;CAEJ,MAAM,sBAAsB,WAAW,KAAK,MAAM,QAAQ,KAAK,EAAE,CAAC;CAClE,MAAM,iBAAiB,4BAA4B;EAClD;EACA;EACA;EACA;EACA;EACA;EACA,CAAC;CACF,MAAM,8BAAkD,CACvD,4BAA4B,EAAE,gBAAgB,CAAC,EAC/C,GAAG,mBAAmB,KAAK,cAC1B,iCACC,UAAU,KACV,4BAA4B,UAAU,MACtC,eACA,CACD,CACD;CACD,MAAM,uBAAuB,4BAA4B,KACvD,GAAG,UAAU,WAAW,QAAQ,EAAE,GACnC;CAED,MAAM,iBAAiB,OAAO,EAC7B,KAAK,aACL,gBACA,wBAKK;EACL,MAAM,mBAAmB,eACf;GACP,MAAM,KAAK,gBAAgB,OAAO,YAAY;AAC9C,MAAG,gBAAgB,MAAM;AACzB,UAAO;MACJ,GACH,KAAA;EAEH,MAAM,WAAW,MAAM,2BAA2B;GACjD,KAAK;GACL,GAAI,mBACD,EAAE,iBAAiB,kBAAkB,GACrC,EAAE;GACL,uBAAuB;IACtB,0BAA0B,CAAC,GAAG,oBAAoB;IAClD,oBAAoB,CACnB,GAAG,6BACH,GAAG,eACH;IACD,oBAAoB,2BACnB,qBACA;IACD,iBAAiB,SAAc;AAE9B,SACC,CAAC,4BAFa,gCAAgC,EAI7C,UACA,eACA,CAED,QAAO;KAGR,MAAM,iBAAiB,uBAAuB;AAC9C,YAAO;MACN,GAAG;MACH,QAAQ,KAAK,OAAO,QAAQ,UAC3B,eAAe,oBACd,MAAM,MACN,MAAM,SACN,CACD;MACD;;IAEF;GACD,CAAC;AAEF,SAAO;GACN,GAAI,MAAM,+BAA+B;IACxC;IACA;IACmB;IACnB,CAAC;GACF;GACA,aAAa,SAAS;GACtB;;AAGF,QAAO,0BAA0B,gBAAgB;EAChD;EACA,UAAU,aAAa;EACvB,gBAAgB,eAAe,OAAO,IAAI;EAC1C,CAAC"}
|