my-pi 0.1.22 → 0.1.24

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.
@@ -1906,6 +1906,7 @@ const BUILTIN_EXTENSION_FACTORIES = {
1906
1906
  };
1907
1907
  const PACKAGE_THEME_DIR = resolve(dirname(createRequire(import.meta.url).resolve("@spences10/pi-themes/package.json")), "themes");
1908
1908
  const PI_AGENT_DIR_ENV = "PI_CODING_AGENT_DIR";
1909
+ const MY_PI_RUNTIME_MODE_ENV = "MY_PI_RUNTIME_MODE";
1909
1910
  const UNTRUSTED_CHILD_ENV_DEFAULTS = {
1910
1911
  MY_PI_CHILD_ENV_ALLOWLIST: "",
1911
1912
  MY_PI_MCP_ENV_ALLOWLIST: "",
@@ -2006,6 +2007,7 @@ async function create_my_pi(options = {}) {
2006
2007
  if (untrusted_repo) apply_untrusted_repo_defaults();
2007
2008
  const effective_agent_dir = resolve_agent_dir(cwd, agent_dir);
2008
2009
  if (agent_dir) process.env[PI_AGENT_DIR_ENV] = effective_agent_dir;
2010
+ process.env[MY_PI_RUNTIME_MODE_ENV] = runtime_mode;
2009
2011
  const resolved_extensions = extensions.map((p) => resolve(cwd, p));
2010
2012
  const force_disabled = get_force_disabled_builtins({
2011
2013
  runtime_mode,
@@ -2082,4 +2084,4 @@ async function create_my_pi(options = {}) {
2082
2084
  //#endregion
2083
2085
  export { is_project_local_skill_path as a, runRpcMode$1 as c, get_force_disabled_builtins as i, apply_untrusted_repo_defaults as n, resolve_model_reference as o, create_my_pi as r, runPrintMode$1 as s, InteractiveMode$1 as t };
2084
2086
 
2085
- //# sourceMappingURL=api-ByzD9jne.js.map
2087
+ //# sourceMappingURL=api-CJN_JYzx.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-ByzD9jne.js","names":["create_child_process_env","create_shared_child_process_env","HOOKS_CONFIG_ENV","create_child_process_env","ENABLED","DISABLED","sets_equal","prompt_presets_extension","session_name_extension","hooks_resolution_extension"],"sources":["../src/extensions/hooks-resolution/env.ts","../src/extensions/hooks-resolution/trust.ts","../src/extensions/hooks-resolution/index.ts","../src/extensions/manager/config.ts","../src/extensions/manager/index.ts","../src/extensions/prompt-presets/index.ts","../src/extensions/session-name/index.ts","../src/api.ts"],"sourcesContent":["import { create_child_process_env as create_shared_child_process_env } from '@spences10/pi-child-env';\n\nexport function create_child_process_env(\n\texplicit_env: Record<string, string> = {},\n\tsource_env: NodeJS.ProcessEnv = process.env,\n): NodeJS.ProcessEnv {\n\treturn create_shared_child_process_env({\n\t\tprofile: 'hooks',\n\t\texplicit_env,\n\t\tsource_env,\n\t});\n}\n","import {\n\tis_project_subject_trusted,\n\tread_project_trust_store,\n\ttrust_project_subject,\n\ttype ProjectTrustSubject,\n} from '@spences10/pi-project-trust';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nconst HOOKS_CONFIG_ENV = 'MY_PI_HOOKS_CONFIG';\n\nexport function default_hooks_trust_store_path(): string {\n\treturn join(homedir(), '.pi', 'agent', 'trusted-hooks.json');\n}\n\nexport function create_hooks_config_trust_subject(\n\tproject_dir: string,\n\thash: string,\n): ProjectTrustSubject {\n\treturn {\n\t\tkind: 'hooks-config',\n\t\tid: project_dir,\n\t\tstore_key: project_dir,\n\t\thash,\n\t\tenv_key: HOOKS_CONFIG_ENV,\n\t\tprompt_title:\n\t\t\t'Project hook config can execute shell commands after tool use. Trust these hooks?',\n\t};\n}\n\nexport function is_hooks_config_trusted(\n\tproject_dir: string,\n\thash: string,\n\ttrust_store_path = default_hooks_trust_store_path(),\n): boolean {\n\tconst subject = create_hooks_config_trust_subject(\n\t\tproject_dir,\n\t\thash,\n\t);\n\tif (is_project_subject_trusted(subject, trust_store_path))\n\t\treturn true;\n\n\tconst legacy_entry = read_project_trust_store(trust_store_path)[\n\t\tproject_dir\n\t] as { project_dir?: unknown; hash?: unknown } | undefined;\n\treturn (\n\t\tlegacy_entry?.project_dir === project_dir &&\n\t\tlegacy_entry.hash === hash\n\t);\n}\n\nexport function trust_hooks_config(\n\tproject_dir: string,\n\thash: string,\n\ttrust_store_path = default_hooks_trust_store_path(),\n): void {\n\ttrust_project_subject(\n\t\tcreate_hooks_config_trust_subject(project_dir, hash),\n\t\ttrust_store_path,\n\t);\n}\n","// Hooks resolution — Claude Code style hook compatibility\n\nimport type {\n\tExtensionAPI,\n\tExtensionContext,\n\tExtensionFactory,\n\tToolResultEvent,\n} from '@mariozechner/pi-coding-agent';\nimport {\n\tresolve_project_trust,\n\ttype ProjectTrustSubject,\n} from '@spences10/pi-project-trust';\nimport { spawn } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport { create_child_process_env } from './env.js';\nimport {\n\tdefault_hooks_trust_store_path,\n\tis_hooks_config_trusted,\n} from './trust.js';\n\nconst HOOK_TIMEOUT_MS = 10 * 60 * 1000;\nconst HOOKS_CONFIG_ENV = 'MY_PI_HOOKS_CONFIG';\n\ntype JsonValue =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| JsonValue[]\n\t| { [key: string]: JsonValue };\n\nexport type HookEventName = 'PostToolUse' | 'PostToolUseFailure';\n\nexport interface ResolvedCommandHook {\n\tevent_name: HookEventName;\n\tmatcher?: RegExp;\n\tmatcher_text?: string;\n\tcommand: string;\n\tsource: string;\n}\n\nexport interface HookState {\n\tproject_dir: string;\n\thooks: ResolvedCommandHook[];\n}\n\nexport interface HooksConfigInfo {\n\tproject_dir: string;\n\thash: string;\n\tsources: string[];\n\thooks: Array<{\n\t\tevent_name: HookEventName;\n\t\tmatcher_text?: string;\n\t\tcommand: string;\n\t\tsource: string;\n\t}>;\n}\n\nexport interface CommandRunResult {\n\tcode: number;\n\tstdout: string;\n\tstderr: string;\n\telapsed_ms: number;\n\ttimed_out: boolean;\n}\n\nexport function is_file(path: string): boolean {\n\ttry {\n\t\treturn statSync(path).isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport function as_record(\n\tvalue: unknown,\n): Record<string, unknown> | undefined {\n\tif (typeof value !== 'object' || value === null) return undefined;\n\treturn value as Record<string, unknown>;\n}\n\nexport function walk_up_directories(\n\tstart_dir: string,\n\tstop_dir?: string,\n): string[] {\n\tconst directories: string[] = [];\n\tconst has_stop_dir = stop_dir !== undefined;\n\tlet current = resolve(start_dir);\n\tlet parent = dirname(current);\n\tlet reached_stop_dir = has_stop_dir && current === stop_dir;\n\tlet reached_filesystem_root = parent === current;\n\n\tdirectories.push(current);\n\twhile (!reached_stop_dir && !reached_filesystem_root) {\n\t\tcurrent = parent;\n\t\tparent = dirname(current);\n\t\treached_stop_dir = has_stop_dir && current === stop_dir;\n\t\treached_filesystem_root = parent === current;\n\t\tdirectories.push(current);\n\t}\n\n\treturn directories;\n}\n\nexport function find_nearest_git_root(\n\tstart_dir: string,\n): string | undefined {\n\tfor (const directory of walk_up_directories(start_dir)) {\n\t\tif (existsSync(join(directory, '.git'))) {\n\t\t\treturn directory;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport function has_hooks_config(directory: string): boolean {\n\treturn (\n\t\tis_file(join(directory, '.claude', 'settings.json')) ||\n\t\tis_file(join(directory, '.rulesync', 'hooks.json')) ||\n\t\tis_file(join(directory, '.pi', 'hooks.json'))\n\t);\n}\n\nexport function find_project_dir(cwd: string): string {\n\tconst git_root = find_nearest_git_root(cwd);\n\tfor (const directory of walk_up_directories(cwd, git_root)) {\n\t\tif (has_hooks_config(directory)) {\n\t\t\treturn directory;\n\t\t}\n\t}\n\treturn git_root ?? resolve(cwd);\n}\n\nexport function read_json_file(path: string): JsonValue | undefined {\n\tif (!is_file(path)) return undefined;\n\ttry {\n\t\treturn JSON.parse(readFileSync(path, 'utf8')) as JsonValue;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function resolve_hook_command(\n\tcommand: string,\n\tproject_dir: string,\n): string {\n\treturn command.replace(/\\$CLAUDE_PROJECT_DIR\\b/g, project_dir);\n}\n\nexport function compile_matcher(\n\tmatcher_text: string | undefined,\n): RegExp | undefined {\n\tif (matcher_text === undefined) return undefined;\n\ttry {\n\t\treturn new RegExp(matcher_text);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function create_hook(\n\tevent_name: HookEventName,\n\tmatcher_text: string | undefined,\n\tcommand: string,\n\tsource: string,\n\tproject_dir: string,\n): ResolvedCommandHook | undefined {\n\tconst matcher = compile_matcher(matcher_text);\n\tif (matcher_text !== undefined && matcher === undefined)\n\t\treturn undefined;\n\treturn {\n\t\tevent_name,\n\t\tmatcher,\n\t\tmatcher_text,\n\t\tcommand: resolve_hook_command(command, project_dir),\n\t\tsource,\n\t};\n}\n\nexport function get_hook_entries(\n\thooks_record: Record<string, unknown>,\n\tevent_name: HookEventName,\n): unknown[] {\n\tconst keys =\n\t\tevent_name === 'PostToolUse'\n\t\t\t? ['PostToolUse', 'postToolUse']\n\t\t\t: ['PostToolUseFailure', 'postToolUseFailure'];\n\n\tfor (const key of keys) {\n\t\tconst value = hooks_record[key];\n\t\tif (Array.isArray(value)) return value;\n\t}\n\treturn [];\n}\n\nexport function parse_claude_settings_hooks(\n\tconfig: unknown,\n\tsource: string,\n\tproject_dir: string,\n): ResolvedCommandHook[] {\n\tconst root = as_record(config);\n\tconst hooks_root = root ? as_record(root.hooks) : undefined;\n\tif (!hooks_root) return [];\n\n\tconst hooks: ResolvedCommandHook[] = [];\n\tconst events: HookEventName[] = [\n\t\t'PostToolUse',\n\t\t'PostToolUseFailure',\n\t];\n\n\tfor (const event_name of events) {\n\t\tconst entries = get_hook_entries(hooks_root, event_name);\n\t\tfor (const entry of entries) {\n\t\t\tconst entry_record = as_record(entry);\n\t\t\tif (!entry_record || !Array.isArray(entry_record.hooks))\n\t\t\t\tcontinue;\n\n\t\t\tconst matcher_text =\n\t\t\t\ttypeof entry_record.matcher === 'string'\n\t\t\t\t\t? entry_record.matcher\n\t\t\t\t\t: undefined;\n\t\t\tfor (const nested_hook of entry_record.hooks) {\n\t\t\t\tconst nested_record = as_record(nested_hook);\n\t\t\t\tif (!nested_record) continue;\n\t\t\t\tif (nested_record.type !== 'command') continue;\n\t\t\t\tif (typeof nested_record.command !== 'string') continue;\n\n\t\t\t\tconst hook = create_hook(\n\t\t\t\t\tevent_name,\n\t\t\t\t\tmatcher_text,\n\t\t\t\t\tnested_record.command,\n\t\t\t\t\tsource,\n\t\t\t\t\tproject_dir,\n\t\t\t\t);\n\t\t\t\tif (hook) hooks.push(hook);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn hooks;\n}\n\nexport function parse_simple_hooks_file(\n\tconfig: unknown,\n\tsource: string,\n\tproject_dir: string,\n): ResolvedCommandHook[] {\n\tconst root = as_record(config);\n\tconst hooks_root = root ? as_record(root.hooks) : undefined;\n\tif (!hooks_root) return [];\n\n\tconst hooks: ResolvedCommandHook[] = [];\n\tconst events: HookEventName[] = [\n\t\t'PostToolUse',\n\t\t'PostToolUseFailure',\n\t];\n\n\tfor (const event_name of events) {\n\t\tconst entries = get_hook_entries(hooks_root, event_name);\n\t\tfor (const entry of entries) {\n\t\t\tconst entry_record = as_record(entry);\n\t\t\tif (!entry_record || typeof entry_record.command !== 'string') {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst matcher_text =\n\t\t\t\ttypeof entry_record.matcher === 'string'\n\t\t\t\t\t? entry_record.matcher\n\t\t\t\t\t: undefined;\n\t\t\tconst hook = create_hook(\n\t\t\t\tevent_name,\n\t\t\t\tmatcher_text,\n\t\t\t\tentry_record.command,\n\t\t\t\tsource,\n\t\t\t\tproject_dir,\n\t\t\t);\n\t\t\tif (hook) hooks.push(hook);\n\t\t}\n\t}\n\n\treturn hooks;\n}\n\nfunction hook_config_paths(project_dir: string): string[] {\n\treturn [\n\t\tjoin(project_dir, '.claude', 'settings.json'),\n\t\tjoin(project_dir, '.rulesync', 'hooks.json'),\n\t\tjoin(project_dir, '.pi', 'hooks.json'),\n\t];\n}\n\nfunction parse_hooks_config_file(\n\tpath: string,\n\tproject_dir: string,\n): ResolvedCommandHook[] {\n\tconst config = read_json_file(path);\n\tif (config === undefined) return [];\n\tif (path.endsWith(join('.claude', 'settings.json'))) {\n\t\treturn parse_claude_settings_hooks(config, path, project_dir);\n\t}\n\treturn parse_simple_hooks_file(config, path, project_dir);\n}\n\nexport function load_hooks(cwd: string): HookState {\n\tconst project_dir = find_project_dir(cwd);\n\tconst hooks = hook_config_paths(project_dir).flatMap((path) =>\n\t\tparse_hooks_config_file(path, project_dir),\n\t);\n\n\treturn { project_dir, hooks };\n}\n\nexport function get_hooks_config_info(\n\tcwd: string,\n): HooksConfigInfo | undefined {\n\tconst project_dir = find_project_dir(cwd);\n\tconst sources = hook_config_paths(project_dir).filter(is_file);\n\tif (sources.length === 0) return undefined;\n\n\tconst hash = createHash('sha256');\n\tfor (const source of sources) {\n\t\thash.update(source);\n\t\thash.update('\\0');\n\t\thash.update(readFileSync(source, 'utf8'));\n\t\thash.update('\\0');\n\t}\n\n\tconst hooks = sources\n\t\t.flatMap((source) => parse_hooks_config_file(source, project_dir))\n\t\t.map((hook) => ({\n\t\t\tevent_name: hook.event_name,\n\t\t\tmatcher_text: hook.matcher_text,\n\t\t\tcommand: hook.command,\n\t\t\tsource: hook.source,\n\t\t}));\n\n\treturn {\n\t\tproject_dir,\n\t\thash: hash.digest('hex'),\n\t\tsources,\n\t\thooks,\n\t};\n}\n\nexport function to_claude_tool_name(tool_name: string): string {\n\tif (tool_name === 'ls') return 'LS';\n\tif (tool_name.length === 0) return tool_name;\n\treturn tool_name[0].toUpperCase() + tool_name.slice(1);\n}\n\nexport function matches_hook(\n\thook: ResolvedCommandHook,\n\ttool_name: string,\n): boolean {\n\tif (!hook.matcher) return true;\n\n\tconst claude_tool_name = to_claude_tool_name(tool_name);\n\thook.matcher.lastIndex = 0;\n\tif (hook.matcher.test(tool_name)) return true;\n\n\thook.matcher.lastIndex = 0;\n\treturn hook.matcher.test(claude_tool_name);\n}\n\nexport function extract_text_content(content: unknown): string {\n\tif (!Array.isArray(content)) return '';\n\n\tconst parts: string[] = [];\n\tfor (const item of content) {\n\t\tif (!item || typeof item !== 'object') continue;\n\t\tconst item_record = item as Record<string, unknown>;\n\t\tif (\n\t\t\titem_record.type === 'text' &&\n\t\t\ttypeof item_record.text === 'string'\n\t\t) {\n\t\t\tparts.push(item_record.text);\n\t\t}\n\t}\n\n\treturn parts.join('\\n');\n}\n\nexport function normalize_tool_input(\n\tinput: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst normalized: Record<string, unknown> = { ...input };\n\tconst path_value =\n\t\ttypeof input.path === 'string' ? input.path : undefined;\n\tif (path_value !== undefined) {\n\t\tnormalized.file_path = path_value;\n\t\tnormalized.filePath = path_value;\n\t}\n\treturn normalized;\n}\n\nexport function build_tool_response(\n\tevent: ToolResultEvent,\n\tnormalized_input: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst response: Record<string, unknown> = {\n\t\tis_error: event.isError,\n\t\tisError: event.isError,\n\t\tcontent: event.content,\n\t\ttext: extract_text_content(event.content),\n\t\tdetails: event.details ?? null,\n\t};\n\n\tconst file_path =\n\t\ttypeof normalized_input.file_path === 'string'\n\t\t\t? normalized_input.file_path\n\t\t\t: undefined;\n\tif (file_path !== undefined) {\n\t\tresponse.file_path = file_path;\n\t\tresponse.filePath = file_path;\n\t}\n\n\treturn response;\n}\n\nexport function build_hook_payload(\n\tevent: ToolResultEvent,\n\tevent_name: HookEventName,\n\tctx: ExtensionContext,\n\tproject_dir: string,\n): Record<string, unknown> {\n\tconst normalized_input = normalize_tool_input(\n\t\tevent.input as Record<string, unknown>,\n\t);\n\tconst session_id =\n\t\tctx.sessionManager.getSessionFile() ?? 'ephemeral';\n\n\treturn {\n\t\tsession_id,\n\t\tcwd: ctx.cwd,\n\t\tclaude_project_dir: project_dir,\n\t\thook_event_name: event_name,\n\t\ttool_name: to_claude_tool_name(event.toolName),\n\t\ttool_call_id: event.toolCallId,\n\t\ttool_input: normalized_input,\n\t\ttool_response: build_tool_response(event, normalized_input),\n\t};\n}\n\nexport async function run_command_hook(\n\tcommand: string,\n\tcwd: string,\n\tpayload: Record<string, unknown>,\n): Promise<CommandRunResult> {\n\treturn await new Promise((resolve) => {\n\t\tconst started_at = Date.now();\n\t\tconst child = spawn('bash', ['-lc', command], {\n\t\t\tcwd,\n\t\t\tenv: create_child_process_env({ CLAUDE_PROJECT_DIR: cwd }),\n\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t});\n\n\t\tlet stdout = '';\n\t\tlet stderr = '';\n\t\tlet timed_out = false;\n\t\tlet resolved = false;\n\n\t\tconst finish = (code: number) => {\n\t\t\tif (resolved) return;\n\t\t\tresolved = true;\n\t\t\tresolve({\n\t\t\t\tcode,\n\t\t\t\tstdout,\n\t\t\t\tstderr,\n\t\t\t\telapsed_ms: Date.now() - started_at,\n\t\t\t\ttimed_out,\n\t\t\t});\n\t\t};\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\ttimed_out = true;\n\t\t\tchild.kill('SIGTERM');\n\t\t\tconst kill_timer = setTimeout(() => {\n\t\t\t\tchild.kill('SIGKILL');\n\t\t\t}, 1000);\n\t\t\t(\n\t\t\t\tkill_timer as NodeJS.Timeout & { unref?: () => void }\n\t\t\t).unref?.();\n\t\t}, HOOK_TIMEOUT_MS);\n\t\t(timeout as NodeJS.Timeout & { unref?: () => void }).unref?.();\n\n\t\tchild.stdout.on('data', (chunk: Buffer) => {\n\t\t\tstdout += chunk.toString('utf8');\n\t\t});\n\t\tchild.stderr.on('data', (chunk: Buffer) => {\n\t\t\tstderr += chunk.toString('utf8');\n\t\t});\n\n\t\tchild.on('error', (error) => {\n\t\t\tclearTimeout(timeout);\n\t\t\tstderr += `${error.message}\\n`;\n\t\t\tfinish(-1);\n\t\t});\n\n\t\tchild.on('close', (code) => {\n\t\t\tclearTimeout(timeout);\n\t\t\tfinish(code ?? -1);\n\t\t});\n\n\t\ttry {\n\t\t\tchild.stdin.write(JSON.stringify(payload));\n\t\t\tchild.stdin.end();\n\t\t} catch (error) {\n\t\t\tstderr += `${error instanceof Error ? error.message : String(error)}\\n`;\n\t\t}\n\t});\n}\n\nexport function hook_event_name_for_result(\n\tevent: ToolResultEvent,\n): HookEventName {\n\treturn event.isError ? 'PostToolUseFailure' : 'PostToolUse';\n}\n\nexport function format_duration(elapsed_ms: number): string {\n\tif (elapsed_ms < 1000) return `${elapsed_ms}ms`;\n\treturn `${(elapsed_ms / 1000).toFixed(1)}s`;\n}\n\nexport function hook_name(command: string): string {\n\tconst sh_path_match = command.match(/[^\\s|;&]+\\.sh\\b/);\n\tif (sh_path_match) return basename(sh_path_match[0]);\n\tconst first_token = command.trim().split(/\\s+/)[0] ?? 'hook';\n\treturn basename(first_token);\n}\n\nfunction create_hooks_trust_subject(\n\tinfo: HooksConfigInfo,\n): ProjectTrustSubject {\n\tconst source_lines = info.sources.map((source) => `- ${source}`);\n\tconst hook_lines =\n\t\tinfo.hooks.length === 0\n\t\t\t? ['- no valid command hooks detected']\n\t\t\t: info.hooks.map((hook) => {\n\t\t\t\t\tconst matcher = hook.matcher_text\n\t\t\t\t\t\t? ` matcher=${hook.matcher_text}`\n\t\t\t\t\t\t: '';\n\t\t\t\t\treturn `- ${hook.event_name}${matcher}: ${hook.command}`;\n\t\t\t\t});\n\treturn {\n\t\tkind: 'hooks-config',\n\t\tid: info.project_dir,\n\t\tstore_key: info.project_dir,\n\t\thash: info.hash,\n\t\tenv_key: HOOKS_CONFIG_ENV,\n\t\tprompt_title:\n\t\t\t'Project hook config can execute shell commands after tool use. Trust these hooks?',\n\t\tsummary_lines: [\n\t\t\t'Sources:',\n\t\t\t...source_lines,\n\t\t\t'Commands:',\n\t\t\t...hook_lines,\n\t\t],\n\t\tchoices: {\n\t\t\tallow_once: 'Allow once for this session',\n\t\t\ttrust: 'Trust this repo until hook config changes',\n\t\t\tskip: 'Skip project hooks',\n\t\t},\n\t\theadless_warning: `Skipping untrusted hook config in ${info.project_dir}. Set ${HOOKS_CONFIG_ENV}=allow to enable hooks for this run.`,\n\t};\n}\n\nasync function should_load_hooks_config(\n\tcwd: string,\n\tctx?: ExtensionContext,\n): Promise<boolean> {\n\tconst info = get_hooks_config_info(cwd);\n\tif (!info) return true;\n\tif (is_hooks_config_trusted(info.project_dir, info.hash))\n\t\treturn true;\n\n\tconst decision = await resolve_project_trust(\n\t\tcreate_hooks_trust_subject(info),\n\t\t{\n\t\t\thas_ui: ctx?.hasUI,\n\t\t\tselect: ctx?.hasUI\n\t\t\t\t? async (\n\t\t\t\t\t\tmessage: string,\n\t\t\t\t\t\tchoices: string[],\n\t\t\t\t\t): Promise<string> => {\n\t\t\t\t\t\tconst selected = await ctx.ui.select(message, choices);\n\t\t\t\t\t\treturn selected ?? '';\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\tenv: process.env,\n\t\t\ttrust_store_path: default_hooks_trust_store_path(),\n\t\t},\n\t);\n\treturn (\n\t\tdecision.action === 'allow-once' ||\n\t\tdecision.action === 'trust-persisted'\n\t);\n}\n\nexport interface HooksResolutionOptions {\n\tload_hooks?: (cwd: string) => HookState;\n\trun_command_hook?: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\tpayload: Record<string, unknown>,\n\t) => Promise<CommandRunResult>;\n}\n\nexport function create_hooks_resolution_extension(\n\toptions: HooksResolutionOptions = {},\n): ExtensionFactory {\n\tconst load_hooks_impl = options.load_hooks ?? load_hooks;\n\tconst run_command_hook_impl =\n\t\toptions.run_command_hook ?? run_command_hook;\n\n\treturn async function hooks_resolution(pi: ExtensionAPI) {\n\t\tlet state: HookState = {\n\t\t\tproject_dir: process.cwd(),\n\t\t\thooks: [],\n\t\t};\n\n\t\tconst refresh_hooks = async (\n\t\t\tcwd: string,\n\t\t\tctx?: ExtensionContext,\n\t\t) => {\n\t\t\tif (!(await should_load_hooks_config(cwd, ctx))) {\n\t\t\t\tstate = { project_dir: cwd, hooks: [] };\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstate = load_hooks_impl(cwd);\n\t\t};\n\n\t\tpi.on('session_start', async (_event, ctx) => {\n\t\t\tawait refresh_hooks(ctx.cwd, ctx);\n\t\t});\n\n\t\tpi.on('tool_result', async (event, ctx) => {\n\t\t\tif (state.hooks.length === 0) return;\n\n\t\t\tconst event_name = hook_event_name_for_result(event);\n\t\t\tconst matching_hooks = state.hooks.filter(\n\t\t\t\t(hook) =>\n\t\t\t\t\thook.event_name === event_name &&\n\t\t\t\t\tmatches_hook(hook, event.toolName),\n\t\t\t);\n\t\t\tif (matching_hooks.length === 0) return;\n\n\t\t\tconst payload = build_hook_payload(\n\t\t\t\tevent,\n\t\t\t\tevent_name,\n\t\t\t\tctx,\n\t\t\t\tstate.project_dir,\n\t\t\t);\n\t\t\tconst executed_commands = new Set<string>();\n\n\t\t\tfor (const hook of matching_hooks) {\n\t\t\t\tif (executed_commands.has(hook.command)) continue;\n\t\t\t\texecuted_commands.add(hook.command);\n\n\t\t\t\tconst result = await run_command_hook_impl(\n\t\t\t\t\thook.command,\n\t\t\t\t\tstate.project_dir,\n\t\t\t\t\tpayload,\n\t\t\t\t);\n\t\t\t\tconst name = hook_name(hook.command);\n\t\t\t\tconst duration = format_duration(result.elapsed_ms);\n\n\t\t\t\tif (ctx.hasUI) {\n\t\t\t\t\tif (result.code === 0) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t`Hook \\`${name}\\` ran (${duration})`,\n\t\t\t\t\t\t\t'info',\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst error_line =\n\t\t\t\t\t\t\tresult.stderr.trim() ||\n\t\t\t\t\t\t\tresult.stdout.trim() ||\n\t\t\t\t\t\t\t`exit code ${result.code}`;\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t`Hook \\`${name}\\` failed (${duration}): ${error_line}`,\n\t\t\t\t\t\t\t'warning',\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\t};\n}\n\nexport default create_hooks_resolution_extension();\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| 'filter-output'\n\t| 'recall'\n\t| 'nopeek'\n\t| 'omnisearch'\n\t| 'sqlite-tools'\n\t| 'prompt-presets'\n\t| 'lsp'\n\t| 'session-name'\n\t| 'confirm-destructive'\n\t| 'hooks-resolution'\n\t| 'team-mode';\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: '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: 'recall',\n\t\tlabel: 'Recall',\n\t\tdescription: 'pirecall reminder and background session sync',\n\t\tcli_flag: '--no-recall',\n\t\taliases: ['recall', 'pirecall'],\n\t},\n\t{\n\t\tkey: 'nopeek',\n\t\tlabel: 'Nopeek',\n\t\tdescription:\n\t\t\t'nopeek reminder for secret-safe environment loading',\n\t\tcli_flag: '--no-nopeek',\n\t\taliases: ['nopeek', 'secrets', 'secret-loading'],\n\t},\n\t{\n\t\tkey: 'omnisearch',\n\t\tlabel: 'Omnisearch',\n\t\tdescription: 'mcp-omnisearch reminder for verified web research',\n\t\tcli_flag: '--no-omnisearch',\n\t\taliases: ['omnisearch', 'search', 'web-search', 'research'],\n\t},\n\t{\n\t\tkey: 'sqlite-tools',\n\t\tlabel: 'SQLite tools',\n\t\tdescription:\n\t\t\t'mcp-sqlite-tools reminder for safer SQLite database work',\n\t\tcli_flag: '--no-sqlite-tools',\n\t\taliases: ['sqlite-tools', 'sqlite', 'mcp-sqlite-tools'],\n\t},\n\t{\n\t\tkey: 'prompt-presets',\n\t\tlabel: 'Prompt presets',\n\t\tdescription:\n\t\t\t'Runtime prompt preset selection and /prompt-preset command',\n\t\tcli_flag: '--no-prompt-presets',\n\t\taliases: ['prompt-presets', 'prompt-preset', 'preset', 'presets'],\n\t},\n\t{\n\t\tkey: 'lsp',\n\t\tlabel: 'LSP',\n\t\tdescription:\n\t\t\t'Language Server Protocol tools (diagnostics, hover, definition, references)',\n\t\tcli_flag: '--no-lsp',\n\t\taliases: ['lsp', 'language-server'],\n\t},\n\t{\n\t\tkey: 'session-name',\n\t\tlabel: 'Session name',\n\t\tdescription:\n\t\t\t'AI-powered session auto-naming and /session-name command',\n\t\tcli_flag: '--no-session-name',\n\t\taliases: ['session-name', 'session', 'auto-name'],\n\t},\n\t{\n\t\tkey: 'confirm-destructive',\n\t\tlabel: 'Confirm destructive',\n\t\tdescription:\n\t\t\t'Prompt before destructive tool calls like file deletes, overwrites, and hard resets',\n\t\tcli_flag: '--no-confirm-destructive',\n\t\taliases: ['confirm-destructive', 'confirm'],\n\t},\n\t{\n\t\tkey: 'hooks-resolution',\n\t\tlabel: 'Hooks resolution',\n\t\tdescription:\n\t\t\t'Claude Code style PostToolUse hook compatibility from .claude, .rulesync, and .pi configs',\n\t\tcli_flag: '--no-hooks',\n\t\taliases: ['hooks-resolution', 'hooks'],\n\t},\n\t{\n\t\tkey: 'team-mode',\n\t\tlabel: 'Team mode',\n\t\tdescription:\n\t\t\t'Experimental orchestrator/team mode with RPC teammates, tasks, and mailboxes',\n\t\tcli_flag: '--no-team-mode',\n\t\taliases: ['team-mode', 'team', 'teammates'],\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 {\n\tExtensionAPI,\n\tExtensionCommandContext,\n} from '@mariozechner/pi-coding-agent';\nimport { type SettingItem } from '@mariozechner/pi-tui';\nimport { show_settings_modal } from '@spences10/pi-tui-modal';\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 = '● enabled';\nconst DISABLED = '○ 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\tasync function show_manager(\n\t\tctx: ExtensionCommandContext,\n\t): Promise<boolean> {\n\t\tif (!ctx.hasUI) return false;\n\n\t\tconst states = resolve_builtin_extension_states(force_disabled);\n\t\tconst initial_enabled = new Set(\n\t\t\tstates\n\t\t\t\t.filter((state) => state.saved_enabled)\n\t\t\t\t.map((state) => state.key),\n\t\t);\n\t\tconst current_enabled = new Set(initial_enabled);\n\n\t\tconst items = states.map(to_setting_item);\n\t\tawait show_settings_modal(ctx, {\n\t\t\ttitle: 'Built-in extensions',\n\t\t\tsubtitle: () => {\n\t\t\t\tconst saved_enabled = current_enabled.size;\n\t\t\t\tconst saved_disabled = states.length - saved_enabled;\n\t\t\t\tconst enabled_now = [...current_enabled].filter(\n\t\t\t\t\t(key) => !force_disabled.has(key as BuiltinExtensionKey),\n\t\t\t\t).length;\n\t\t\t\tconst disabled_now = states.length - enabled_now;\n\t\t\t\treturn `${saved_enabled} saved enabled • ${saved_disabled} saved disabled • ${enabled_now} enabled now • ${disabled_now} disabled now`;\n\t\t\t},\n\t\t\titems,\n\t\t\tenable_search: true,\n\t\t\tfooter:\n\t\t\t\t'esc close • search filters • changes save immediately • CLI --no-* flags still win in this process',\n\t\t\ton_change: (id, new_value) => {\n\t\t\t\tconst key = id as BuiltinExtensionKey;\n\t\t\t\tconst enabled = new_value === ENABLED;\n\t\t\t\tif (enabled) {\n\t\t\t\t\tcurrent_enabled.add(key);\n\t\t\t\t} else {\n\t\t\t\t\tcurrent_enabled.delete(key);\n\t\t\t\t}\n\t\t\t\tsave_extension_enabled(key, enabled);\n\t\t\t},\n\t\t});\n\n\t\tif (!sets_equal(initial_enabled, current_enabled)) {\n\t\t\tctx.ui.notify(\n\t\t\t\tforce_disabled.size > 0\n\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: 'Reloading to apply updated built-in extensions...',\n\t\t\t\t'info',\n\t\t\t);\n\t\t\tawait ctx.reload();\n\t\t}\n\n\t\treturn true;\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) {\n\t\t\t\t\tif (await show_manager(ctx)) return;\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\tif (await show_manager(ctx)) return;\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","import {\n\tgetAgentDir,\n\ttype ExtensionAPI,\n\ttype ExtensionCommandContext,\n\ttype ExtensionContext,\n\ttype ReadonlyFooterDataProvider,\n} from '@mariozechner/pi-coding-agent';\nimport {\n\ttruncateToWidth,\n\tvisibleWidth,\n\ttype SettingItem,\n} from '@mariozechner/pi-tui';\nimport { show_settings_modal } from '@spences10/pi-tui-modal';\nimport {\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trenameSync,\n\tunlinkSync,\n\twriteFileSync,\n} from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nexport type PromptPresetKind = 'base' | 'layer';\nexport type PromptPresetSource = 'builtin' | 'user' | 'project';\n\nconst PROJECT_PROMPT_PRESETS_ENV = 'MY_PI_PROMPT_PRESETS_PROJECT';\n\nexport interface PromptPreset {\n\tkind?: PromptPresetKind;\n\tdescription?: string;\n\tinstructions: string;\n}\n\nexport type PromptPresetMap = Record<string, PromptPreset>;\n\nexport interface LoadedPromptPreset extends PromptPreset {\n\tname: string;\n\tkind: PromptPresetKind;\n\tsource: PromptPresetSource;\n}\n\nexport interface PromptPresetState {\n\tbase_name: string | null;\n\tlayer_names: string[];\n}\n\ninterface PersistedPromptPresetStates {\n\tversion: number;\n\tprojects: Record<string, PromptPresetState>;\n}\n\nconst PRESET_STATE_TYPE = 'prompt-preset-state';\nexport const DEFAULT_BASE_PROMPT_PRESET_NAME = 'terse';\nconst ENABLED = '● enabled';\nconst DISABLED = '○ disabled';\nconst SELECTED = '● selected';\nconst UNSELECTED = '○';\nconst NONE_BASE_ID = '__base_none__';\n\nexport const DEFAULT_PROMPT_PRESETS: PromptPresetMap = {\n\tterse: {\n\t\tkind: 'base',\n\t\tdescription: 'Short, direct, no fluff',\n\t\tinstructions:\n\t\t\t\"Be concise and direct. Default to the shortest response that fully solves the user's request. Use at most one short paragraph or 3 bullets unless the user explicitly asks for detail. For implementation reports, include only what changed, validation, and the next step if relevant. No purple prose, no filler, no repetitive caveats.\",\n\t},\n\tstandard: {\n\t\tkind: 'base',\n\t\tdescription: 'Clear and concise with key context',\n\t\tinstructions:\n\t\t\t'Be clear, direct, and concise. Include only the reasoning and implementation details that matter. Avoid filler, grandstanding, and ornamental language. Use bullets when they improve scanability.',\n\t},\n\tdetailed: {\n\t\tkind: 'base',\n\t\tdescription: 'More explanation when nuance matters',\n\t\tinstructions:\n\t\t\t'Be thorough when the task is complex or tradeoffs matter, but stay practical. Explain only the details that help the user decide, verify, or implement. Avoid purple prose and unnecessary scene-setting.',\n\t},\n\t'no-purple-prose': {\n\t\tkind: 'layer',\n\t\tdescription: 'Strip out ornamental language',\n\t\tinstructions:\n\t\t\t'Do not use purple prose, flourish, motivational filler, or theatrical transitions. Prefer plain language and concrete statements.',\n\t},\n\tbullets: {\n\t\tkind: 'layer',\n\t\tdescription: 'Prefer short bullets when useful',\n\t\tinstructions:\n\t\t\t'When presenting options, findings, or steps, prefer short bullet lists over long paragraphs.',\n\t},\n\t'clarify-first': {\n\t\tkind: 'layer',\n\t\tdescription:\n\t\t\t'Ask brief clarifying questions when requirements are ambiguous',\n\t\tinstructions:\n\t\t\t'If the request is materially ambiguous, ask the minimum clarifying question(s) needed before proceeding. Do not ask unnecessary questions.',\n\t},\n\t'include-risks': {\n\t\tkind: 'layer',\n\t\tdescription: 'Call out notable risks or tradeoffs',\n\t\tinstructions:\n\t\t\t'When making a recommendation or implementation plan, briefly mention the key risk, tradeoff, or caveat if one materially matters.',\n\t},\n};\n\nexport function normalize_prompt_presets(\n\tinput: unknown,\n): PromptPresetMap {\n\tif (!input || typeof input !== 'object') return {};\n\n\tconst normalized: PromptPresetMap = {};\n\tfor (const [raw_name, raw_value] of Object.entries(input)) {\n\t\tconst name = raw_name.trim();\n\t\tif (!name) continue;\n\n\t\tif (typeof raw_value === 'string') {\n\t\t\tnormalized[name] = {\n\t\t\t\tkind: 'base',\n\t\t\t\tinstructions: raw_value,\n\t\t\t};\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!raw_value || typeof raw_value !== 'object') continue;\n\t\tconst candidate = raw_value as {\n\t\t\tkind?: unknown;\n\t\t\tdescription?: unknown;\n\t\t\tinstructions?: unknown;\n\t\t};\n\t\tif (typeof candidate.instructions !== 'string') continue;\n\n\t\tnormalized[name] = {\n\t\t\tinstructions: candidate.instructions,\n\t\t\t...(candidate.kind === 'layer'\n\t\t\t\t? { kind: 'layer' as const }\n\t\t\t\t: {}),\n\t\t\t...(typeof candidate.description === 'string'\n\t\t\t\t? { description: candidate.description }\n\t\t\t\t: {}),\n\t\t};\n\t}\n\n\treturn normalized;\n}\n\nexport function merge_prompt_presets(\n\t...sources: PromptPresetMap[]\n): PromptPresetMap {\n\treturn Object.assign({}, ...sources);\n}\n\nfunction to_loaded_prompt_presets(\n\tpresets: PromptPresetMap,\n\tsource: PromptPresetSource,\n): Record<string, LoadedPromptPreset> {\n\treturn Object.fromEntries(\n\t\tObject.entries(presets).map(([name, preset]) => [\n\t\t\tname,\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tkind: preset.kind === 'layer' ? 'layer' : 'base',\n\t\t\t\tsource,\n\t\t\t\t...preset,\n\t\t\t},\n\t\t]),\n\t);\n}\n\nfunction get_global_presets_path(): string {\n\treturn join(getAgentDir(), 'presets.json');\n}\n\nfunction get_project_presets_path(cwd: string): string {\n\treturn join(cwd, '.pi', 'presets.json');\n}\n\nfunction get_global_presets_dir(): string {\n\treturn join(getAgentDir(), 'presets');\n}\n\nfunction get_project_presets_dir(cwd: string): string {\n\treturn join(cwd, '.pi', 'presets');\n}\n\nfunction sanitize_prompt_preset_file_name(name: string): string {\n\tconst sanitized = name\n\t\t.trim()\n\t\t.replace(/[\\\\/:*?\"<>|]/g, '-')\n\t\t.replace(/^\\.+$/, '')\n\t\t.replace(/^\\.+/, '')\n\t\t.replace(/\\.+$/, '');\n\tif (!sanitized) {\n\t\tthrow new Error(\n\t\t\t'Prompt preset name must contain a file-safe character',\n\t\t);\n\t}\n\treturn sanitized;\n}\n\nfunction get_prompt_preset_file_path(\n\tdir: string,\n\tname: string,\n): string {\n\treturn join(dir, `${sanitize_prompt_preset_file_name(name)}.md`);\n}\n\nfunction get_persisted_prompt_state_path(): string {\n\treturn join(getAgentDir(), 'prompt-preset-state.json');\n}\n\nfunction read_prompt_presets_file(path: string): PromptPresetMap {\n\tif (!existsSync(path)) return {};\n\n\ttry {\n\t\treturn normalize_prompt_presets(\n\t\t\tJSON.parse(readFileSync(path, 'utf-8')),\n\t\t);\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction unquote_frontmatter_value(value: string): string {\n\tconst trimmed = value.trim();\n\tif (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n\t\ttry {\n\t\t\treturn JSON.parse(trimmed) as string;\n\t\t} catch {\n\t\t\treturn trimmed.slice(1, -1);\n\t\t}\n\t}\n\tif (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n\t\treturn trimmed.slice(1, -1);\n\t}\n\treturn trimmed;\n}\n\nfunction parse_prompt_preset_markdown(content: string): {\n\tmetadata: Record<string, string>;\n\tbody: string;\n} {\n\tconst normalized = content.replace(/\\r\\n/g, '\\n');\n\tif (!normalized.startsWith('---\\n')) {\n\t\treturn { metadata: {}, body: normalized.trim() };\n\t}\n\n\tconst lines = normalized.split('\\n');\n\tconst end = lines.findIndex(\n\t\t(line, index) => index > 0 && line.trim() === '---',\n\t);\n\tif (end === -1) {\n\t\treturn { metadata: {}, body: normalized.trim() };\n\t}\n\n\tconst metadata: Record<string, string> = {};\n\tfor (const line of lines.slice(1, end)) {\n\t\tconst separator = line.indexOf(':');\n\t\tif (separator === -1) continue;\n\t\tconst key = line.slice(0, separator).trim().toLowerCase();\n\t\tconst value = line.slice(separator + 1).trim();\n\t\tif (!key) continue;\n\t\tmetadata[key] = unquote_frontmatter_value(value);\n\t}\n\n\treturn {\n\t\tmetadata,\n\t\tbody: lines\n\t\t\t.slice(end + 1)\n\t\t\t.join('\\n')\n\t\t\t.trim(),\n\t};\n}\n\nexport function read_prompt_presets_dir(\n\tpath: string,\n): PromptPresetMap {\n\tif (!existsSync(path)) return {};\n\n\ttry {\n\t\tconst presets: PromptPresetMap = {};\n\t\tfor (const entry of readdirSync(path, { withFileTypes: true })\n\t\t\t.filter((item) => item.isFile() && item.name.endsWith('.md'))\n\t\t\t.sort((a, b) => a.name.localeCompare(b.name))) {\n\t\t\tconst name = entry.name.slice(0, -3).trim();\n\t\t\tif (!name) continue;\n\t\t\tconst { metadata, body } = parse_prompt_preset_markdown(\n\t\t\t\treadFileSync(join(path, entry.name), 'utf-8'),\n\t\t\t);\n\t\t\tif (!body) continue;\n\t\t\tpresets[name] = {\n\t\t\t\tkind: metadata.kind === 'layer' ? 'layer' : 'base',\n\t\t\t\tinstructions: body,\n\t\t\t\t...(metadata.description\n\t\t\t\t\t? { description: metadata.description }\n\t\t\t\t\t: {}),\n\t\t\t};\n\t\t}\n\t\treturn presets;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction format_prompt_preset_markdown(preset: PromptPreset): string {\n\tconst lines = [\n\t\t'---',\n\t\t`kind: ${preset.kind === 'layer' ? 'layer' : 'base'}`,\n\t];\n\tif (preset.description?.trim()) {\n\t\tlines.push(\n\t\t\t`description: ${JSON.stringify(preset.description.trim())}`,\n\t\t);\n\t}\n\tlines.push('---', '', preset.instructions.trim(), '');\n\treturn lines.join('\\n');\n}\n\nexport function save_prompt_preset_file(\n\tdir: string,\n\tname: string,\n\tpreset: PromptPreset,\n): string {\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n\n\tconst path = get_prompt_preset_file_path(dir, name);\n\tconst tmp = `${path}.tmp-${Date.now()}`;\n\twriteFileSync(tmp, format_prompt_preset_markdown(preset), {\n\t\tmode: 0o600,\n\t});\n\trenameSync(tmp, path);\n\treturn path;\n}\n\nfunction save_project_prompt_preset_file(\n\tcwd: string,\n\tname: string,\n\tpreset: PromptPreset,\n): string {\n\treturn save_prompt_preset_file(\n\t\tget_project_presets_dir(cwd),\n\t\tname,\n\t\tpreset,\n\t);\n}\n\nfunction save_global_prompt_preset_file(\n\tname: string,\n\tpreset: PromptPreset,\n): string {\n\treturn save_prompt_preset_file(\n\t\tget_global_presets_dir(),\n\t\tname,\n\t\tpreset,\n\t);\n}\n\nfunction should_load_project_prompt_presets(): boolean {\n\tconst normalized = process.env[PROJECT_PROMPT_PRESETS_ENV]\n\t\t?.trim()\n\t\t.toLowerCase();\n\treturn !['0', 'false', 'no', 'skip', 'disable'].includes(\n\t\tnormalized ?? '',\n\t);\n}\n\nexport function load_prompt_presets(\n\tcwd: string,\n): Record<string, LoadedPromptPreset> {\n\treturn Object.assign(\n\t\t{},\n\t\tto_loaded_prompt_presets(DEFAULT_PROMPT_PRESETS, 'builtin'),\n\t\tto_loaded_prompt_presets(\n\t\t\tread_prompt_presets_file(get_global_presets_path()),\n\t\t\t'user',\n\t\t),\n\t\tto_loaded_prompt_presets(\n\t\t\tread_prompt_presets_dir(get_global_presets_dir()),\n\t\t\t'user',\n\t\t),\n\t\t...(should_load_project_prompt_presets()\n\t\t\t? [\n\t\t\t\t\tto_loaded_prompt_presets(\n\t\t\t\t\t\tread_prompt_presets_file(get_project_presets_path(cwd)),\n\t\t\t\t\t\t'project',\n\t\t\t\t\t),\n\t\t\t\t\tto_loaded_prompt_presets(\n\t\t\t\t\t\tread_prompt_presets_dir(get_project_presets_dir(cwd)),\n\t\t\t\t\t\t'project',\n\t\t\t\t\t),\n\t\t\t\t]\n\t\t\t: []),\n\t);\n}\n\nfunction sort_prompt_presets(\n\tpresets: PromptPresetMap,\n): PromptPresetMap {\n\treturn Object.fromEntries(\n\t\tObject.entries(presets).sort(([a], [b]) => a.localeCompare(b)),\n\t);\n}\n\nexport function save_project_prompt_presets(\n\tcwd: string,\n\tpresets: PromptPresetMap,\n): string {\n\tconst path = get_project_presets_path(cwd);\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n\n\tconst tmp = `${path}.tmp-${Date.now()}`;\n\twriteFileSync(\n\t\ttmp,\n\t\tJSON.stringify(sort_prompt_presets(presets), null, '\\t') + '\\n',\n\t\t{ mode: 0o600 },\n\t);\n\trenameSync(tmp, path);\n\treturn path;\n}\n\nexport function remove_project_prompt_preset(\n\tcwd: string,\n\tname: string,\n): {\n\tremoved: boolean;\n\tpath: string;\n\tremaining: number;\n} {\n\tconst json_path = get_project_presets_path(cwd);\n\tconst project_presets = read_prompt_presets_file(json_path);\n\tlet removed = false;\n\tlet removed_path = json_path;\n\n\tif (name in project_presets) {\n\t\tdelete project_presets[name];\n\t\tremoved = true;\n\t\tremoved_path = json_path;\n\t\tif (Object.keys(project_presets).length === 0) {\n\t\t\tif (existsSync(json_path)) {\n\t\t\t\tunlinkSync(json_path);\n\t\t\t}\n\t\t} else {\n\t\t\tsave_project_prompt_presets(cwd, project_presets);\n\t\t}\n\t}\n\n\tconst file_path = get_prompt_preset_file_path(\n\t\tget_project_presets_dir(cwd),\n\t\tname,\n\t);\n\tif (existsSync(file_path)) {\n\t\tunlinkSync(file_path);\n\t\tremoved = true;\n\t\tremoved_path = file_path;\n\t}\n\n\tconst remaining =\n\t\tObject.keys(read_prompt_presets_file(json_path)).length +\n\t\tObject.keys(read_prompt_presets_dir(get_project_presets_dir(cwd)))\n\t\t\t.length;\n\n\treturn { removed, path: removed_path, remaining };\n}\n\nfunction normalize_prompt_preset_state(\n\tinput: unknown,\n): PromptPresetState | undefined {\n\tif (!input || typeof input !== 'object') return undefined;\n\n\tconst candidate = input as {\n\t\tbase_name?: unknown;\n\t\tlayer_names?: unknown;\n\t};\n\tconst base_name =\n\t\ttypeof candidate.base_name === 'string' &&\n\t\tcandidate.base_name.trim()\n\t\t\t? candidate.base_name.trim()\n\t\t\t: null;\n\tconst layer_names = Array.isArray(candidate.layer_names)\n\t\t? [\n\t\t\t\t...new Set(\n\t\t\t\t\tcandidate.layer_names\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t(value): value is string =>\n\t\t\t\t\t\t\t\ttypeof value === 'string' && value.trim().length > 0,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.map((value) => value.trim()),\n\t\t\t\t),\n\t\t\t].sort()\n\t\t: [];\n\n\treturn {\n\t\tbase_name,\n\t\tlayer_names,\n\t};\n}\n\nfunction read_persisted_prompt_states(\n\tpath = get_persisted_prompt_state_path(),\n): PersistedPromptPresetStates {\n\tif (!existsSync(path)) {\n\t\treturn { version: 1, projects: {} };\n\t}\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(path, 'utf-8')) as {\n\t\t\tversion?: unknown;\n\t\t\tprojects?: unknown;\n\t\t};\n\t\tconst raw_projects =\n\t\t\tparsed.projects && typeof parsed.projects === 'object'\n\t\t\t\t? parsed.projects\n\t\t\t\t: {};\n\t\tconst projects: Record<string, PromptPresetState> = {};\n\t\tfor (const [cwd, value] of Object.entries(raw_projects)) {\n\t\t\tconst normalized = normalize_prompt_preset_state(value);\n\t\t\tif (!normalized) continue;\n\t\t\tprojects[cwd] = normalized;\n\t\t}\n\t\treturn {\n\t\t\tversion:\n\t\t\t\ttypeof parsed.version === 'number' ? parsed.version : 1,\n\t\t\tprojects,\n\t\t};\n\t} catch {\n\t\treturn { version: 1, projects: {} };\n\t}\n}\n\nexport function load_persisted_prompt_state(\n\tcwd: string,\n\tpath = get_persisted_prompt_state_path(),\n): PromptPresetState | undefined {\n\treturn read_persisted_prompt_states(path).projects[cwd];\n}\n\nexport function save_persisted_prompt_state(\n\tcwd: string,\n\tstate: PromptPresetState,\n\tpath = get_persisted_prompt_state_path(),\n): string {\n\tconst persisted = read_persisted_prompt_states(path);\n\tpersisted.projects[cwd] = normalize_prompt_preset_state(state) ?? {\n\t\tbase_name: null,\n\t\tlayer_names: [],\n\t};\n\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n\n\tconst tmp = `${path}.tmp-${Date.now()}`;\n\twriteFileSync(\n\t\ttmp,\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tversion: 1,\n\t\t\t\tprojects: Object.fromEntries(\n\t\t\t\t\tObject.entries(persisted.projects).sort(([a], [b]) =>\n\t\t\t\t\t\ta.localeCompare(b),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t},\n\t\t\tnull,\n\t\t\t'\\t',\n\t\t) + '\\n',\n\t\t{ mode: 0o600 },\n\t);\n\trenameSync(tmp, path);\n\treturn path;\n}\n\nfunction get_last_preset_state(\n\tctx: ExtensionContext,\n): PromptPresetState | undefined {\n\tconst entries = ctx.sessionManager.getEntries();\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i] as {\n\t\t\ttype?: string;\n\t\t\tcustomType?: string;\n\t\t\tdata?: PromptPresetState;\n\t\t};\n\t\tif (\n\t\t\tentry.type === 'custom' &&\n\t\t\tentry.customType === PRESET_STATE_TYPE &&\n\t\t\tentry.data\n\t\t) {\n\t\t\treturn entry.data;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction sets_equal(\n\ta: ReadonlySet<string>,\n\tb: ReadonlySet<string>,\n): boolean {\n\tif (a.size !== b.size) return false;\n\tfor (const value of a) {\n\t\tif (!b.has(value)) return false;\n\t}\n\treturn true;\n}\n\nfunction get_prompt_source_label(source: PromptPresetSource): string {\n\tswitch (source) {\n\t\tcase 'builtin':\n\t\t\treturn 'built-in';\n\t\tcase 'user':\n\t\t\treturn 'user';\n\t\tcase 'project':\n\t\t\treturn 'project';\n\t}\n}\n\nfunction list_base_presets(\n\tpresets: Record<string, LoadedPromptPreset>,\n): LoadedPromptPreset[] {\n\treturn Object.values(presets)\n\t\t.filter((preset) => preset.kind === 'base')\n\t\t.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction list_layer_presets(\n\tpresets: Record<string, LoadedPromptPreset>,\n): LoadedPromptPreset[] {\n\treturn Object.values(presets)\n\t\t.filter((preset) => preset.kind === 'layer')\n\t\t.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction format_summary(\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n\tpresets: Record<string, LoadedPromptPreset>,\n): string {\n\tconst lines = [`Base: ${active_base_name ?? '(none)'}`];\n\n\tconst layer_names = [...active_layers].sort();\n\tif (layer_names.length === 0) {\n\t\tlines.push('Layers: (none)');\n\t} else {\n\t\tlines.push('Layers:');\n\t\tfor (const name of layer_names) {\n\t\t\tconst preset = presets[name];\n\t\t\tconst description = preset?.description\n\t\t\t\t? ` — ${preset.description}`\n\t\t\t\t: '';\n\t\t\tlines.push(`- ${name}${description}`);\n\t\t}\n\t}\n\n\treturn lines.join('\\n');\n}\n\nfunction format_active_details(\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n\tpresets: Record<string, LoadedPromptPreset>,\n): string {\n\tconst parts: string[] = [];\n\n\tif (active_base_name) {\n\t\tconst base = presets[active_base_name];\n\t\tif (base) {\n\t\t\tparts.push(`Base: ${base.name}`);\n\t\t\tif (base.description)\n\t\t\t\tparts.push(`Description: ${base.description}`);\n\t\t\tparts.push(`Source: ${get_prompt_source_label(base.source)}`);\n\t\t\tparts.push('', base.instructions.trim());\n\t\t}\n\t}\n\n\tconst layer_names = [...active_layers].sort();\n\tif (layer_names.length > 0) {\n\t\tif (parts.length > 0) parts.push('', '---', '');\n\t\tparts.push('Layers:');\n\t\tfor (const name of layer_names) {\n\t\t\tconst layer = presets[name];\n\t\t\tif (!layer) continue;\n\t\t\tparts.push(\n\t\t\t\t`- ${layer.name} (${get_prompt_source_label(layer.source)})`,\n\t\t\t);\n\t\t\tif (layer.description) parts.push(` ${layer.description}`);\n\t\t}\n\t}\n\n\treturn parts.join('\\n') || 'No preset or layers active';\n}\n\nfunction get_footer_prompt_status(\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): string | undefined {\n\tif (!active_base_name && active_layers.size === 0) {\n\t\treturn undefined;\n\t}\n\n\tconst label = active_base_name ?? 'none';\n\tconst layer_suffix =\n\t\tactive_layers.size > 0 ? ` +${active_layers.size}` : '';\n\treturn `prompt:${label}${layer_suffix}`;\n}\n\nfunction sanitize_status_text(text: string): string {\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, ' ')\n\t\t.replace(/ +/g, ' ')\n\t\t.trim();\n}\n\nfunction format_token_count(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\nexport function render_footer_status_line(\n\ttheme: ExtensionContext['ui']['theme'],\n\twidth: number,\n\tleft_items: string[],\n\tright_item?: string,\n): string | undefined {\n\tconst left = sanitize_status_text(left_items.join(' '));\n\tconst right = right_item ? sanitize_status_text(right_item) : '';\n\tif (!left && !right) return undefined;\n\tif (!right) {\n\t\treturn truncateToWidth(\n\t\t\ttheme.fg('dim', left),\n\t\t\twidth,\n\t\t\ttheme.fg('dim', '...'),\n\t\t);\n\t}\n\tif (!left) {\n\t\tconst themed_right = theme.fg('dim', right);\n\t\tconst right_width = visibleWidth(themed_right);\n\t\treturn right_width >= width\n\t\t\t? truncateToWidth(themed_right, width, theme.fg('dim', '...'))\n\t\t\t: `${' '.repeat(width - right_width)}${themed_right}`;\n\t}\n\n\tconst right_width = visibleWidth(right);\n\tif (right_width >= width) {\n\t\treturn truncateToWidth(\n\t\t\ttheme.fg('dim', right),\n\t\t\twidth,\n\t\t\ttheme.fg('dim', '...'),\n\t\t);\n\t}\n\n\tconst min_gap = 1;\n\tconst available_left = Math.max(0, width - right_width - min_gap);\n\tconst truncated_left = truncateToWidth(left, available_left, '...');\n\tconst left_width = visibleWidth(truncated_left);\n\tconst gap = Math.max(min_gap, width - left_width - right_width);\n\treturn (\n\t\ttheme.fg('dim', truncated_left) +\n\t\t' '.repeat(gap) +\n\t\ttheme.fg('dim', right)\n\t);\n}\n\nfunction get_current_thinking_level(ctx: ExtensionContext): string {\n\tconst entries = ctx.sessionManager.getEntries();\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i] as {\n\t\t\ttype?: string;\n\t\t\tthinkingLevel?: string;\n\t\t};\n\t\tif (\n\t\t\tentry.type === 'thinking_level_change' &&\n\t\t\ttypeof entry.thinkingLevel === 'string'\n\t\t) {\n\t\t\treturn entry.thinkingLevel;\n\t\t}\n\t}\n\treturn ctx.model?.reasoning ? 'high' : 'off';\n}\n\nfunction render_footer_lines(\n\tctx: ExtensionContext,\n\ttheme: ExtensionContext['ui']['theme'],\n\tfooter_data: ReadonlyFooterDataProvider,\n\twidth: number,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): string[] {\n\tlet total_input = 0;\n\tlet total_output = 0;\n\tlet total_cache_read = 0;\n\tlet total_cache_write = 0;\n\tlet total_cost = 0;\n\tfor (const entry of ctx.sessionManager.getEntries()) {\n\t\tif (\n\t\t\tentry.type === 'message' &&\n\t\t\tentry.message.role === 'assistant'\n\t\t) {\n\t\t\ttotal_input += entry.message.usage.input;\n\t\t\ttotal_output += entry.message.usage.output;\n\t\t\ttotal_cache_read += entry.message.usage.cacheRead;\n\t\t\ttotal_cache_write += entry.message.usage.cacheWrite;\n\t\t\ttotal_cost += entry.message.usage.cost.total;\n\t\t}\n\t}\n\n\tconst context_usage = ctx.getContextUsage();\n\tconst context_window =\n\t\tcontext_usage?.contextWindow ?? ctx.model?.contextWindow ?? 0;\n\tconst context_percent_value = context_usage?.percent ?? 0;\n\tconst context_percent =\n\t\tcontext_usage?.percent !== null\n\t\t\t? context_percent_value.toFixed(1)\n\t\t\t: '?';\n\n\tlet pwd = ctx.cwd;\n\tconst home = process.env.HOME || process.env.USERPROFILE;\n\tif (home && pwd.startsWith(home)) {\n\t\tpwd = `~${pwd.slice(home.length)}`;\n\t}\n\n\tconst branch = footer_data.getGitBranch();\n\tif (branch) {\n\t\tpwd = `${pwd} (${branch})`;\n\t}\n\n\tconst session_name = ctx.sessionManager.getSessionName();\n\tif (session_name) {\n\t\tpwd = `${pwd} • ${session_name}`;\n\t}\n\n\tconst stats_parts: string[] = [];\n\tif (total_input)\n\t\tstats_parts.push(`↑${format_token_count(total_input)}`);\n\tif (total_output)\n\t\tstats_parts.push(`↓${format_token_count(total_output)}`);\n\tif (total_cache_read)\n\t\tstats_parts.push(`R${format_token_count(total_cache_read)}`);\n\tif (total_cache_write)\n\t\tstats_parts.push(`W${format_token_count(total_cache_write)}`);\n\n\tconst using_subscription = ctx.model\n\t\t? ctx.modelRegistry.isUsingOAuth(ctx.model)\n\t\t: false;\n\tif (total_cost || using_subscription) {\n\t\tstats_parts.push(\n\t\t\t`$${total_cost.toFixed(3)}${using_subscription ? ' (sub)' : ''}`,\n\t\t);\n\t}\n\n\tconst context_percent_display =\n\t\tcontext_percent === '?'\n\t\t\t? `?/${format_token_count(context_window)}`\n\t\t\t: `${context_percent}%/${format_token_count(context_window)}`;\n\tlet context_percent_str = context_percent_display;\n\tif (context_percent_value > 90) {\n\t\tcontext_percent_str = theme.fg('error', context_percent_display);\n\t} else if (context_percent_value > 70) {\n\t\tcontext_percent_str = theme.fg(\n\t\t\t'warning',\n\t\t\tcontext_percent_display,\n\t\t);\n\t}\n\tstats_parts.push(context_percent_str);\n\n\tlet stats_left = stats_parts.join(' ');\n\tlet stats_left_width = visibleWidth(stats_left);\n\tif (stats_left_width > width) {\n\t\tstats_left = truncateToWidth(stats_left, width, '...');\n\t\tstats_left_width = visibleWidth(stats_left);\n\t}\n\n\tconst model_name = ctx.model?.id || 'no-model';\n\tconst thinking_level = get_current_thinking_level(ctx);\n\tlet right_side_without_provider = model_name;\n\tif (ctx.model?.reasoning) {\n\t\tright_side_without_provider =\n\t\t\tthinking_level === 'off'\n\t\t\t\t? `${model_name} • thinking off`\n\t\t\t\t: `${model_name} • ${thinking_level}`;\n\t}\n\n\tlet right_side = right_side_without_provider;\n\tif (footer_data.getAvailableProviderCount() > 1 && ctx.model) {\n\t\tright_side = `(${ctx.model.provider}) ${right_side_without_provider}`;\n\t\tif (stats_left_width + 2 + visibleWidth(right_side) > width) {\n\t\t\tright_side = right_side_without_provider;\n\t\t}\n\t}\n\n\tconst right_side_width = visibleWidth(right_side);\n\tconst total_needed = stats_left_width + 2 + right_side_width;\n\tlet stats_line: string;\n\tif (total_needed <= width) {\n\t\tconst padding = ' '.repeat(\n\t\t\twidth - stats_left_width - right_side_width,\n\t\t);\n\t\tstats_line = stats_left + padding + right_side;\n\t} else {\n\t\tconst available_for_right = width - stats_left_width - 2;\n\t\tif (available_for_right > 0) {\n\t\t\tconst truncated_right = truncateToWidth(\n\t\t\t\tright_side,\n\t\t\t\tavailable_for_right,\n\t\t\t\t'',\n\t\t\t);\n\t\t\tconst truncated_right_width = visibleWidth(truncated_right);\n\t\t\tconst padding = ' '.repeat(\n\t\t\t\tMath.max(0, width - stats_left_width - truncated_right_width),\n\t\t\t);\n\t\t\tstats_line = stats_left + padding + truncated_right;\n\t\t} else {\n\t\t\tstats_line = stats_left;\n\t\t}\n\t}\n\n\tconst dim_stats_left = theme.fg('dim', stats_left);\n\tconst remainder = stats_line.slice(stats_left.length);\n\tconst dim_remainder = theme.fg('dim', remainder);\n\tconst lines = [\n\t\ttruncateToWidth(\n\t\t\ttheme.fg('dim', pwd),\n\t\t\twidth,\n\t\t\ttheme.fg('dim', '...'),\n\t\t),\n\t\tdim_stats_left + dim_remainder,\n\t];\n\n\tconst prompt_status = get_footer_prompt_status(\n\t\tactive_base_name,\n\t\tactive_layers,\n\t);\n\n\tconst other_statuses = Array.from(\n\t\tfooter_data.getExtensionStatuses().entries(),\n\t)\n\t\t.filter(([key]) => key !== 'preset')\n\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t.map(([, text]) => sanitize_status_text(text));\n\tconst combined_status_line = render_footer_status_line(\n\t\ttheme,\n\t\twidth,\n\t\tother_statuses,\n\t\tprompt_status,\n\t);\n\tif (combined_status_line) {\n\t\tlines.push(combined_status_line);\n\t}\n\n\treturn lines;\n}\n\nfunction set_status(\n\tctx: ExtensionContext,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): void {\n\tctx.ui.setStatus('preset', undefined);\n\tif (!ctx.hasUI) return;\n\tctx.ui.setFooter((tui, theme, footer_data) => {\n\t\tconst unsubscribe = footer_data.onBranchChange(() =>\n\t\t\ttui.requestRender(),\n\t\t);\n\t\treturn {\n\t\t\tdispose: unsubscribe,\n\t\t\tinvalidate() {},\n\t\t\trender(width: number) {\n\t\t\t\treturn render_footer_lines(\n\t\t\t\t\tctx,\n\t\t\t\t\ttheme,\n\t\t\t\t\tfooter_data,\n\t\t\t\t\twidth,\n\t\t\t\t\tactive_base_name,\n\t\t\t\t\tactive_layers,\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t});\n}\n\nfunction persist_state(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): void {\n\tconst state = {\n\t\tbase_name: active_base_name ?? null,\n\t\tlayer_names: [...active_layers].sort(),\n\t};\n\tpi.appendEntry(PRESET_STATE_TYPE, state);\n\tsave_persisted_prompt_state(ctx.cwd, state);\n}\n\nfunction normalize_active_state(\n\tpresets: Record<string, LoadedPromptPreset>,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): {\n\tactive_base_name: string | undefined;\n\tactive_layers: Set<string>;\n} {\n\tconst next_base_name =\n\t\tactive_base_name && presets[active_base_name]?.kind === 'base'\n\t\t\t? active_base_name\n\t\t\t: undefined;\n\tconst next_layers = new Set(\n\t\t[...active_layers].filter(\n\t\t\t(name) => presets[name]?.kind === 'layer',\n\t\t),\n\t);\n\treturn {\n\t\tactive_base_name: next_base_name,\n\t\tactive_layers: next_layers,\n\t};\n}\n\nfunction parse_preset_flag(flag: string): string[] {\n\treturn flag\n\t\t.split(',')\n\t\t.map((item) => item.trim())\n\t\t.filter(Boolean);\n}\n\nfunction is_subcommand(command: string): boolean {\n\treturn [\n\t\t'help',\n\t\t'list',\n\t\t'show',\n\t\t'clear',\n\t\t'edit',\n\t\t'edit-global',\n\t\t'export-defaults',\n\t\t'delete',\n\t\t'reset',\n\t\t'reload',\n\t\t'base',\n\t\t'enable',\n\t\t'disable',\n\t\t'toggle',\n\t].includes(command);\n}\n\nfunction format_prompt_preset_help(): string {\n\treturn `Prompt presets append instructions to the system prompt.\n\nCommands:\n- /prompt-preset Open the preset picker\n- /prompt-preset show Show the active base and layers\n- /prompt-preset <name> Activate a base preset or toggle a layer\n- /prompt-preset base <name> Activate a base preset\n- /prompt-preset enable <layer> Enable a layer\n- /prompt-preset disable <layer> Disable a layer\n- /prompt-preset edit <name> Edit/create .pi/presets/<name>.md\n- /prompt-preset edit-global <name> Edit/create ~/.pi/agent/presets/<name>.md\n- /prompt-preset export-defaults Export built-ins to ~/.pi/agent/presets/*.md\n- /prompt-preset export-defaults project Export built-ins to .pi/presets/*.md\n- /prompt-preset reload Reload presets after manual file edits\n- /prompt-preset clear Clear active base and layers\n\nExamples:\n- /prompt-preset export-defaults\n- /prompt-preset edit-global terse\n- /prompt-preset base detailed\n- /prompt-preset enable bullets\n- /prompt-preset show\n\nAlias: /preset`;\n}\n\nexport default async function prompt_presets(pi: ExtensionAPI) {\n\tlet presets: Record<string, LoadedPromptPreset> = {};\n\tlet active_base_name: string | undefined;\n\tlet active_layers = new Set<string>();\n\n\tfunction get_base(\n\t\tname: string | undefined,\n\t): LoadedPromptPreset | undefined {\n\t\treturn name ? presets[name] : undefined;\n\t}\n\n\tfunction get_layer(name: string): LoadedPromptPreset | undefined {\n\t\tconst preset = presets[name];\n\t\treturn preset?.kind === 'layer' ? preset : undefined;\n\t}\n\n\tfunction commit_state(\n\t\tctx: ExtensionContext,\n\t\tnext_base_name: string | undefined,\n\t\tnext_layers: ReadonlySet<string>,\n\t\toptions?: { persist?: boolean; notify?: string },\n\t): void {\n\t\tactive_base_name = next_base_name;\n\t\tactive_layers = new Set(next_layers);\n\t\tset_status(ctx, active_base_name, active_layers);\n\t\tif (options?.persist !== false) {\n\t\t\tpersist_state(pi, ctx, active_base_name, active_layers);\n\t\t}\n\t\tif (options?.notify) {\n\t\t\tctx.ui.notify(options.notify, 'info');\n\t\t}\n\t}\n\n\tfunction activate_base(\n\t\tname: string | undefined,\n\t\tctx: ExtensionContext,\n\t\toptions?: { persist?: boolean },\n\t): boolean {\n\t\tif (!name) {\n\t\t\tcommit_state(ctx, undefined, active_layers, {\n\t\t\t\tpersist: options?.persist,\n\t\t\t\tnotify: 'Base preset cleared',\n\t\t\t});\n\t\t\treturn true;\n\t\t}\n\n\t\tconst preset = get_base(name);\n\t\tif (!preset) {\n\t\t\tctx.ui.notify(`Unknown base preset: ${name}`, 'warning');\n\t\t\treturn false;\n\t\t}\n\n\t\tcommit_state(ctx, preset.name, active_layers, {\n\t\t\tpersist: options?.persist,\n\t\t\tnotify: `Base preset \"${preset.name}\" activated`,\n\t\t});\n\t\treturn true;\n\t}\n\n\tfunction set_layer_enabled(\n\t\tname: string,\n\t\tenabled: boolean,\n\t\tctx: ExtensionContext,\n\t\toptions?: { persist?: boolean },\n\t): boolean {\n\t\tconst preset = get_layer(name);\n\t\tif (!preset) {\n\t\t\tctx.ui.notify(`Unknown prompt layer: ${name}`, 'warning');\n\t\t\treturn false;\n\t\t}\n\n\t\tconst next_layers = new Set(active_layers);\n\t\tif (enabled) {\n\t\t\tnext_layers.add(preset.name);\n\t\t} else {\n\t\t\tnext_layers.delete(preset.name);\n\t\t}\n\n\t\tcommit_state(ctx, active_base_name, next_layers, {\n\t\t\tpersist: options?.persist,\n\t\t\tnotify: enabled\n\t\t\t\t? `Layer \"${preset.name}\" enabled`\n\t\t\t\t: `Layer \"${preset.name}\" disabled`,\n\t\t});\n\t\treturn true;\n\t}\n\n\tfunction toggle_layer(\n\t\tname: string,\n\t\tctx: ExtensionContext,\n\t\toptions?: { persist?: boolean },\n\t): boolean {\n\t\treturn set_layer_enabled(\n\t\t\tname,\n\t\t\t!active_layers.has(name),\n\t\t\tctx,\n\t\t\toptions,\n\t\t);\n\t}\n\n\tasync function edit_preset(\n\t\tname: string,\n\t\tctx: ExtensionCommandContext,\n\t\tscope: 'project' | 'global' = 'project',\n\t): Promise<void> {\n\t\tconst existing = presets[name];\n\t\tconst kind_choice = await ctx.ui.select('Preset kind', [\n\t\t\texisting?.kind === 'layer'\n\t\t\t\t? 'layer (current)'\n\t\t\t\t: 'base (current)',\n\t\t\texisting?.kind === 'layer' ? 'base' : 'layer',\n\t\t]);\n\t\tif (!kind_choice) return;\n\t\tconst kind: PromptPresetKind = kind_choice.startsWith('layer')\n\t\t\t? 'layer'\n\t\t\t: 'base';\n\n\t\tconst description = await ctx.ui.input(\n\t\t\t`Description for ${name}`,\n\t\t\texisting?.description ?? '',\n\t\t);\n\t\tif (description === undefined) return;\n\n\t\tconst instructions = await ctx.ui.editor(\n\t\t\t`Edit ${kind} preset: ${name}`,\n\t\t\texisting?.instructions ?? '',\n\t\t);\n\t\tif (instructions === undefined) return;\n\n\t\tconst saved_path =\n\t\t\tscope === 'global'\n\t\t\t\t? save_global_prompt_preset_file(name, {\n\t\t\t\t\t\tkind,\n\t\t\t\t\t\tinstructions,\n\t\t\t\t\t\t...(description.trim()\n\t\t\t\t\t\t\t? { description: description.trim() }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t})\n\t\t\t\t: save_project_prompt_preset_file(ctx.cwd, name, {\n\t\t\t\t\t\tkind,\n\t\t\t\t\t\tinstructions,\n\t\t\t\t\t\t...(description.trim()\n\t\t\t\t\t\t\t? { description: description.trim() }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t});\n\n\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\tconst normalized = normalize_active_state(\n\t\t\tpresets,\n\t\t\tactive_base_name,\n\t\t\tactive_layers,\n\t\t);\n\t\tactive_base_name = normalized.active_base_name;\n\t\tactive_layers = normalized.active_layers;\n\n\t\tif (kind === 'base') {\n\t\t\tactivate_base(name, ctx);\n\t\t} else {\n\t\t\tset_layer_enabled(name, true, ctx);\n\t\t}\n\t\tctx.ui.notify(`Saved preset \"${name}\" to ${saved_path}`, 'info');\n\t}\n\n\tfunction export_default_presets(\n\t\tctx: ExtensionCommandContext,\n\t\tscope: 'project' | 'global',\n\t): void {\n\t\tconst dir =\n\t\t\tscope === 'global'\n\t\t\t\t? get_global_presets_dir()\n\t\t\t\t: get_project_presets_dir(ctx.cwd);\n\t\tlet written = 0;\n\t\tlet skipped = 0;\n\t\tfor (const [name, preset] of Object.entries(\n\t\t\tDEFAULT_PROMPT_PRESETS,\n\t\t)) {\n\t\t\tconst path = get_prompt_preset_file_path(dir, name);\n\t\t\tif (existsSync(path)) {\n\t\t\t\tskipped += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tsave_prompt_preset_file(dir, name, preset);\n\t\t\twritten += 1;\n\t\t}\n\n\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\tconst normalized = normalize_active_state(\n\t\t\tpresets,\n\t\t\tactive_base_name,\n\t\t\tactive_layers,\n\t\t);\n\t\tactive_base_name = normalized.active_base_name;\n\t\tactive_layers = normalized.active_layers;\n\t\tset_status(ctx, active_base_name, active_layers);\n\n\t\tctx.ui.notify(\n\t\t\t`Exported ${written} built-in preset file(s) to ${dir}${skipped ? ` (${skipped} already existed)` : ''}`,\n\t\t\t'info',\n\t\t);\n\t}\n\n\tfunction remove_custom_preset(\n\t\tname: string,\n\t\tctx: ExtensionCommandContext,\n\t\tmode: 'delete' | 'reset',\n\t): void {\n\t\tconst result = remove_project_prompt_preset(ctx.cwd, name);\n\t\tif (!result.removed) {\n\t\t\tctx.ui.notify(\n\t\t\t\t`No project-local preset named \"${name}\" to ${mode}`,\n\t\t\t\t'warning',\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\tconst normalized = normalize_active_state(\n\t\t\tpresets,\n\t\t\tactive_base_name,\n\t\t\tactive_layers,\n\t\t);\n\t\tactive_base_name = normalized.active_base_name;\n\t\tactive_layers = normalized.active_layers;\n\t\tset_status(ctx, active_base_name, active_layers);\n\t\tpersist_state(pi, ctx, active_base_name, active_layers);\n\n\t\tconst fallback = presets[name];\n\t\tif (mode === 'reset' && fallback) {\n\t\t\tctx.ui.notify(\n\t\t\t\t`Reset \"${name}\" to ${get_prompt_source_label(fallback.source)} preset`,\n\t\t\t\t'info',\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tctx.ui.notify(\n\t\t\tresult.remaining === 0\n\t\t\t\t? `Removed \"${name}\" and deleted ${result.path}`\n\t\t\t\t: `Removed \"${name}\" from ${result.path}`,\n\t\t\t'info',\n\t\t);\n\t}\n\n\tasync function show_manager(\n\t\tctx: ExtensionCommandContext,\n\t): Promise<void> {\n\t\tconst base_presets = list_base_presets(presets);\n\t\tconst layer_presets = list_layer_presets(presets);\n\t\tif (base_presets.length === 0 && layer_presets.length === 0) {\n\t\t\tctx.ui.notify('No prompt presets available', 'warning');\n\t\t\treturn;\n\t\t}\n\n\t\tconst initial_base = active_base_name;\n\t\tconst initial_layers = new Set(active_layers);\n\t\tlet selected_base = active_base_name;\n\t\tconst enabled_layers = new Set(active_layers);\n\n\t\tconst items: SettingItem[] = [];\n\t\tconst base_ids = new Set<string>();\n\t\tconst layer_ids = new Set<string>();\n\n\t\titems.push({\n\t\t\tid: '__header_base__',\n\t\t\tlabel: `── Base presets (${base_presets.length + 1}) ──`,\n\t\t\tdescription: '',\n\t\t\tcurrentValue: '',\n\t\t});\n\t\titems.push({\n\t\t\tid: NONE_BASE_ID,\n\t\t\tlabel: '(none)',\n\t\t\tdescription: 'No active base preset',\n\t\t\tcurrentValue: UNSELECTED,\n\t\t\tvalues: [SELECTED, UNSELECTED],\n\t\t});\n\t\tbase_ids.add(NONE_BASE_ID);\n\n\t\tfor (const preset of base_presets) {\n\t\t\titems.push({\n\t\t\t\tid: preset.name,\n\t\t\t\tlabel: preset.name,\n\t\t\t\tdescription: [\n\t\t\t\t\t`${get_prompt_source_label(preset.source)} • ${preset.description ?? 'base preset'}`,\n\t\t\t\t].join('\\n'),\n\t\t\t\tcurrentValue: UNSELECTED,\n\t\t\t\tvalues: [SELECTED, UNSELECTED],\n\t\t\t});\n\t\t\tbase_ids.add(preset.name);\n\t\t}\n\n\t\titems.push({\n\t\t\tid: '__header_layers__',\n\t\t\tlabel: `── Prompt layers (${layer_presets.length}) ──`,\n\t\t\tdescription: '',\n\t\t\tcurrentValue: '',\n\t\t});\n\t\tfor (const preset of layer_presets) {\n\t\t\titems.push({\n\t\t\t\tid: preset.name,\n\t\t\t\tlabel: preset.name,\n\t\t\t\tdescription: [\n\t\t\t\t\t`${get_prompt_source_label(preset.source)} • ${preset.description ?? 'layer'}`,\n\t\t\t\t].join('\\n'),\n\t\t\t\tcurrentValue: DISABLED,\n\t\t\t\tvalues: [ENABLED, DISABLED],\n\t\t\t});\n\t\t\tlayer_ids.add(preset.name);\n\t\t}\n\n\t\tfunction sync_values() {\n\t\t\tfor (const item of items) {\n\t\t\t\tif (base_ids.has(item.id)) {\n\t\t\t\t\tconst is_selected =\n\t\t\t\t\t\t(item.id === NONE_BASE_ID && !selected_base) ||\n\t\t\t\t\t\titem.id === selected_base;\n\t\t\t\t\titem.currentValue = is_selected ? SELECTED : UNSELECTED;\n\t\t\t\t} else if (layer_ids.has(item.id)) {\n\t\t\t\t\titem.currentValue = enabled_layers.has(item.id)\n\t\t\t\t\t\t? ENABLED\n\t\t\t\t\t\t: DISABLED;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsync_values();\n\n\t\tawait show_settings_modal(ctx, {\n\t\t\ttitle: 'Prompt presets',\n\t\t\tsubtitle: () =>\n\t\t\t\t`base: ${selected_base ?? '(none)'} • ${enabled_layers.size} layer(s) enabled`,\n\t\t\titems,\n\t\t\tmax_visible: Math.min(Math.max(items.length + 4, 8), 24),\n\t\t\tenable_search: true,\n\t\t\ton_change: (id, new_value) => {\n\t\t\t\tif (id.startsWith('__header_')) return;\n\n\t\t\t\tif (base_ids.has(id)) {\n\t\t\t\t\tselected_base =\n\t\t\t\t\t\tnew_value === SELECTED && id !== NONE_BASE_ID\n\t\t\t\t\t\t\t? id\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\tsync_values();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (layer_ids.has(id)) {\n\t\t\t\t\tif (new_value === ENABLED) {\n\t\t\t\t\t\tenabled_layers.add(id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tenabled_layers.delete(id);\n\t\t\t\t\t}\n\t\t\t\t\tsync_values();\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\tif (\n\t\t\tselected_base !== initial_base ||\n\t\t\t!sets_equal(initial_layers, enabled_layers)\n\t\t) {\n\t\t\tcommit_state(ctx, selected_base, enabled_layers, {\n\t\t\t\tnotify: 'Updated prompt preset selection',\n\t\t\t});\n\t\t}\n\t}\n\n\tpi.registerFlag('preset', {\n\t\tdescription:\n\t\t\t'Activate prompt config on startup. Accepts a base preset or comma-separated preset/layer names.',\n\t\ttype: 'string',\n\t});\n\n\tconst prompt_preset_command: Parameters<\n\t\tExtensionAPI['registerCommand']\n\t>[1] = {\n\t\tdescription:\n\t\t\t'Manage prompt presets and layers. Try: /prompt-preset help, /prompt-preset export-defaults, /prompt-preset edit-global terse',\n\t\tgetArgumentCompletions: (prefix) => {\n\t\t\tconst trimmed = prefix.trim();\n\t\t\tconst parts = trimmed ? trimmed.split(/\\s+/) : [];\n\t\t\tconst base_names = list_base_presets(presets).map(\n\t\t\t\t(preset) => preset.name,\n\t\t\t);\n\t\t\tconst layer_names = list_layer_presets(presets).map(\n\t\t\t\t(preset) => preset.name,\n\t\t\t);\n\t\t\tconst all_names = [...base_names, ...layer_names];\n\n\t\t\tif (parts.length <= 1) {\n\t\t\t\tconst query = parts[0] ?? '';\n\t\t\t\tconst subcommands = [\n\t\t\t\t\t'help',\n\t\t\t\t\t'list',\n\t\t\t\t\t'show',\n\t\t\t\t\t'clear',\n\t\t\t\t\t'edit',\n\t\t\t\t\t'edit-global',\n\t\t\t\t\t'export-defaults',\n\t\t\t\t\t'delete',\n\t\t\t\t\t'reset',\n\t\t\t\t\t'reload',\n\t\t\t\t\t'base',\n\t\t\t\t\t'enable',\n\t\t\t\t\t'disable',\n\t\t\t\t\t'toggle',\n\t\t\t\t];\n\t\t\t\treturn [\n\t\t\t\t\t...subcommands\n\t\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t\t.map((item) => ({ value: item, label: item })),\n\t\t\t\t\t...all_names\n\t\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t\t.map((item) => ({ value: item, label: item })),\n\t\t\t\t];\n\t\t\t}\n\n\t\t\tconst command = parts[0];\n\t\t\tconst query = parts.slice(1).join(' ');\n\t\t\tif (command === 'base') {\n\t\t\t\treturn base_names\n\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t.map((item) => ({ value: `base ${item}`, label: item }));\n\t\t\t}\n\t\t\tif (['enable', 'disable', 'toggle'].includes(command)) {\n\t\t\t\treturn layer_names\n\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t.map((item) => ({\n\t\t\t\t\t\tvalue: `${command} ${item}`,\n\t\t\t\t\t\tlabel: item,\n\t\t\t\t\t}));\n\t\t\t}\n\t\t\tif (command === 'edit' || command === 'edit-global') {\n\t\t\t\treturn all_names\n\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t.map((item) => ({\n\t\t\t\t\t\tvalue: `${command} ${item}`,\n\t\t\t\t\t\tlabel: item,\n\t\t\t\t\t}));\n\t\t\t}\n\t\t\tif (['delete', 'reset'].includes(command)) {\n\t\t\t\treturn all_names\n\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t.map((item) => ({\n\t\t\t\t\t\tvalue: `${command} ${item}`,\n\t\t\t\t\t\tlabel: item,\n\t\t\t\t\t}));\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\thandler: async (args, ctx) => {\n\t\t\tconst trimmed = args.trim();\n\t\t\tif (!trimmed) {\n\t\t\t\tif (ctx.hasUI) {\n\t\t\t\t\tawait show_manager(ctx);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\tformat_summary(active_base_name, active_layers, presets),\n\t\t\t\t\t'info',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst [first, ...rest] = trimmed.split(/\\s+/);\n\t\t\tconst arg = rest.join(' ').trim();\n\n\t\t\tswitch (first) {\n\t\t\t\tcase 'help':\n\t\t\t\t\tctx.ui.notify(format_prompt_preset_help(), 'info');\n\t\t\t\t\treturn;\n\t\t\t\tcase 'list':\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\tformat_summary(active_base_name, active_layers, presets),\n\t\t\t\t\t\t'info',\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'show':\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\tformat_active_details(\n\t\t\t\t\t\t\tactive_base_name,\n\t\t\t\t\t\t\tactive_layers,\n\t\t\t\t\t\t\tpresets,\n\t\t\t\t\t\t),\n\t\t\t\t\t\t'info',\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'clear':\n\t\t\t\t\tcommit_state(ctx, undefined, new Set(), {\n\t\t\t\t\t\tnotify: 'Cleared base preset and prompt layers',\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\tcase 'reload': {\n\t\t\t\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\t\t\t\tconst normalized = normalize_active_state(\n\t\t\t\t\t\tpresets,\n\t\t\t\t\t\tactive_base_name,\n\t\t\t\t\t\tactive_layers,\n\t\t\t\t\t);\n\t\t\t\t\tactive_base_name = normalized.active_base_name;\n\t\t\t\t\tactive_layers = normalized.active_layers;\n\t\t\t\t\tset_status(ctx, active_base_name, active_layers);\n\t\t\t\t\tctx.ui.notify('Reloaded prompt presets', 'info');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcase 'base':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset base <name> (alias: /preset)',\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\tactivate_base(arg, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'enable':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset enable <layer> (alias: /preset)',\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tset_layer_enabled(arg, true, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'disable':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset disable <layer> (alias: /preset)',\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tset_layer_enabled(arg, false, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'toggle':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset toggle <layer> (alias: /preset)',\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\ttoggle_layer(arg, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'edit': {\n\t\t\t\t\tlet scope: 'project' | 'global' = 'project';\n\t\t\t\t\tlet name = arg;\n\t\t\t\t\tif (arg.startsWith('--global ')) {\n\t\t\t\t\t\tscope = 'global';\n\t\t\t\t\t\tname = arg.slice('--global '.length).trim();\n\t\t\t\t\t} else if (arg.startsWith('--project ')) {\n\t\t\t\t\t\tname = arg.slice('--project '.length).trim();\n\t\t\t\t\t}\n\t\t\t\t\tif (!name) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset edit [--global|--project] <name> (alias: /preset)',\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\tawait edit_preset(name, ctx, scope);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcase 'edit-global':\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: /prompt-preset edit-global <name> (alias: /preset)',\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\tawait edit_preset(arg, ctx, 'global');\n\t\t\t\t\treturn;\n\t\t\t\tcase 'export-defaults': {\n\t\t\t\t\tconst scope = arg || 'global';\n\t\t\t\t\tif (scope !== 'global' && scope !== 'project') {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset export-defaults [global|project] (alias: /preset)',\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\texport_default_presets(ctx, scope);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcase 'delete':\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: /prompt-preset delete <name> (alias: /preset)',\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\tremove_custom_preset(arg, ctx, 'delete');\n\t\t\t\t\treturn;\n\t\t\t\tcase 'reset':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset reset <name> (alias: /preset)',\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\tremove_custom_preset(arg, ctx, 'reset');\n\t\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (is_subcommand(first)) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Unsupported preset command: ${first}`,\n\t\t\t\t\t'warning',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst preset = presets[trimmed];\n\t\t\tif (!preset) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Unknown preset or layer: ${trimmed}. Try /prompt-preset help.`,\n\t\t\t\t\t'warning',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (preset.kind === 'base') {\n\t\t\t\tactivate_base(preset.name, ctx);\n\t\t\t} else {\n\t\t\t\ttoggle_layer(preset.name, ctx);\n\t\t\t}\n\t\t},\n\t};\n\n\tfor (const command_name of [\n\t\t'prompt-preset',\n\t\t'prompt-presets',\n\t\t'preset',\n\t]) {\n\t\tpi.registerCommand(command_name, prompt_preset_command);\n\t}\n\n\tpi.on('session_start', async (_event, ctx) => {\n\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\tactive_base_name = undefined;\n\t\tactive_layers = new Set();\n\n\t\tconst preset_flag = pi.getFlag('preset');\n\t\tif (typeof preset_flag === 'string' && preset_flag.trim()) {\n\t\t\tfor (const name of parse_preset_flag(preset_flag)) {\n\t\t\t\tconst preset = presets[name];\n\t\t\t\tif (!preset) continue;\n\t\t\t\tif (preset.kind === 'base') {\n\t\t\t\t\tactive_base_name = name;\n\t\t\t\t} else {\n\t\t\t\t\tactive_layers.add(name);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst normalized = normalize_active_state(\n\t\t\t\tpresets,\n\t\t\t\tactive_base_name,\n\t\t\t\tactive_layers,\n\t\t\t);\n\t\t\tactive_base_name = normalized.active_base_name;\n\t\t\tactive_layers = normalized.active_layers;\n\t\t\tset_status(ctx, active_base_name, active_layers);\n\t\t\treturn;\n\t\t}\n\n\t\tconst restored = get_last_preset_state(ctx) ??\n\t\t\tload_persisted_prompt_state(ctx.cwd) ?? {\n\t\t\t\tbase_name: DEFAULT_BASE_PROMPT_PRESET_NAME,\n\t\t\t\tlayer_names: [],\n\t\t\t};\n\t\tactive_base_name = restored.base_name ?? undefined;\n\t\tactive_layers = new Set(restored.layer_names ?? []);\n\t\tconst normalized = normalize_active_state(\n\t\t\tpresets,\n\t\t\tactive_base_name,\n\t\t\tactive_layers,\n\t\t);\n\t\tactive_base_name = normalized.active_base_name;\n\t\tactive_layers = normalized.active_layers;\n\t\tset_status(ctx, active_base_name, active_layers);\n\t});\n\n\tpi.on('before_agent_start', async (event) => {\n\t\tconst blocks: string[] = [];\n\t\tconst base = get_base(active_base_name);\n\t\tif (base?.instructions.trim()) {\n\t\t\tblocks.push(\n\t\t\t\t`## Active Base Prompt: ${base.name}\\n${base.instructions.trim()}`,\n\t\t\t);\n\t\t}\n\n\t\tconst layer_blocks = [...active_layers]\n\t\t\t.sort()\n\t\t\t.map((name) => presets[name])\n\t\t\t.filter((preset): preset is LoadedPromptPreset =>\n\t\t\t\tBoolean(preset?.instructions.trim()),\n\t\t\t)\n\t\t\t.map(\n\t\t\t\t(preset) =>\n\t\t\t\t\t`### ${preset.name}\\n${preset.instructions.trim()}`,\n\t\t\t);\n\t\tif (layer_blocks.length > 0) {\n\t\t\tblocks.push(\n\t\t\t\t`## Active Prompt Layers\\n\\n${layer_blocks.join('\\n\\n')}`,\n\t\t\t);\n\t\t}\n\n\t\tif (blocks.length === 0) return;\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n\\n${blocks.join('\\n\\n')}`,\n\t\t};\n\t});\n\n\tpi.on('session_shutdown', async (_event, ctx) => {\n\t\tctx.ui.setStatus('preset', undefined);\n\t\tctx.ui.setFooter(undefined);\n\t});\n}\n","// Session name — AI-powered session naming\n// Adapted from Thomas Lopes' pi dotfiles\n\nimport { complete, type Message } from '@mariozechner/pi-ai';\nimport type {\n\tExtensionAPI,\n\tSessionEntry,\n} from '@mariozechner/pi-coding-agent';\nimport {\n\tBorderedLoader,\n\tconvertToLlm,\n\tserializeConversation,\n} from '@mariozechner/pi-coding-agent';\n\nconst SYSTEM_PROMPT = `You are a session naming assistant. Given a conversation history, generate a short, descriptive session name (2-5 words) that captures the main topic or task.\n\nGuidelines:\n- Be concise but specific\n- Use kebab-case or natural language\n- Focus on the core task/question\n- Avoid generic names like \"discussion\" or \"conversation\"\n- No quotes, no punctuation at the end\n\nExamples:\n- \"fix auth bug\" -> \"fix-auth-bug\" or \"authentication fix\"\n- \"how do I deploy to vercel\" -> \"vercel deployment\"\n- \"explain react hooks\" -> \"react hooks explanation\"\n- \"optimize database queries\" -> \"db query optimization\"\n\nOutput ONLY the session name, nothing else.`;\n\nconst AUTO_NAME_THRESHOLD = 1;\nconst MAX_CHARS = 4000;\nconst MAX_NAME_LEN = 50;\n\nfunction clean_name(value: string): string {\n\treturn value\n\t\t.replace(/^[\"']|[\"']$/g, '')\n\t\t.replace(/\\n/g, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim()\n\t\t.slice(0, MAX_NAME_LEN);\n}\n\nfunction truncate_conversation(value: string): string {\n\treturn value.length > MAX_CHARS\n\t\t? value.slice(0, MAX_CHARS) + '\\n...'\n\t\t: value;\n}\n\nasync function generate_session_name(\n\tctx: {\n\t\tmodelRegistry: {\n\t\t\tgetApiKeyAndHeaders: (\n\t\t\t\tmodel: NonNullable<\n\t\t\t\t\tParameters<\n\t\t\t\t\t\tParameters<ExtensionAPI['registerCommand']>[1]['handler']\n\t\t\t\t\t>[1]['model']\n\t\t\t\t>,\n\t\t\t) => Promise<any>;\n\t\t};\n\t},\n\tmodel: NonNullable<\n\t\tParameters<\n\t\t\tParameters<ExtensionAPI['registerCommand']>[1]['handler']\n\t\t>[1]['model']\n\t>,\n\tconversation_text: string,\n\tsignal?: AbortSignal,\n): Promise<string | null> {\n\tconst auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);\n\tif (!auth.ok || !auth.apiKey) {\n\t\tthrow new Error(\n\t\t\tauth.ok ? `No API key for ${model.provider}` : auth.error,\n\t\t);\n\t}\n\n\tconst user_message: Message = {\n\t\trole: 'user',\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: 'text',\n\t\t\t\ttext: `## Conversation History\\n\\n${truncate_conversation(conversation_text)}\\n\\nGenerate a concise session name for this conversation.`,\n\t\t\t},\n\t\t],\n\t\ttimestamp: Date.now(),\n\t};\n\n\tconst response = await complete(\n\t\tmodel,\n\t\t{ systemPrompt: SYSTEM_PROMPT, messages: [user_message] },\n\t\t{ apiKey: auth.apiKey, headers: auth.headers, signal },\n\t);\n\n\tif (response.stopReason === 'aborted') {\n\t\treturn null;\n\t}\n\n\treturn clean_name(\n\t\tresponse.content\n\t\t\t.filter(\n\t\t\t\t(c): c is { type: 'text'; text: string } => c.type === 'text',\n\t\t\t)\n\t\t\t.map((c) => c.text.trim())\n\t\t\t.join(' '),\n\t);\n}\n\nexport default async function session_name(pi: ExtensionAPI) {\n\tlet auto_named_attempted = false;\n\n\tpi.on('agent_end', async (_event, ctx) => {\n\t\tif (!ctx.hasUI || !ctx.model) return;\n\t\tif (pi.getSessionName() || auto_named_attempted) return;\n\n\t\tconst branch = ctx.sessionManager.getBranch();\n\t\tconst user_messages = branch.filter(\n\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\tentry.type === 'message' && entry.message.role === 'user',\n\t\t);\n\t\tif (user_messages.length < AUTO_NAME_THRESHOLD) return;\n\n\t\tauto_named_attempted = true;\n\t\tconst messages = branch\n\t\t\t.filter(\n\t\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\t\tentry.type === 'message',\n\t\t\t)\n\t\t\t.map((entry) => entry.message);\n\t\tif (messages.length === 0) return;\n\n\t\tconst conversation_text = serializeConversation(\n\t\t\tconvertToLlm(messages),\n\t\t);\n\n\t\tgenerate_session_name(ctx, ctx.model, conversation_text)\n\t\t\t.then((name) => {\n\t\t\t\tif (!name) return;\n\t\t\t\tpi.setSessionName(name);\n\t\t\t\tctx.ui.notify(`Auto-named: ${name}`, 'info');\n\t\t\t})\n\t\t\t.catch((err) => {\n\t\t\t\tconsole.error('Auto-naming failed:', err);\n\t\t\t});\n\t});\n\n\tpi.on('session_start', async () => {\n\t\tauto_named_attempted = false;\n\t});\n\n\tpi.registerCommand('session-name', {\n\t\tdescription:\n\t\t\t'Set, show, or auto-generate the current session name',\n\t\thandler: async (args, ctx) => {\n\t\t\tconst trimmed = args.trim();\n\n\t\t\tif (!trimmed) {\n\t\t\t\tconst current = pi.getSessionName();\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\tcurrent ? `Session: ${current}` : 'No session name set',\n\t\t\t\t\t'info',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (trimmed === '--auto' || trimmed === '-a') {\n\t\t\t\tif (!ctx.hasUI || !ctx.model) {\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t'Auto-naming requires interactive mode and a selected model',\n\t\t\t\t\t\t'error',\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst branch = ctx.sessionManager.getBranch();\n\t\t\t\tconst messages = branch\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\t\t\t\tentry.type === 'message',\n\t\t\t\t\t)\n\t\t\t\t\t.map((entry) => entry.message);\n\t\t\t\tif (messages.length === 0) {\n\t\t\t\t\tctx.ui.notify('No conversation to analyze', 'error');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst conversation_text = serializeConversation(\n\t\t\t\t\tconvertToLlm(messages),\n\t\t\t\t);\n\n\t\t\t\tconst result = await ctx.ui.custom<string | null>(\n\t\t\t\t\t(tui, theme, _kb, done) => {\n\t\t\t\t\t\tconst loader = new BorderedLoader(\n\t\t\t\t\t\t\ttui,\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\t'Generating session name...',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tloader.onAbort = () => done(null);\n\n\t\t\t\t\t\tgenerate_session_name(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\tctx.model!,\n\t\t\t\t\t\t\tconversation_text,\n\t\t\t\t\t\t\tloader.signal,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.then(done)\n\t\t\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\t\t\tconsole.error('Auto-naming failed:', err);\n\t\t\t\t\t\t\t\tdone(null);\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn loader;\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (result === null) {\n\t\t\t\t\tctx.ui.notify('Auto-naming cancelled', 'info');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!result) {\n\t\t\t\t\tctx.ui.notify('Failed to generate name', 'error');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tpi.setSessionName(result);\n\t\t\t\tctx.ui.notify(`Session named: ${result}`, 'info');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tpi.setSessionName(clean_name(trimmed));\n\t\t\tctx.ui.notify(`Session named: ${clean_name(trimmed)}`, 'info');\n\t\t},\n\t});\n}\n","// Composable programmatic API for my-pi\n// Extension loading patterns inspired by pi-vs-claude-code\n\nimport type { Api, Model } from '@mariozechner/pi-ai';\nimport {\n\tInteractiveMode,\n\tSessionManager,\n\tcreateAgentSessionFromServices,\n\tcreateAgentSessionRuntime,\n\tcreateAgentSessionServices,\n\tgetAgentDir,\n\trunPrintMode,\n\trunRpcMode,\n\ttype ExtensionFactory,\n\ttype LoadExtensionsResult,\n} from '@mariozechner/pi-coding-agent';\nimport confirm_destructive_extension from '@spences10/pi-confirm-destructive';\nimport lsp_extension from '@spences10/pi-lsp';\nimport mcp_extension from '@spences10/pi-mcp';\nimport nopeek_extension from '@spences10/pi-nopeek';\nimport omnisearch_extension from '@spences10/pi-omnisearch';\nimport { apply_project_trust_untrusted_defaults } from '@spences10/pi-project-trust';\nimport recall_extension from '@spences10/pi-recall';\nimport filter_output_extension from '@spences10/pi-redact';\nimport skills_extension, {\n\tcreate_skills_manager,\n} from '@spences10/pi-skills';\nimport sqlite_tools_extension from '@spences10/pi-sqlite-tools';\nimport team_mode_extension from '@spences10/pi-team-mode';\nimport { create_telemetry_extension } from '@spences10/pi-telemetry';\nimport { createRequire } from 'node:module';\nimport { dirname, isAbsolute, relative, resolve } from 'node:path';\nimport hooks_resolution_extension from './extensions/hooks-resolution/index.js';\nimport {\n\tBUILTIN_EXTENSIONS,\n\tis_builtin_extension_active,\n\tload_builtin_extensions_config,\n\ttype BuiltinExtensionKey,\n} from './extensions/manager/config.js';\nimport { create_extensions_extension } from './extensions/manager/index.js';\nimport prompt_presets_extension from './extensions/prompt-presets/index.js';\nimport session_name_extension from './extensions/session-name/index.js';\n\nexport type MyPiRuntimeMode =\n\t| 'interactive'\n\t| 'print'\n\t| 'json'\n\t| 'rpc';\n\nexport interface CreateMyPiOptions {\n\tcwd?: string;\n\tagent_dir?: string;\n\textensions?: string[];\n\textensionFactories?: ExtensionFactory[];\n\truntime_mode?: MyPiRuntimeMode;\n\tmcp?: boolean;\n\tskills?: boolean;\n\tfilter_output?: boolean;\n\trecall?: boolean;\n\tnopeek?: boolean;\n\tomnisearch?: boolean;\n\tsqlite_tools?: boolean;\n\tprompt_presets?: boolean;\n\tlsp?: boolean;\n\tsession_name?: boolean;\n\tconfirm_destructive?: boolean;\n\thooks_resolution?: boolean;\n\tteam_mode?: boolean;\n\ttelemetry?: boolean;\n\ttelemetry_db_path?: string;\n\tmodel?: string;\n\tselected_tools?: string[];\n\tselected_skills?: string[];\n\tsession_dir?: string;\n\tsystem_prompt?: string;\n\tappend_system_prompt?: string;\n\tuntrusted_repo?: boolean;\n}\n\nconst BUILTIN_EXTENSION_FACTORIES: Record<\n\tBuiltinExtensionKey,\n\tExtensionFactory\n> = {\n\tmcp: mcp_extension,\n\tskills: skills_extension,\n\t'filter-output': filter_output_extension,\n\trecall: recall_extension,\n\tnopeek: nopeek_extension,\n\tomnisearch: omnisearch_extension,\n\t'sqlite-tools': sqlite_tools_extension,\n\t'prompt-presets': prompt_presets_extension,\n\tlsp: lsp_extension,\n\t'session-name': session_name_extension,\n\t'confirm-destructive': confirm_destructive_extension,\n\t'hooks-resolution': hooks_resolution_extension,\n\t'team-mode': team_mode_extension,\n};\n\nconst require = createRequire(import.meta.url);\nconst PACKAGE_THEME_DIR = resolve(\n\tdirname(require.resolve('@spences10/pi-themes/package.json')),\n\t'themes',\n);\nconst PI_AGENT_DIR_ENV = 'PI_CODING_AGENT_DIR';\n\nconst UNTRUSTED_CHILD_ENV_DEFAULTS: Record<string, string> = {\n\tMY_PI_CHILD_ENV_ALLOWLIST: '',\n\tMY_PI_MCP_ENV_ALLOWLIST: '',\n\tMY_PI_LSP_ENV_ALLOWLIST: '',\n\tMY_PI_HOOKS_ENV_ALLOWLIST: '',\n\tMY_PI_TEAM_MODE_ENV_ALLOWLIST: '',\n};\n\nexport function apply_untrusted_repo_defaults(\n\tenv: NodeJS.ProcessEnv = process.env,\n): string[] {\n\tconst applied = apply_project_trust_untrusted_defaults(env);\n\tfor (const [key, value] of Object.entries(\n\t\tUNTRUSTED_CHILD_ENV_DEFAULTS,\n\t)) {\n\t\tif (env[key] !== undefined) continue;\n\t\tenv[key] = value;\n\t\tapplied.push(key);\n\t}\n\treturn applied;\n}\n\nfunction is_resource_enabled(value: string | undefined): boolean {\n\tconst normalized = value?.trim().toLowerCase();\n\tif (!normalized) return true;\n\tif (['0', 'false', 'no', 'skip', 'disable'].includes(normalized)) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport function is_project_local_skill_path(\n\tcwd: string,\n\tfile_path: string | undefined,\n): boolean {\n\tif (!file_path) return false;\n\tconst absolute = resolve(cwd, file_path);\n\tconst relative_path = relative(cwd, absolute);\n\tif (\n\t\t!relative_path ||\n\t\trelative_path.startsWith('..') ||\n\t\tisAbsolute(relative_path)\n\t) {\n\t\treturn false;\n\t}\n\tconst parts = relative_path.split(/[\\\\/]+/);\n\treturn parts.some(\n\t\t(part, index) =>\n\t\t\t(part === '.pi' || part === '.claude') &&\n\t\t\tparts[index + 1] === 'skills',\n\t);\n}\n\nfunction resolve_agent_dir(cwd: string, agent_dir?: string): string {\n\treturn agent_dir ? resolve(cwd, agent_dir) : getAgentDir();\n}\n\nconst NON_INTERACTIVE_UI_ONLY_BUILTINS: BuiltinExtensionKey[] = [\n\t'session-name',\n];\n\ninterface ModelRegistryLike {\n\tgetAll(): Model<Api>[];\n}\n\nexport function resolve_model_reference(\n\tmodel_reference: string | undefined,\n\tmodel_registry: ModelRegistryLike,\n): Model<Api> | undefined {\n\tif (!model_reference) return undefined;\n\tconst models = model_registry.getAll();\n\tconst lower_reference = model_reference.toLowerCase();\n\tconst slash_index = model_reference.indexOf('/');\n\n\tif (slash_index !== -1) {\n\t\tconst maybe_provider = model_reference.slice(0, slash_index);\n\t\tconst model_id = model_reference.slice(slash_index + 1);\n\t\tconst provider = models.find(\n\t\t\t(model) =>\n\t\t\t\tmodel.provider.toLowerCase() === maybe_provider.toLowerCase(),\n\t\t)?.provider;\n\n\t\tif (provider) {\n\t\t\tconst provider_match = models.find(\n\t\t\t\t(model) =>\n\t\t\t\t\tmodel.provider === provider &&\n\t\t\t\t\tmodel.id.toLowerCase() === model_id.toLowerCase(),\n\t\t\t);\n\t\t\tif (provider_match) return provider_match;\n\t\t}\n\t}\n\n\treturn models.find((model) => {\n\t\tconst id = model.id.toLowerCase();\n\t\tconst full_id = `${model.provider}/${model.id}`.toLowerCase();\n\t\treturn id === lower_reference || full_id === lower_reference;\n\t});\n}\n\nexport function get_force_disabled_builtins(\n\toptions: Pick<\n\t\tCreateMyPiOptions,\n\t\t| 'runtime_mode'\n\t\t| 'mcp'\n\t\t| 'skills'\n\t\t| 'filter_output'\n\t\t| 'recall'\n\t\t| 'nopeek'\n\t\t| 'omnisearch'\n\t\t| 'sqlite_tools'\n\t\t| 'prompt_presets'\n\t\t| 'lsp'\n\t\t| 'session_name'\n\t\t| 'confirm_destructive'\n\t\t| 'hooks_resolution'\n\t\t| 'team_mode'\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.filter_output) force_disabled.add('filter-output');\n\tif (!options.recall) force_disabled.add('recall');\n\tif (!options.nopeek) force_disabled.add('nopeek');\n\tif (!options.omnisearch) force_disabled.add('omnisearch');\n\tif (!options.sqlite_tools) force_disabled.add('sqlite-tools');\n\tif (!options.prompt_presets) force_disabled.add('prompt-presets');\n\tif (!options.lsp) force_disabled.add('lsp');\n\tif (!options.session_name) force_disabled.add('session-name');\n\tif (!options.confirm_destructive)\n\t\tforce_disabled.add('confirm-destructive');\n\tif (!options.hooks_resolution)\n\t\tforce_disabled.add('hooks-resolution');\n\tif (!options.team_mode) force_disabled.add('team-mode');\n\tif (\n\t\toptions.runtime_mode &&\n\t\toptions.runtime_mode !== 'interactive'\n\t) {\n\t\tfor (const key of NON_INTERACTIVE_UI_ONLY_BUILTINS) {\n\t\t\tforce_disabled.add(key);\n\t\t}\n\t}\n\treturn force_disabled;\n}\n\nfunction create_builtin_extension_factory(\n\tkey: BuiltinExtensionKey,\n\textension: ExtensionFactory,\n\tforce_disabled: ReadonlySet<BuiltinExtensionKey>,\n): ExtensionFactory {\n\treturn async (pi) => {\n\t\tconst config = load_builtin_extensions_config();\n\t\tif (!is_builtin_extension_active(config, key, force_disabled)) {\n\t\t\treturn;\n\t\t}\n\t\tawait extension(pi);\n\t};\n}\n\nfunction create_extensions_override(\n\tmanaged_inline_paths: string[],\n): (base: LoadExtensionsResult) => LoadExtensionsResult {\n\tconst managed_paths = new Set(managed_inline_paths);\n\treturn (base) => {\n\t\tconst managed = new Map(\n\t\t\tbase.extensions.map((extension) => [extension.path, extension]),\n\t\t);\n\t\tconst ordered_managed = managed_inline_paths\n\t\t\t.map((path) => managed.get(path))\n\t\t\t.filter(\n\t\t\t\t(\n\t\t\t\t\textension,\n\t\t\t\t): extension is LoadExtensionsResult['extensions'][number] =>\n\t\t\t\t\tBoolean(extension),\n\t\t\t);\n\t\tconst others = base.extensions.filter(\n\t\t\t(extension) => !managed_paths.has(extension.path),\n\t\t);\n\t\treturn {\n\t\t\t...base,\n\t\t\textensions: [...ordered_managed, ...others],\n\t\t};\n\t};\n}\n\nexport async function create_my_pi(options: CreateMyPiOptions = {}) {\n\tconst {\n\t\tcwd = process.cwd(),\n\t\tagent_dir,\n\t\textensions = [],\n\t\textensionFactories: user_factories = [],\n\t\truntime_mode = 'interactive',\n\t\tmcp = true,\n\t\tskills = true,\n\t\tfilter_output = true,\n\t\trecall = true,\n\t\tnopeek = true,\n\t\tomnisearch = true,\n\t\tsqlite_tools = true,\n\t\tprompt_presets = true,\n\t\tlsp = true,\n\t\tsession_name = true,\n\t\tconfirm_destructive = true,\n\t\thooks_resolution = true,\n\t\tteam_mode = true,\n\t\ttelemetry,\n\t\ttelemetry_db_path,\n\t\tmodel,\n\t\tselected_tools,\n\t\tselected_skills,\n\t\tsession_dir,\n\t\tsystem_prompt,\n\t\tappend_system_prompt,\n\t\tuntrusted_repo = false,\n\t} = options;\n\n\tif (untrusted_repo) {\n\t\tapply_untrusted_repo_defaults();\n\t}\n\n\tconst effective_agent_dir = resolve_agent_dir(cwd, agent_dir);\n\tif (agent_dir) {\n\t\tprocess.env[PI_AGENT_DIR_ENV] = effective_agent_dir;\n\t}\n\n\tconst resolved_extensions = extensions.map((p) => resolve(cwd, p));\n\tconst force_disabled = get_force_disabled_builtins({\n\t\truntime_mode,\n\t\tmcp,\n\t\tskills,\n\t\tfilter_output,\n\t\trecall,\n\t\tnopeek,\n\t\tomnisearch,\n\t\tsqlite_tools,\n\t\tprompt_presets,\n\t\tlsp,\n\t\tsession_name,\n\t\tconfirm_destructive,\n\t\thooks_resolution,\n\t\tteam_mode,\n\t});\n\tconst managed_extension_factories: ExtensionFactory[] = [\n\t\tcreate_telemetry_extension({\n\t\t\tenabled: telemetry,\n\t\t\tdb_path: telemetry_db_path,\n\t\t\tcwd,\n\t\t}),\n\t\tcreate_extensions_extension({ force_disabled }),\n\t\t...BUILTIN_EXTENSIONS.map((extension) =>\n\t\t\tcreate_builtin_extension_factory(\n\t\t\t\textension.key,\n\t\t\t\tBUILTIN_EXTENSION_FACTORIES[extension.key],\n\t\t\t\tforce_disabled,\n\t\t\t),\n\t\t),\n\t];\n\tconst managed_inline_paths = managed_extension_factories.map(\n\t\t(_, index) => `<inline:${index + 1}>`,\n\t);\n\n\tconst create_runtime = async ({\n\t\tcwd: runtime_cwd,\n\t\tsessionManager,\n\t\tsessionStartEvent,\n\t}: {\n\t\tcwd: string;\n\t\tsessionManager: SessionManager;\n\t\tsessionStartEvent?: unknown;\n\t}) => {\n\t\tconst services = await createAgentSessionServices({\n\t\t\tcwd: runtime_cwd,\n\t\t\tagentDir: effective_agent_dir,\n\t\t\tresourceLoaderOptions: {\n\t\t\t\t...(system_prompt !== undefined\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tsystemPromptOverride: () => system_prompt,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\t...(append_system_prompt !== undefined\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tappendSystemPromptOverride: (base: string[]) => [\n\t\t\t\t\t\t\t\t...base,\n\t\t\t\t\t\t\t\tappend_system_prompt,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\tadditionalExtensionPaths: [...resolved_extensions],\n\t\t\t\t...(runtime_mode === 'interactive'\n\t\t\t\t\t? { additionalThemePaths: [PACKAGE_THEME_DIR] }\n\t\t\t\t\t: {}),\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 include_project_skills = is_resource_enabled(\n\t\t\t\t\t\tprocess.env.MY_PI_PROJECT_SKILLS,\n\t\t\t\t\t);\n\t\t\t\t\tconst skills_manager = create_skills_manager();\n\t\t\t\t\tconst selected_skill_names = selected_skills?.length\n\t\t\t\t\t\t? new Set(selected_skills)\n\t\t\t\t\t\t: undefined;\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\tif (\n\t\t\t\t\t\t\t\t!include_project_skills &&\n\t\t\t\t\t\t\t\tis_project_local_skill_path(\n\t\t\t\t\t\t\t\t\truntime_cwd,\n\t\t\t\t\t\t\t\t\tskill.filePath,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tselected_skill_names &&\n\t\t\t\t\t\t\t\t!selected_skill_names.has(skill.name)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn skills_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\tconst requested_model = resolve_model_reference(\n\t\t\tmodel,\n\t\t\tservices.modelRegistry,\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\t...(requested_model ? { model: requested_model } : {}),\n\t\t\t\t...(selected_tools?.length ? { tools: selected_tools } : {}),\n\t\t\t})),\n\t\t\tservices,\n\t\t\tdiagnostics: services.diagnostics,\n\t\t};\n\t};\n\n\treturn createAgentSessionRuntime(create_runtime, {\n\t\tcwd,\n\t\tagentDir: effective_agent_dir,\n\t\tsessionManager: SessionManager.create(\n\t\t\tcwd,\n\t\t\tsession_dir ? resolve(cwd, session_dir) : undefined,\n\t\t),\n\t});\n}\n\nexport { InteractiveMode, runPrintMode, runRpcMode };\n\nexport type {\n\tAgentSessionRuntime,\n\tExtensionFactory,\n\tInteractiveModeOptions,\n\tPrintModeOptions,\n} from '@mariozechner/pi-coding-agent';\n"],"mappings":"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"}
1
+ {"version":3,"file":"api-CJN_JYzx.js","names":["create_child_process_env","create_shared_child_process_env","HOOKS_CONFIG_ENV","create_child_process_env","ENABLED","DISABLED","sets_equal","prompt_presets_extension","session_name_extension","hooks_resolution_extension"],"sources":["../src/extensions/hooks-resolution/env.ts","../src/extensions/hooks-resolution/trust.ts","../src/extensions/hooks-resolution/index.ts","../src/extensions/manager/config.ts","../src/extensions/manager/index.ts","../src/extensions/prompt-presets/index.ts","../src/extensions/session-name/index.ts","../src/api.ts"],"sourcesContent":["import { create_child_process_env as create_shared_child_process_env } from '@spences10/pi-child-env';\n\nexport function create_child_process_env(\n\texplicit_env: Record<string, string> = {},\n\tsource_env: NodeJS.ProcessEnv = process.env,\n): NodeJS.ProcessEnv {\n\treturn create_shared_child_process_env({\n\t\tprofile: 'hooks',\n\t\texplicit_env,\n\t\tsource_env,\n\t});\n}\n","import {\n\tis_project_subject_trusted,\n\tread_project_trust_store,\n\ttrust_project_subject,\n\ttype ProjectTrustSubject,\n} from '@spences10/pi-project-trust';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nconst HOOKS_CONFIG_ENV = 'MY_PI_HOOKS_CONFIG';\n\nexport function default_hooks_trust_store_path(): string {\n\treturn join(homedir(), '.pi', 'agent', 'trusted-hooks.json');\n}\n\nexport function create_hooks_config_trust_subject(\n\tproject_dir: string,\n\thash: string,\n): ProjectTrustSubject {\n\treturn {\n\t\tkind: 'hooks-config',\n\t\tid: project_dir,\n\t\tstore_key: project_dir,\n\t\thash,\n\t\tenv_key: HOOKS_CONFIG_ENV,\n\t\tprompt_title:\n\t\t\t'Project hook config can execute shell commands after tool use. Trust these hooks?',\n\t};\n}\n\nexport function is_hooks_config_trusted(\n\tproject_dir: string,\n\thash: string,\n\ttrust_store_path = default_hooks_trust_store_path(),\n): boolean {\n\tconst subject = create_hooks_config_trust_subject(\n\t\tproject_dir,\n\t\thash,\n\t);\n\tif (is_project_subject_trusted(subject, trust_store_path))\n\t\treturn true;\n\n\tconst legacy_entry = read_project_trust_store(trust_store_path)[\n\t\tproject_dir\n\t] as { project_dir?: unknown; hash?: unknown } | undefined;\n\treturn (\n\t\tlegacy_entry?.project_dir === project_dir &&\n\t\tlegacy_entry.hash === hash\n\t);\n}\n\nexport function trust_hooks_config(\n\tproject_dir: string,\n\thash: string,\n\ttrust_store_path = default_hooks_trust_store_path(),\n): void {\n\ttrust_project_subject(\n\t\tcreate_hooks_config_trust_subject(project_dir, hash),\n\t\ttrust_store_path,\n\t);\n}\n","// Hooks resolution — Claude Code style hook compatibility\n\nimport type {\n\tExtensionAPI,\n\tExtensionContext,\n\tExtensionFactory,\n\tToolResultEvent,\n} from '@mariozechner/pi-coding-agent';\nimport {\n\tresolve_project_trust,\n\ttype ProjectTrustSubject,\n} from '@spences10/pi-project-trust';\nimport { spawn } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport { create_child_process_env } from './env.js';\nimport {\n\tdefault_hooks_trust_store_path,\n\tis_hooks_config_trusted,\n} from './trust.js';\n\nconst HOOK_TIMEOUT_MS = 10 * 60 * 1000;\nconst HOOKS_CONFIG_ENV = 'MY_PI_HOOKS_CONFIG';\n\ntype JsonValue =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| JsonValue[]\n\t| { [key: string]: JsonValue };\n\nexport type HookEventName = 'PostToolUse' | 'PostToolUseFailure';\n\nexport interface ResolvedCommandHook {\n\tevent_name: HookEventName;\n\tmatcher?: RegExp;\n\tmatcher_text?: string;\n\tcommand: string;\n\tsource: string;\n}\n\nexport interface HookState {\n\tproject_dir: string;\n\thooks: ResolvedCommandHook[];\n}\n\nexport interface HooksConfigInfo {\n\tproject_dir: string;\n\thash: string;\n\tsources: string[];\n\thooks: Array<{\n\t\tevent_name: HookEventName;\n\t\tmatcher_text?: string;\n\t\tcommand: string;\n\t\tsource: string;\n\t}>;\n}\n\nexport interface CommandRunResult {\n\tcode: number;\n\tstdout: string;\n\tstderr: string;\n\telapsed_ms: number;\n\ttimed_out: boolean;\n}\n\nexport function is_file(path: string): boolean {\n\ttry {\n\t\treturn statSync(path).isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport function as_record(\n\tvalue: unknown,\n): Record<string, unknown> | undefined {\n\tif (typeof value !== 'object' || value === null) return undefined;\n\treturn value as Record<string, unknown>;\n}\n\nexport function walk_up_directories(\n\tstart_dir: string,\n\tstop_dir?: string,\n): string[] {\n\tconst directories: string[] = [];\n\tconst has_stop_dir = stop_dir !== undefined;\n\tlet current = resolve(start_dir);\n\tlet parent = dirname(current);\n\tlet reached_stop_dir = has_stop_dir && current === stop_dir;\n\tlet reached_filesystem_root = parent === current;\n\n\tdirectories.push(current);\n\twhile (!reached_stop_dir && !reached_filesystem_root) {\n\t\tcurrent = parent;\n\t\tparent = dirname(current);\n\t\treached_stop_dir = has_stop_dir && current === stop_dir;\n\t\treached_filesystem_root = parent === current;\n\t\tdirectories.push(current);\n\t}\n\n\treturn directories;\n}\n\nexport function find_nearest_git_root(\n\tstart_dir: string,\n): string | undefined {\n\tfor (const directory of walk_up_directories(start_dir)) {\n\t\tif (existsSync(join(directory, '.git'))) {\n\t\t\treturn directory;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport function has_hooks_config(directory: string): boolean {\n\treturn (\n\t\tis_file(join(directory, '.claude', 'settings.json')) ||\n\t\tis_file(join(directory, '.rulesync', 'hooks.json')) ||\n\t\tis_file(join(directory, '.pi', 'hooks.json'))\n\t);\n}\n\nexport function find_project_dir(cwd: string): string {\n\tconst git_root = find_nearest_git_root(cwd);\n\tfor (const directory of walk_up_directories(cwd, git_root)) {\n\t\tif (has_hooks_config(directory)) {\n\t\t\treturn directory;\n\t\t}\n\t}\n\treturn git_root ?? resolve(cwd);\n}\n\nexport function read_json_file(path: string): JsonValue | undefined {\n\tif (!is_file(path)) return undefined;\n\ttry {\n\t\treturn JSON.parse(readFileSync(path, 'utf8')) as JsonValue;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function resolve_hook_command(\n\tcommand: string,\n\tproject_dir: string,\n): string {\n\treturn command.replace(/\\$CLAUDE_PROJECT_DIR\\b/g, project_dir);\n}\n\nexport function compile_matcher(\n\tmatcher_text: string | undefined,\n): RegExp | undefined {\n\tif (matcher_text === undefined) return undefined;\n\ttry {\n\t\treturn new RegExp(matcher_text);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function create_hook(\n\tevent_name: HookEventName,\n\tmatcher_text: string | undefined,\n\tcommand: string,\n\tsource: string,\n\tproject_dir: string,\n): ResolvedCommandHook | undefined {\n\tconst matcher = compile_matcher(matcher_text);\n\tif (matcher_text !== undefined && matcher === undefined)\n\t\treturn undefined;\n\treturn {\n\t\tevent_name,\n\t\tmatcher,\n\t\tmatcher_text,\n\t\tcommand: resolve_hook_command(command, project_dir),\n\t\tsource,\n\t};\n}\n\nexport function get_hook_entries(\n\thooks_record: Record<string, unknown>,\n\tevent_name: HookEventName,\n): unknown[] {\n\tconst keys =\n\t\tevent_name === 'PostToolUse'\n\t\t\t? ['PostToolUse', 'postToolUse']\n\t\t\t: ['PostToolUseFailure', 'postToolUseFailure'];\n\n\tfor (const key of keys) {\n\t\tconst value = hooks_record[key];\n\t\tif (Array.isArray(value)) return value;\n\t}\n\treturn [];\n}\n\nexport function parse_claude_settings_hooks(\n\tconfig: unknown,\n\tsource: string,\n\tproject_dir: string,\n): ResolvedCommandHook[] {\n\tconst root = as_record(config);\n\tconst hooks_root = root ? as_record(root.hooks) : undefined;\n\tif (!hooks_root) return [];\n\n\tconst hooks: ResolvedCommandHook[] = [];\n\tconst events: HookEventName[] = [\n\t\t'PostToolUse',\n\t\t'PostToolUseFailure',\n\t];\n\n\tfor (const event_name of events) {\n\t\tconst entries = get_hook_entries(hooks_root, event_name);\n\t\tfor (const entry of entries) {\n\t\t\tconst entry_record = as_record(entry);\n\t\t\tif (!entry_record || !Array.isArray(entry_record.hooks))\n\t\t\t\tcontinue;\n\n\t\t\tconst matcher_text =\n\t\t\t\ttypeof entry_record.matcher === 'string'\n\t\t\t\t\t? entry_record.matcher\n\t\t\t\t\t: undefined;\n\t\t\tfor (const nested_hook of entry_record.hooks) {\n\t\t\t\tconst nested_record = as_record(nested_hook);\n\t\t\t\tif (!nested_record) continue;\n\t\t\t\tif (nested_record.type !== 'command') continue;\n\t\t\t\tif (typeof nested_record.command !== 'string') continue;\n\n\t\t\t\tconst hook = create_hook(\n\t\t\t\t\tevent_name,\n\t\t\t\t\tmatcher_text,\n\t\t\t\t\tnested_record.command,\n\t\t\t\t\tsource,\n\t\t\t\t\tproject_dir,\n\t\t\t\t);\n\t\t\t\tif (hook) hooks.push(hook);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn hooks;\n}\n\nexport function parse_simple_hooks_file(\n\tconfig: unknown,\n\tsource: string,\n\tproject_dir: string,\n): ResolvedCommandHook[] {\n\tconst root = as_record(config);\n\tconst hooks_root = root ? as_record(root.hooks) : undefined;\n\tif (!hooks_root) return [];\n\n\tconst hooks: ResolvedCommandHook[] = [];\n\tconst events: HookEventName[] = [\n\t\t'PostToolUse',\n\t\t'PostToolUseFailure',\n\t];\n\n\tfor (const event_name of events) {\n\t\tconst entries = get_hook_entries(hooks_root, event_name);\n\t\tfor (const entry of entries) {\n\t\t\tconst entry_record = as_record(entry);\n\t\t\tif (!entry_record || typeof entry_record.command !== 'string') {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst matcher_text =\n\t\t\t\ttypeof entry_record.matcher === 'string'\n\t\t\t\t\t? entry_record.matcher\n\t\t\t\t\t: undefined;\n\t\t\tconst hook = create_hook(\n\t\t\t\tevent_name,\n\t\t\t\tmatcher_text,\n\t\t\t\tentry_record.command,\n\t\t\t\tsource,\n\t\t\t\tproject_dir,\n\t\t\t);\n\t\t\tif (hook) hooks.push(hook);\n\t\t}\n\t}\n\n\treturn hooks;\n}\n\nfunction hook_config_paths(project_dir: string): string[] {\n\treturn [\n\t\tjoin(project_dir, '.claude', 'settings.json'),\n\t\tjoin(project_dir, '.rulesync', 'hooks.json'),\n\t\tjoin(project_dir, '.pi', 'hooks.json'),\n\t];\n}\n\nfunction parse_hooks_config_file(\n\tpath: string,\n\tproject_dir: string,\n): ResolvedCommandHook[] {\n\tconst config = read_json_file(path);\n\tif (config === undefined) return [];\n\tif (path.endsWith(join('.claude', 'settings.json'))) {\n\t\treturn parse_claude_settings_hooks(config, path, project_dir);\n\t}\n\treturn parse_simple_hooks_file(config, path, project_dir);\n}\n\nexport function load_hooks(cwd: string): HookState {\n\tconst project_dir = find_project_dir(cwd);\n\tconst hooks = hook_config_paths(project_dir).flatMap((path) =>\n\t\tparse_hooks_config_file(path, project_dir),\n\t);\n\n\treturn { project_dir, hooks };\n}\n\nexport function get_hooks_config_info(\n\tcwd: string,\n): HooksConfigInfo | undefined {\n\tconst project_dir = find_project_dir(cwd);\n\tconst sources = hook_config_paths(project_dir).filter(is_file);\n\tif (sources.length === 0) return undefined;\n\n\tconst hash = createHash('sha256');\n\tfor (const source of sources) {\n\t\thash.update(source);\n\t\thash.update('\\0');\n\t\thash.update(readFileSync(source, 'utf8'));\n\t\thash.update('\\0');\n\t}\n\n\tconst hooks = sources\n\t\t.flatMap((source) => parse_hooks_config_file(source, project_dir))\n\t\t.map((hook) => ({\n\t\t\tevent_name: hook.event_name,\n\t\t\tmatcher_text: hook.matcher_text,\n\t\t\tcommand: hook.command,\n\t\t\tsource: hook.source,\n\t\t}));\n\n\treturn {\n\t\tproject_dir,\n\t\thash: hash.digest('hex'),\n\t\tsources,\n\t\thooks,\n\t};\n}\n\nexport function to_claude_tool_name(tool_name: string): string {\n\tif (tool_name === 'ls') return 'LS';\n\tif (tool_name.length === 0) return tool_name;\n\treturn tool_name[0].toUpperCase() + tool_name.slice(1);\n}\n\nexport function matches_hook(\n\thook: ResolvedCommandHook,\n\ttool_name: string,\n): boolean {\n\tif (!hook.matcher) return true;\n\n\tconst claude_tool_name = to_claude_tool_name(tool_name);\n\thook.matcher.lastIndex = 0;\n\tif (hook.matcher.test(tool_name)) return true;\n\n\thook.matcher.lastIndex = 0;\n\treturn hook.matcher.test(claude_tool_name);\n}\n\nexport function extract_text_content(content: unknown): string {\n\tif (!Array.isArray(content)) return '';\n\n\tconst parts: string[] = [];\n\tfor (const item of content) {\n\t\tif (!item || typeof item !== 'object') continue;\n\t\tconst item_record = item as Record<string, unknown>;\n\t\tif (\n\t\t\titem_record.type === 'text' &&\n\t\t\ttypeof item_record.text === 'string'\n\t\t) {\n\t\t\tparts.push(item_record.text);\n\t\t}\n\t}\n\n\treturn parts.join('\\n');\n}\n\nexport function normalize_tool_input(\n\tinput: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst normalized: Record<string, unknown> = { ...input };\n\tconst path_value =\n\t\ttypeof input.path === 'string' ? input.path : undefined;\n\tif (path_value !== undefined) {\n\t\tnormalized.file_path = path_value;\n\t\tnormalized.filePath = path_value;\n\t}\n\treturn normalized;\n}\n\nexport function build_tool_response(\n\tevent: ToolResultEvent,\n\tnormalized_input: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst response: Record<string, unknown> = {\n\t\tis_error: event.isError,\n\t\tisError: event.isError,\n\t\tcontent: event.content,\n\t\ttext: extract_text_content(event.content),\n\t\tdetails: event.details ?? null,\n\t};\n\n\tconst file_path =\n\t\ttypeof normalized_input.file_path === 'string'\n\t\t\t? normalized_input.file_path\n\t\t\t: undefined;\n\tif (file_path !== undefined) {\n\t\tresponse.file_path = file_path;\n\t\tresponse.filePath = file_path;\n\t}\n\n\treturn response;\n}\n\nexport function build_hook_payload(\n\tevent: ToolResultEvent,\n\tevent_name: HookEventName,\n\tctx: ExtensionContext,\n\tproject_dir: string,\n): Record<string, unknown> {\n\tconst normalized_input = normalize_tool_input(\n\t\tevent.input as Record<string, unknown>,\n\t);\n\tconst session_id =\n\t\tctx.sessionManager.getSessionFile() ?? 'ephemeral';\n\n\treturn {\n\t\tsession_id,\n\t\tcwd: ctx.cwd,\n\t\tclaude_project_dir: project_dir,\n\t\thook_event_name: event_name,\n\t\ttool_name: to_claude_tool_name(event.toolName),\n\t\ttool_call_id: event.toolCallId,\n\t\ttool_input: normalized_input,\n\t\ttool_response: build_tool_response(event, normalized_input),\n\t};\n}\n\nexport async function run_command_hook(\n\tcommand: string,\n\tcwd: string,\n\tpayload: Record<string, unknown>,\n): Promise<CommandRunResult> {\n\treturn await new Promise((resolve) => {\n\t\tconst started_at = Date.now();\n\t\tconst child = spawn('bash', ['-lc', command], {\n\t\t\tcwd,\n\t\t\tenv: create_child_process_env({ CLAUDE_PROJECT_DIR: cwd }),\n\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t});\n\n\t\tlet stdout = '';\n\t\tlet stderr = '';\n\t\tlet timed_out = false;\n\t\tlet resolved = false;\n\n\t\tconst finish = (code: number) => {\n\t\t\tif (resolved) return;\n\t\t\tresolved = true;\n\t\t\tresolve({\n\t\t\t\tcode,\n\t\t\t\tstdout,\n\t\t\t\tstderr,\n\t\t\t\telapsed_ms: Date.now() - started_at,\n\t\t\t\ttimed_out,\n\t\t\t});\n\t\t};\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\ttimed_out = true;\n\t\t\tchild.kill('SIGTERM');\n\t\t\tconst kill_timer = setTimeout(() => {\n\t\t\t\tchild.kill('SIGKILL');\n\t\t\t}, 1000);\n\t\t\t(\n\t\t\t\tkill_timer as NodeJS.Timeout & { unref?: () => void }\n\t\t\t).unref?.();\n\t\t}, HOOK_TIMEOUT_MS);\n\t\t(timeout as NodeJS.Timeout & { unref?: () => void }).unref?.();\n\n\t\tchild.stdout.on('data', (chunk: Buffer) => {\n\t\t\tstdout += chunk.toString('utf8');\n\t\t});\n\t\tchild.stderr.on('data', (chunk: Buffer) => {\n\t\t\tstderr += chunk.toString('utf8');\n\t\t});\n\n\t\tchild.on('error', (error) => {\n\t\t\tclearTimeout(timeout);\n\t\t\tstderr += `${error.message}\\n`;\n\t\t\tfinish(-1);\n\t\t});\n\n\t\tchild.on('close', (code) => {\n\t\t\tclearTimeout(timeout);\n\t\t\tfinish(code ?? -1);\n\t\t});\n\n\t\ttry {\n\t\t\tchild.stdin.write(JSON.stringify(payload));\n\t\t\tchild.stdin.end();\n\t\t} catch (error) {\n\t\t\tstderr += `${error instanceof Error ? error.message : String(error)}\\n`;\n\t\t}\n\t});\n}\n\nexport function hook_event_name_for_result(\n\tevent: ToolResultEvent,\n): HookEventName {\n\treturn event.isError ? 'PostToolUseFailure' : 'PostToolUse';\n}\n\nexport function format_duration(elapsed_ms: number): string {\n\tif (elapsed_ms < 1000) return `${elapsed_ms}ms`;\n\treturn `${(elapsed_ms / 1000).toFixed(1)}s`;\n}\n\nexport function hook_name(command: string): string {\n\tconst sh_path_match = command.match(/[^\\s|;&]+\\.sh\\b/);\n\tif (sh_path_match) return basename(sh_path_match[0]);\n\tconst first_token = command.trim().split(/\\s+/)[0] ?? 'hook';\n\treturn basename(first_token);\n}\n\nfunction create_hooks_trust_subject(\n\tinfo: HooksConfigInfo,\n): ProjectTrustSubject {\n\tconst source_lines = info.sources.map((source) => `- ${source}`);\n\tconst hook_lines =\n\t\tinfo.hooks.length === 0\n\t\t\t? ['- no valid command hooks detected']\n\t\t\t: info.hooks.map((hook) => {\n\t\t\t\t\tconst matcher = hook.matcher_text\n\t\t\t\t\t\t? ` matcher=${hook.matcher_text}`\n\t\t\t\t\t\t: '';\n\t\t\t\t\treturn `- ${hook.event_name}${matcher}: ${hook.command}`;\n\t\t\t\t});\n\treturn {\n\t\tkind: 'hooks-config',\n\t\tid: info.project_dir,\n\t\tstore_key: info.project_dir,\n\t\thash: info.hash,\n\t\tenv_key: HOOKS_CONFIG_ENV,\n\t\tprompt_title:\n\t\t\t'Project hook config can execute shell commands after tool use. Trust these hooks?',\n\t\tsummary_lines: [\n\t\t\t'Sources:',\n\t\t\t...source_lines,\n\t\t\t'Commands:',\n\t\t\t...hook_lines,\n\t\t],\n\t\tchoices: {\n\t\t\tallow_once: 'Allow once for this session',\n\t\t\ttrust: 'Trust this repo until hook config changes',\n\t\t\tskip: 'Skip project hooks',\n\t\t},\n\t\theadless_warning: `Skipping untrusted hook config in ${info.project_dir}. Set ${HOOKS_CONFIG_ENV}=allow to enable hooks for this run.`,\n\t};\n}\n\nasync function should_load_hooks_config(\n\tcwd: string,\n\tctx?: ExtensionContext,\n): Promise<boolean> {\n\tconst info = get_hooks_config_info(cwd);\n\tif (!info) return true;\n\tif (is_hooks_config_trusted(info.project_dir, info.hash))\n\t\treturn true;\n\n\tconst decision = await resolve_project_trust(\n\t\tcreate_hooks_trust_subject(info),\n\t\t{\n\t\t\thas_ui: ctx?.hasUI,\n\t\t\tselect: ctx?.hasUI\n\t\t\t\t? async (\n\t\t\t\t\t\tmessage: string,\n\t\t\t\t\t\tchoices: string[],\n\t\t\t\t\t): Promise<string> => {\n\t\t\t\t\t\tconst selected = await ctx.ui.select(message, choices);\n\t\t\t\t\t\treturn selected ?? '';\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\tenv: process.env,\n\t\t\ttrust_store_path: default_hooks_trust_store_path(),\n\t\t},\n\t);\n\treturn (\n\t\tdecision.action === 'allow-once' ||\n\t\tdecision.action === 'trust-persisted'\n\t);\n}\n\nexport interface HooksResolutionOptions {\n\tload_hooks?: (cwd: string) => HookState;\n\trun_command_hook?: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\tpayload: Record<string, unknown>,\n\t) => Promise<CommandRunResult>;\n}\n\nexport function create_hooks_resolution_extension(\n\toptions: HooksResolutionOptions = {},\n): ExtensionFactory {\n\tconst load_hooks_impl = options.load_hooks ?? load_hooks;\n\tconst run_command_hook_impl =\n\t\toptions.run_command_hook ?? run_command_hook;\n\n\treturn async function hooks_resolution(pi: ExtensionAPI) {\n\t\tlet state: HookState = {\n\t\t\tproject_dir: process.cwd(),\n\t\t\thooks: [],\n\t\t};\n\n\t\tconst refresh_hooks = async (\n\t\t\tcwd: string,\n\t\t\tctx?: ExtensionContext,\n\t\t) => {\n\t\t\tif (!(await should_load_hooks_config(cwd, ctx))) {\n\t\t\t\tstate = { project_dir: cwd, hooks: [] };\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstate = load_hooks_impl(cwd);\n\t\t};\n\n\t\tpi.on('session_start', async (_event, ctx) => {\n\t\t\tawait refresh_hooks(ctx.cwd, ctx);\n\t\t});\n\n\t\tpi.on('tool_result', async (event, ctx) => {\n\t\t\tif (state.hooks.length === 0) return;\n\n\t\t\tconst event_name = hook_event_name_for_result(event);\n\t\t\tconst matching_hooks = state.hooks.filter(\n\t\t\t\t(hook) =>\n\t\t\t\t\thook.event_name === event_name &&\n\t\t\t\t\tmatches_hook(hook, event.toolName),\n\t\t\t);\n\t\t\tif (matching_hooks.length === 0) return;\n\n\t\t\tconst payload = build_hook_payload(\n\t\t\t\tevent,\n\t\t\t\tevent_name,\n\t\t\t\tctx,\n\t\t\t\tstate.project_dir,\n\t\t\t);\n\t\t\tconst executed_commands = new Set<string>();\n\n\t\t\tfor (const hook of matching_hooks) {\n\t\t\t\tif (executed_commands.has(hook.command)) continue;\n\t\t\t\texecuted_commands.add(hook.command);\n\n\t\t\t\tconst result = await run_command_hook_impl(\n\t\t\t\t\thook.command,\n\t\t\t\t\tstate.project_dir,\n\t\t\t\t\tpayload,\n\t\t\t\t);\n\t\t\t\tconst name = hook_name(hook.command);\n\t\t\t\tconst duration = format_duration(result.elapsed_ms);\n\n\t\t\t\tif (ctx.hasUI) {\n\t\t\t\t\tif (result.code === 0) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t`Hook \\`${name}\\` ran (${duration})`,\n\t\t\t\t\t\t\t'info',\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst error_line =\n\t\t\t\t\t\t\tresult.stderr.trim() ||\n\t\t\t\t\t\t\tresult.stdout.trim() ||\n\t\t\t\t\t\t\t`exit code ${result.code}`;\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t`Hook \\`${name}\\` failed (${duration}): ${error_line}`,\n\t\t\t\t\t\t\t'warning',\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\t};\n}\n\nexport default create_hooks_resolution_extension();\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| 'filter-output'\n\t| 'recall'\n\t| 'nopeek'\n\t| 'omnisearch'\n\t| 'sqlite-tools'\n\t| 'prompt-presets'\n\t| 'lsp'\n\t| 'session-name'\n\t| 'confirm-destructive'\n\t| 'hooks-resolution'\n\t| 'team-mode';\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: '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: 'recall',\n\t\tlabel: 'Recall',\n\t\tdescription: 'pirecall reminder and background session sync',\n\t\tcli_flag: '--no-recall',\n\t\taliases: ['recall', 'pirecall'],\n\t},\n\t{\n\t\tkey: 'nopeek',\n\t\tlabel: 'Nopeek',\n\t\tdescription:\n\t\t\t'nopeek reminder for secret-safe environment loading',\n\t\tcli_flag: '--no-nopeek',\n\t\taliases: ['nopeek', 'secrets', 'secret-loading'],\n\t},\n\t{\n\t\tkey: 'omnisearch',\n\t\tlabel: 'Omnisearch',\n\t\tdescription: 'mcp-omnisearch reminder for verified web research',\n\t\tcli_flag: '--no-omnisearch',\n\t\taliases: ['omnisearch', 'search', 'web-search', 'research'],\n\t},\n\t{\n\t\tkey: 'sqlite-tools',\n\t\tlabel: 'SQLite tools',\n\t\tdescription:\n\t\t\t'mcp-sqlite-tools reminder for safer SQLite database work',\n\t\tcli_flag: '--no-sqlite-tools',\n\t\taliases: ['sqlite-tools', 'sqlite', 'mcp-sqlite-tools'],\n\t},\n\t{\n\t\tkey: 'prompt-presets',\n\t\tlabel: 'Prompt presets',\n\t\tdescription:\n\t\t\t'Runtime prompt preset selection and /prompt-preset command',\n\t\tcli_flag: '--no-prompt-presets',\n\t\taliases: ['prompt-presets', 'prompt-preset', 'preset', 'presets'],\n\t},\n\t{\n\t\tkey: 'lsp',\n\t\tlabel: 'LSP',\n\t\tdescription:\n\t\t\t'Language Server Protocol tools (diagnostics, hover, definition, references)',\n\t\tcli_flag: '--no-lsp',\n\t\taliases: ['lsp', 'language-server'],\n\t},\n\t{\n\t\tkey: 'session-name',\n\t\tlabel: 'Session name',\n\t\tdescription:\n\t\t\t'AI-powered session auto-naming and /session-name command',\n\t\tcli_flag: '--no-session-name',\n\t\taliases: ['session-name', 'session', 'auto-name'],\n\t},\n\t{\n\t\tkey: 'confirm-destructive',\n\t\tlabel: 'Confirm destructive',\n\t\tdescription:\n\t\t\t'Prompt before destructive tool calls like file deletes, overwrites, and hard resets',\n\t\tcli_flag: '--no-confirm-destructive',\n\t\taliases: ['confirm-destructive', 'confirm'],\n\t},\n\t{\n\t\tkey: 'hooks-resolution',\n\t\tlabel: 'Hooks resolution',\n\t\tdescription:\n\t\t\t'Claude Code style PostToolUse hook compatibility from .claude, .rulesync, and .pi configs',\n\t\tcli_flag: '--no-hooks',\n\t\taliases: ['hooks-resolution', 'hooks'],\n\t},\n\t{\n\t\tkey: 'team-mode',\n\t\tlabel: 'Team mode',\n\t\tdescription:\n\t\t\t'Experimental orchestrator/team mode with RPC teammates, tasks, and mailboxes',\n\t\tcli_flag: '--no-team-mode',\n\t\taliases: ['team-mode', 'team', 'teammates'],\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 {\n\tExtensionAPI,\n\tExtensionCommandContext,\n} from '@mariozechner/pi-coding-agent';\nimport { type SettingItem } from '@mariozechner/pi-tui';\nimport { show_settings_modal } from '@spences10/pi-tui-modal';\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 = '● enabled';\nconst DISABLED = '○ 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\tasync function show_manager(\n\t\tctx: ExtensionCommandContext,\n\t): Promise<boolean> {\n\t\tif (!ctx.hasUI) return false;\n\n\t\tconst states = resolve_builtin_extension_states(force_disabled);\n\t\tconst initial_enabled = new Set(\n\t\t\tstates\n\t\t\t\t.filter((state) => state.saved_enabled)\n\t\t\t\t.map((state) => state.key),\n\t\t);\n\t\tconst current_enabled = new Set(initial_enabled);\n\n\t\tconst items = states.map(to_setting_item);\n\t\tawait show_settings_modal(ctx, {\n\t\t\ttitle: 'Built-in extensions',\n\t\t\tsubtitle: () => {\n\t\t\t\tconst saved_enabled = current_enabled.size;\n\t\t\t\tconst saved_disabled = states.length - saved_enabled;\n\t\t\t\tconst enabled_now = [...current_enabled].filter(\n\t\t\t\t\t(key) => !force_disabled.has(key as BuiltinExtensionKey),\n\t\t\t\t).length;\n\t\t\t\tconst disabled_now = states.length - enabled_now;\n\t\t\t\treturn `${saved_enabled} saved enabled • ${saved_disabled} saved disabled • ${enabled_now} enabled now • ${disabled_now} disabled now`;\n\t\t\t},\n\t\t\titems,\n\t\t\tenable_search: true,\n\t\t\tfooter:\n\t\t\t\t'esc close • search filters • changes save immediately • CLI --no-* flags still win in this process',\n\t\t\ton_change: (id, new_value) => {\n\t\t\t\tconst key = id as BuiltinExtensionKey;\n\t\t\t\tconst enabled = new_value === ENABLED;\n\t\t\t\tif (enabled) {\n\t\t\t\t\tcurrent_enabled.add(key);\n\t\t\t\t} else {\n\t\t\t\t\tcurrent_enabled.delete(key);\n\t\t\t\t}\n\t\t\t\tsave_extension_enabled(key, enabled);\n\t\t\t},\n\t\t});\n\n\t\tif (!sets_equal(initial_enabled, current_enabled)) {\n\t\t\tctx.ui.notify(\n\t\t\t\tforce_disabled.size > 0\n\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: 'Reloading to apply updated built-in extensions...',\n\t\t\t\t'info',\n\t\t\t);\n\t\t\tawait ctx.reload();\n\t\t}\n\n\t\treturn true;\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) {\n\t\t\t\t\tif (await show_manager(ctx)) return;\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\tif (await show_manager(ctx)) return;\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","import {\n\tgetAgentDir,\n\ttype ExtensionAPI,\n\ttype ExtensionCommandContext,\n\ttype ExtensionContext,\n\ttype ReadonlyFooterDataProvider,\n} from '@mariozechner/pi-coding-agent';\nimport {\n\ttruncateToWidth,\n\tvisibleWidth,\n\ttype SettingItem,\n} from '@mariozechner/pi-tui';\nimport { show_settings_modal } from '@spences10/pi-tui-modal';\nimport {\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trenameSync,\n\tunlinkSync,\n\twriteFileSync,\n} from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nexport type PromptPresetKind = 'base' | 'layer';\nexport type PromptPresetSource = 'builtin' | 'user' | 'project';\n\nconst PROJECT_PROMPT_PRESETS_ENV = 'MY_PI_PROMPT_PRESETS_PROJECT';\n\nexport interface PromptPreset {\n\tkind?: PromptPresetKind;\n\tdescription?: string;\n\tinstructions: string;\n}\n\nexport type PromptPresetMap = Record<string, PromptPreset>;\n\nexport interface LoadedPromptPreset extends PromptPreset {\n\tname: string;\n\tkind: PromptPresetKind;\n\tsource: PromptPresetSource;\n}\n\nexport interface PromptPresetState {\n\tbase_name: string | null;\n\tlayer_names: string[];\n}\n\ninterface PersistedPromptPresetStates {\n\tversion: number;\n\tprojects: Record<string, PromptPresetState>;\n}\n\nconst PRESET_STATE_TYPE = 'prompt-preset-state';\nexport const DEFAULT_BASE_PROMPT_PRESET_NAME = 'terse';\nconst ENABLED = '● enabled';\nconst DISABLED = '○ disabled';\nconst SELECTED = '● selected';\nconst UNSELECTED = '○';\nconst NONE_BASE_ID = '__base_none__';\n\nexport const DEFAULT_PROMPT_PRESETS: PromptPresetMap = {\n\tterse: {\n\t\tkind: 'base',\n\t\tdescription: 'Short, direct, no fluff',\n\t\tinstructions:\n\t\t\t\"Be concise and direct. Default to the shortest response that fully solves the user's request. Use at most one short paragraph or 3 bullets unless the user explicitly asks for detail. For implementation reports, include only what changed, validation, and the next step if relevant. No purple prose, no filler, no repetitive caveats.\",\n\t},\n\tstandard: {\n\t\tkind: 'base',\n\t\tdescription: 'Clear and concise with key context',\n\t\tinstructions:\n\t\t\t'Be clear, direct, and concise. Include only the reasoning and implementation details that matter. Avoid filler, grandstanding, and ornamental language. Use bullets when they improve scanability.',\n\t},\n\tdetailed: {\n\t\tkind: 'base',\n\t\tdescription: 'More explanation when nuance matters',\n\t\tinstructions:\n\t\t\t'Be thorough when the task is complex or tradeoffs matter, but stay practical. Explain only the details that help the user decide, verify, or implement. Avoid purple prose and unnecessary scene-setting.',\n\t},\n\t'no-purple-prose': {\n\t\tkind: 'layer',\n\t\tdescription: 'Strip out ornamental language',\n\t\tinstructions:\n\t\t\t'Do not use purple prose, flourish, motivational filler, or theatrical transitions. Prefer plain language and concrete statements.',\n\t},\n\tbullets: {\n\t\tkind: 'layer',\n\t\tdescription: 'Prefer short bullets when useful',\n\t\tinstructions:\n\t\t\t'When presenting options, findings, or steps, prefer short bullet lists over long paragraphs.',\n\t},\n\t'clarify-first': {\n\t\tkind: 'layer',\n\t\tdescription:\n\t\t\t'Ask brief clarifying questions when requirements are ambiguous',\n\t\tinstructions:\n\t\t\t'If the request is materially ambiguous, ask the minimum clarifying question(s) needed before proceeding. Do not ask unnecessary questions.',\n\t},\n\t'include-risks': {\n\t\tkind: 'layer',\n\t\tdescription: 'Call out notable risks or tradeoffs',\n\t\tinstructions:\n\t\t\t'When making a recommendation or implementation plan, briefly mention the key risk, tradeoff, or caveat if one materially matters.',\n\t},\n};\n\nexport function normalize_prompt_presets(\n\tinput: unknown,\n): PromptPresetMap {\n\tif (!input || typeof input !== 'object') return {};\n\n\tconst normalized: PromptPresetMap = {};\n\tfor (const [raw_name, raw_value] of Object.entries(input)) {\n\t\tconst name = raw_name.trim();\n\t\tif (!name) continue;\n\n\t\tif (typeof raw_value === 'string') {\n\t\t\tnormalized[name] = {\n\t\t\t\tkind: 'base',\n\t\t\t\tinstructions: raw_value,\n\t\t\t};\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!raw_value || typeof raw_value !== 'object') continue;\n\t\tconst candidate = raw_value as {\n\t\t\tkind?: unknown;\n\t\t\tdescription?: unknown;\n\t\t\tinstructions?: unknown;\n\t\t};\n\t\tif (typeof candidate.instructions !== 'string') continue;\n\n\t\tnormalized[name] = {\n\t\t\tinstructions: candidate.instructions,\n\t\t\t...(candidate.kind === 'layer'\n\t\t\t\t? { kind: 'layer' as const }\n\t\t\t\t: {}),\n\t\t\t...(typeof candidate.description === 'string'\n\t\t\t\t? { description: candidate.description }\n\t\t\t\t: {}),\n\t\t};\n\t}\n\n\treturn normalized;\n}\n\nexport function merge_prompt_presets(\n\t...sources: PromptPresetMap[]\n): PromptPresetMap {\n\treturn Object.assign({}, ...sources);\n}\n\nfunction to_loaded_prompt_presets(\n\tpresets: PromptPresetMap,\n\tsource: PromptPresetSource,\n): Record<string, LoadedPromptPreset> {\n\treturn Object.fromEntries(\n\t\tObject.entries(presets).map(([name, preset]) => [\n\t\t\tname,\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tkind: preset.kind === 'layer' ? 'layer' : 'base',\n\t\t\t\tsource,\n\t\t\t\t...preset,\n\t\t\t},\n\t\t]),\n\t);\n}\n\nfunction get_global_presets_path(): string {\n\treturn join(getAgentDir(), 'presets.json');\n}\n\nfunction get_project_presets_path(cwd: string): string {\n\treturn join(cwd, '.pi', 'presets.json');\n}\n\nfunction get_global_presets_dir(): string {\n\treturn join(getAgentDir(), 'presets');\n}\n\nfunction get_project_presets_dir(cwd: string): string {\n\treturn join(cwd, '.pi', 'presets');\n}\n\nfunction sanitize_prompt_preset_file_name(name: string): string {\n\tconst sanitized = name\n\t\t.trim()\n\t\t.replace(/[\\\\/:*?\"<>|]/g, '-')\n\t\t.replace(/^\\.+$/, '')\n\t\t.replace(/^\\.+/, '')\n\t\t.replace(/\\.+$/, '');\n\tif (!sanitized) {\n\t\tthrow new Error(\n\t\t\t'Prompt preset name must contain a file-safe character',\n\t\t);\n\t}\n\treturn sanitized;\n}\n\nfunction get_prompt_preset_file_path(\n\tdir: string,\n\tname: string,\n): string {\n\treturn join(dir, `${sanitize_prompt_preset_file_name(name)}.md`);\n}\n\nfunction get_persisted_prompt_state_path(): string {\n\treturn join(getAgentDir(), 'prompt-preset-state.json');\n}\n\nfunction read_prompt_presets_file(path: string): PromptPresetMap {\n\tif (!existsSync(path)) return {};\n\n\ttry {\n\t\treturn normalize_prompt_presets(\n\t\t\tJSON.parse(readFileSync(path, 'utf-8')),\n\t\t);\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction unquote_frontmatter_value(value: string): string {\n\tconst trimmed = value.trim();\n\tif (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n\t\ttry {\n\t\t\treturn JSON.parse(trimmed) as string;\n\t\t} catch {\n\t\t\treturn trimmed.slice(1, -1);\n\t\t}\n\t}\n\tif (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n\t\treturn trimmed.slice(1, -1);\n\t}\n\treturn trimmed;\n}\n\nfunction parse_prompt_preset_markdown(content: string): {\n\tmetadata: Record<string, string>;\n\tbody: string;\n} {\n\tconst normalized = content.replace(/\\r\\n/g, '\\n');\n\tif (!normalized.startsWith('---\\n')) {\n\t\treturn { metadata: {}, body: normalized.trim() };\n\t}\n\n\tconst lines = normalized.split('\\n');\n\tconst end = lines.findIndex(\n\t\t(line, index) => index > 0 && line.trim() === '---',\n\t);\n\tif (end === -1) {\n\t\treturn { metadata: {}, body: normalized.trim() };\n\t}\n\n\tconst metadata: Record<string, string> = {};\n\tfor (const line of lines.slice(1, end)) {\n\t\tconst separator = line.indexOf(':');\n\t\tif (separator === -1) continue;\n\t\tconst key = line.slice(0, separator).trim().toLowerCase();\n\t\tconst value = line.slice(separator + 1).trim();\n\t\tif (!key) continue;\n\t\tmetadata[key] = unquote_frontmatter_value(value);\n\t}\n\n\treturn {\n\t\tmetadata,\n\t\tbody: lines\n\t\t\t.slice(end + 1)\n\t\t\t.join('\\n')\n\t\t\t.trim(),\n\t};\n}\n\nexport function read_prompt_presets_dir(\n\tpath: string,\n): PromptPresetMap {\n\tif (!existsSync(path)) return {};\n\n\ttry {\n\t\tconst presets: PromptPresetMap = {};\n\t\tfor (const entry of readdirSync(path, { withFileTypes: true })\n\t\t\t.filter((item) => item.isFile() && item.name.endsWith('.md'))\n\t\t\t.sort((a, b) => a.name.localeCompare(b.name))) {\n\t\t\tconst name = entry.name.slice(0, -3).trim();\n\t\t\tif (!name) continue;\n\t\t\tconst { metadata, body } = parse_prompt_preset_markdown(\n\t\t\t\treadFileSync(join(path, entry.name), 'utf-8'),\n\t\t\t);\n\t\t\tif (!body) continue;\n\t\t\tpresets[name] = {\n\t\t\t\tkind: metadata.kind === 'layer' ? 'layer' : 'base',\n\t\t\t\tinstructions: body,\n\t\t\t\t...(metadata.description\n\t\t\t\t\t? { description: metadata.description }\n\t\t\t\t\t: {}),\n\t\t\t};\n\t\t}\n\t\treturn presets;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction format_prompt_preset_markdown(preset: PromptPreset): string {\n\tconst lines = [\n\t\t'---',\n\t\t`kind: ${preset.kind === 'layer' ? 'layer' : 'base'}`,\n\t];\n\tif (preset.description?.trim()) {\n\t\tlines.push(\n\t\t\t`description: ${JSON.stringify(preset.description.trim())}`,\n\t\t);\n\t}\n\tlines.push('---', '', preset.instructions.trim(), '');\n\treturn lines.join('\\n');\n}\n\nexport function save_prompt_preset_file(\n\tdir: string,\n\tname: string,\n\tpreset: PromptPreset,\n): string {\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n\n\tconst path = get_prompt_preset_file_path(dir, name);\n\tconst tmp = `${path}.tmp-${Date.now()}`;\n\twriteFileSync(tmp, format_prompt_preset_markdown(preset), {\n\t\tmode: 0o600,\n\t});\n\trenameSync(tmp, path);\n\treturn path;\n}\n\nfunction save_project_prompt_preset_file(\n\tcwd: string,\n\tname: string,\n\tpreset: PromptPreset,\n): string {\n\treturn save_prompt_preset_file(\n\t\tget_project_presets_dir(cwd),\n\t\tname,\n\t\tpreset,\n\t);\n}\n\nfunction save_global_prompt_preset_file(\n\tname: string,\n\tpreset: PromptPreset,\n): string {\n\treturn save_prompt_preset_file(\n\t\tget_global_presets_dir(),\n\t\tname,\n\t\tpreset,\n\t);\n}\n\nfunction should_load_project_prompt_presets(): boolean {\n\tconst normalized = process.env[PROJECT_PROMPT_PRESETS_ENV]\n\t\t?.trim()\n\t\t.toLowerCase();\n\treturn !['0', 'false', 'no', 'skip', 'disable'].includes(\n\t\tnormalized ?? '',\n\t);\n}\n\nexport function load_prompt_presets(\n\tcwd: string,\n): Record<string, LoadedPromptPreset> {\n\treturn Object.assign(\n\t\t{},\n\t\tto_loaded_prompt_presets(DEFAULT_PROMPT_PRESETS, 'builtin'),\n\t\tto_loaded_prompt_presets(\n\t\t\tread_prompt_presets_file(get_global_presets_path()),\n\t\t\t'user',\n\t\t),\n\t\tto_loaded_prompt_presets(\n\t\t\tread_prompt_presets_dir(get_global_presets_dir()),\n\t\t\t'user',\n\t\t),\n\t\t...(should_load_project_prompt_presets()\n\t\t\t? [\n\t\t\t\t\tto_loaded_prompt_presets(\n\t\t\t\t\t\tread_prompt_presets_file(get_project_presets_path(cwd)),\n\t\t\t\t\t\t'project',\n\t\t\t\t\t),\n\t\t\t\t\tto_loaded_prompt_presets(\n\t\t\t\t\t\tread_prompt_presets_dir(get_project_presets_dir(cwd)),\n\t\t\t\t\t\t'project',\n\t\t\t\t\t),\n\t\t\t\t]\n\t\t\t: []),\n\t);\n}\n\nfunction sort_prompt_presets(\n\tpresets: PromptPresetMap,\n): PromptPresetMap {\n\treturn Object.fromEntries(\n\t\tObject.entries(presets).sort(([a], [b]) => a.localeCompare(b)),\n\t);\n}\n\nexport function save_project_prompt_presets(\n\tcwd: string,\n\tpresets: PromptPresetMap,\n): string {\n\tconst path = get_project_presets_path(cwd);\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n\n\tconst tmp = `${path}.tmp-${Date.now()}`;\n\twriteFileSync(\n\t\ttmp,\n\t\tJSON.stringify(sort_prompt_presets(presets), null, '\\t') + '\\n',\n\t\t{ mode: 0o600 },\n\t);\n\trenameSync(tmp, path);\n\treturn path;\n}\n\nexport function remove_project_prompt_preset(\n\tcwd: string,\n\tname: string,\n): {\n\tremoved: boolean;\n\tpath: string;\n\tremaining: number;\n} {\n\tconst json_path = get_project_presets_path(cwd);\n\tconst project_presets = read_prompt_presets_file(json_path);\n\tlet removed = false;\n\tlet removed_path = json_path;\n\n\tif (name in project_presets) {\n\t\tdelete project_presets[name];\n\t\tremoved = true;\n\t\tremoved_path = json_path;\n\t\tif (Object.keys(project_presets).length === 0) {\n\t\t\tif (existsSync(json_path)) {\n\t\t\t\tunlinkSync(json_path);\n\t\t\t}\n\t\t} else {\n\t\t\tsave_project_prompt_presets(cwd, project_presets);\n\t\t}\n\t}\n\n\tconst file_path = get_prompt_preset_file_path(\n\t\tget_project_presets_dir(cwd),\n\t\tname,\n\t);\n\tif (existsSync(file_path)) {\n\t\tunlinkSync(file_path);\n\t\tremoved = true;\n\t\tremoved_path = file_path;\n\t}\n\n\tconst remaining =\n\t\tObject.keys(read_prompt_presets_file(json_path)).length +\n\t\tObject.keys(read_prompt_presets_dir(get_project_presets_dir(cwd)))\n\t\t\t.length;\n\n\treturn { removed, path: removed_path, remaining };\n}\n\nfunction normalize_prompt_preset_state(\n\tinput: unknown,\n): PromptPresetState | undefined {\n\tif (!input || typeof input !== 'object') return undefined;\n\n\tconst candidate = input as {\n\t\tbase_name?: unknown;\n\t\tlayer_names?: unknown;\n\t};\n\tconst base_name =\n\t\ttypeof candidate.base_name === 'string' &&\n\t\tcandidate.base_name.trim()\n\t\t\t? candidate.base_name.trim()\n\t\t\t: null;\n\tconst layer_names = Array.isArray(candidate.layer_names)\n\t\t? [\n\t\t\t\t...new Set(\n\t\t\t\t\tcandidate.layer_names\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t(value): value is string =>\n\t\t\t\t\t\t\t\ttypeof value === 'string' && value.trim().length > 0,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.map((value) => value.trim()),\n\t\t\t\t),\n\t\t\t].sort()\n\t\t: [];\n\n\treturn {\n\t\tbase_name,\n\t\tlayer_names,\n\t};\n}\n\nfunction read_persisted_prompt_states(\n\tpath = get_persisted_prompt_state_path(),\n): PersistedPromptPresetStates {\n\tif (!existsSync(path)) {\n\t\treturn { version: 1, projects: {} };\n\t}\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(path, 'utf-8')) as {\n\t\t\tversion?: unknown;\n\t\t\tprojects?: unknown;\n\t\t};\n\t\tconst raw_projects =\n\t\t\tparsed.projects && typeof parsed.projects === 'object'\n\t\t\t\t? parsed.projects\n\t\t\t\t: {};\n\t\tconst projects: Record<string, PromptPresetState> = {};\n\t\tfor (const [cwd, value] of Object.entries(raw_projects)) {\n\t\t\tconst normalized = normalize_prompt_preset_state(value);\n\t\t\tif (!normalized) continue;\n\t\t\tprojects[cwd] = normalized;\n\t\t}\n\t\treturn {\n\t\t\tversion:\n\t\t\t\ttypeof parsed.version === 'number' ? parsed.version : 1,\n\t\t\tprojects,\n\t\t};\n\t} catch {\n\t\treturn { version: 1, projects: {} };\n\t}\n}\n\nexport function load_persisted_prompt_state(\n\tcwd: string,\n\tpath = get_persisted_prompt_state_path(),\n): PromptPresetState | undefined {\n\treturn read_persisted_prompt_states(path).projects[cwd];\n}\n\nexport function save_persisted_prompt_state(\n\tcwd: string,\n\tstate: PromptPresetState,\n\tpath = get_persisted_prompt_state_path(),\n): string {\n\tconst persisted = read_persisted_prompt_states(path);\n\tpersisted.projects[cwd] = normalize_prompt_preset_state(state) ?? {\n\t\tbase_name: null,\n\t\tlayer_names: [],\n\t};\n\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n\n\tconst tmp = `${path}.tmp-${Date.now()}`;\n\twriteFileSync(\n\t\ttmp,\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tversion: 1,\n\t\t\t\tprojects: Object.fromEntries(\n\t\t\t\t\tObject.entries(persisted.projects).sort(([a], [b]) =>\n\t\t\t\t\t\ta.localeCompare(b),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t},\n\t\t\tnull,\n\t\t\t'\\t',\n\t\t) + '\\n',\n\t\t{ mode: 0o600 },\n\t);\n\trenameSync(tmp, path);\n\treturn path;\n}\n\nfunction get_last_preset_state(\n\tctx: ExtensionContext,\n): PromptPresetState | undefined {\n\tconst entries = ctx.sessionManager.getEntries();\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i] as {\n\t\t\ttype?: string;\n\t\t\tcustomType?: string;\n\t\t\tdata?: PromptPresetState;\n\t\t};\n\t\tif (\n\t\t\tentry.type === 'custom' &&\n\t\t\tentry.customType === PRESET_STATE_TYPE &&\n\t\t\tentry.data\n\t\t) {\n\t\t\treturn entry.data;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction sets_equal(\n\ta: ReadonlySet<string>,\n\tb: ReadonlySet<string>,\n): boolean {\n\tif (a.size !== b.size) return false;\n\tfor (const value of a) {\n\t\tif (!b.has(value)) return false;\n\t}\n\treturn true;\n}\n\nfunction get_prompt_source_label(source: PromptPresetSource): string {\n\tswitch (source) {\n\t\tcase 'builtin':\n\t\t\treturn 'built-in';\n\t\tcase 'user':\n\t\t\treturn 'user';\n\t\tcase 'project':\n\t\t\treturn 'project';\n\t}\n}\n\nfunction list_base_presets(\n\tpresets: Record<string, LoadedPromptPreset>,\n): LoadedPromptPreset[] {\n\treturn Object.values(presets)\n\t\t.filter((preset) => preset.kind === 'base')\n\t\t.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction list_layer_presets(\n\tpresets: Record<string, LoadedPromptPreset>,\n): LoadedPromptPreset[] {\n\treturn Object.values(presets)\n\t\t.filter((preset) => preset.kind === 'layer')\n\t\t.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction format_summary(\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n\tpresets: Record<string, LoadedPromptPreset>,\n): string {\n\tconst lines = [`Base: ${active_base_name ?? '(none)'}`];\n\n\tconst layer_names = [...active_layers].sort();\n\tif (layer_names.length === 0) {\n\t\tlines.push('Layers: (none)');\n\t} else {\n\t\tlines.push('Layers:');\n\t\tfor (const name of layer_names) {\n\t\t\tconst preset = presets[name];\n\t\t\tconst description = preset?.description\n\t\t\t\t? ` — ${preset.description}`\n\t\t\t\t: '';\n\t\t\tlines.push(`- ${name}${description}`);\n\t\t}\n\t}\n\n\treturn lines.join('\\n');\n}\n\nfunction format_active_details(\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n\tpresets: Record<string, LoadedPromptPreset>,\n): string {\n\tconst parts: string[] = [];\n\n\tif (active_base_name) {\n\t\tconst base = presets[active_base_name];\n\t\tif (base) {\n\t\t\tparts.push(`Base: ${base.name}`);\n\t\t\tif (base.description)\n\t\t\t\tparts.push(`Description: ${base.description}`);\n\t\t\tparts.push(`Source: ${get_prompt_source_label(base.source)}`);\n\t\t\tparts.push('', base.instructions.trim());\n\t\t}\n\t}\n\n\tconst layer_names = [...active_layers].sort();\n\tif (layer_names.length > 0) {\n\t\tif (parts.length > 0) parts.push('', '---', '');\n\t\tparts.push('Layers:');\n\t\tfor (const name of layer_names) {\n\t\t\tconst layer = presets[name];\n\t\t\tif (!layer) continue;\n\t\t\tparts.push(\n\t\t\t\t`- ${layer.name} (${get_prompt_source_label(layer.source)})`,\n\t\t\t);\n\t\t\tif (layer.description) parts.push(` ${layer.description}`);\n\t\t}\n\t}\n\n\treturn parts.join('\\n') || 'No preset or layers active';\n}\n\nfunction get_footer_prompt_status(\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): string | undefined {\n\tif (!active_base_name && active_layers.size === 0) {\n\t\treturn undefined;\n\t}\n\n\tconst label = active_base_name ?? 'none';\n\tconst layer_suffix =\n\t\tactive_layers.size > 0 ? ` +${active_layers.size}` : '';\n\treturn `prompt:${label}${layer_suffix}`;\n}\n\nfunction sanitize_status_text(text: string): string {\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, ' ')\n\t\t.replace(/ +/g, ' ')\n\t\t.trim();\n}\n\nfunction format_token_count(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\nexport function render_footer_status_line(\n\ttheme: ExtensionContext['ui']['theme'],\n\twidth: number,\n\tleft_items: string[],\n\tright_item?: string,\n): string | undefined {\n\tconst left = sanitize_status_text(left_items.join(' '));\n\tconst right = right_item ? sanitize_status_text(right_item) : '';\n\tif (!left && !right) return undefined;\n\tif (!right) {\n\t\treturn truncateToWidth(\n\t\t\ttheme.fg('dim', left),\n\t\t\twidth,\n\t\t\ttheme.fg('dim', '...'),\n\t\t);\n\t}\n\tif (!left) {\n\t\tconst themed_right = theme.fg('dim', right);\n\t\tconst right_width = visibleWidth(themed_right);\n\t\treturn right_width >= width\n\t\t\t? truncateToWidth(themed_right, width, theme.fg('dim', '...'))\n\t\t\t: `${' '.repeat(width - right_width)}${themed_right}`;\n\t}\n\n\tconst right_width = visibleWidth(right);\n\tif (right_width >= width) {\n\t\treturn truncateToWidth(\n\t\t\ttheme.fg('dim', right),\n\t\t\twidth,\n\t\t\ttheme.fg('dim', '...'),\n\t\t);\n\t}\n\n\tconst min_gap = 1;\n\tconst available_left = Math.max(0, width - right_width - min_gap);\n\tconst truncated_left = truncateToWidth(left, available_left, '...');\n\tconst left_width = visibleWidth(truncated_left);\n\tconst gap = Math.max(min_gap, width - left_width - right_width);\n\treturn (\n\t\ttheme.fg('dim', truncated_left) +\n\t\t' '.repeat(gap) +\n\t\ttheme.fg('dim', right)\n\t);\n}\n\nfunction get_current_thinking_level(ctx: ExtensionContext): string {\n\tconst entries = ctx.sessionManager.getEntries();\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i] as {\n\t\t\ttype?: string;\n\t\t\tthinkingLevel?: string;\n\t\t};\n\t\tif (\n\t\t\tentry.type === 'thinking_level_change' &&\n\t\t\ttypeof entry.thinkingLevel === 'string'\n\t\t) {\n\t\t\treturn entry.thinkingLevel;\n\t\t}\n\t}\n\treturn ctx.model?.reasoning ? 'high' : 'off';\n}\n\nfunction render_footer_lines(\n\tctx: ExtensionContext,\n\ttheme: ExtensionContext['ui']['theme'],\n\tfooter_data: ReadonlyFooterDataProvider,\n\twidth: number,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): string[] {\n\tlet total_input = 0;\n\tlet total_output = 0;\n\tlet total_cache_read = 0;\n\tlet total_cache_write = 0;\n\tlet total_cost = 0;\n\tfor (const entry of ctx.sessionManager.getEntries()) {\n\t\tif (\n\t\t\tentry.type === 'message' &&\n\t\t\tentry.message.role === 'assistant'\n\t\t) {\n\t\t\ttotal_input += entry.message.usage.input;\n\t\t\ttotal_output += entry.message.usage.output;\n\t\t\ttotal_cache_read += entry.message.usage.cacheRead;\n\t\t\ttotal_cache_write += entry.message.usage.cacheWrite;\n\t\t\ttotal_cost += entry.message.usage.cost.total;\n\t\t}\n\t}\n\n\tconst context_usage = ctx.getContextUsage();\n\tconst context_window =\n\t\tcontext_usage?.contextWindow ?? ctx.model?.contextWindow ?? 0;\n\tconst context_percent_value = context_usage?.percent ?? 0;\n\tconst context_percent =\n\t\tcontext_usage?.percent !== null\n\t\t\t? context_percent_value.toFixed(1)\n\t\t\t: '?';\n\n\tlet pwd = ctx.cwd;\n\tconst home = process.env.HOME || process.env.USERPROFILE;\n\tif (home && pwd.startsWith(home)) {\n\t\tpwd = `~${pwd.slice(home.length)}`;\n\t}\n\n\tconst branch = footer_data.getGitBranch();\n\tif (branch) {\n\t\tpwd = `${pwd} (${branch})`;\n\t}\n\n\tconst session_name = ctx.sessionManager.getSessionName();\n\tif (session_name) {\n\t\tpwd = `${pwd} • ${session_name}`;\n\t}\n\n\tconst stats_parts: string[] = [];\n\tif (total_input)\n\t\tstats_parts.push(`↑${format_token_count(total_input)}`);\n\tif (total_output)\n\t\tstats_parts.push(`↓${format_token_count(total_output)}`);\n\tif (total_cache_read)\n\t\tstats_parts.push(`R${format_token_count(total_cache_read)}`);\n\tif (total_cache_write)\n\t\tstats_parts.push(`W${format_token_count(total_cache_write)}`);\n\n\tconst using_subscription = ctx.model\n\t\t? ctx.modelRegistry.isUsingOAuth(ctx.model)\n\t\t: false;\n\tif (total_cost || using_subscription) {\n\t\tstats_parts.push(\n\t\t\t`$${total_cost.toFixed(3)}${using_subscription ? ' (sub)' : ''}`,\n\t\t);\n\t}\n\n\tconst context_percent_display =\n\t\tcontext_percent === '?'\n\t\t\t? `?/${format_token_count(context_window)}`\n\t\t\t: `${context_percent}%/${format_token_count(context_window)}`;\n\tlet context_percent_str = context_percent_display;\n\tif (context_percent_value > 90) {\n\t\tcontext_percent_str = theme.fg('error', context_percent_display);\n\t} else if (context_percent_value > 70) {\n\t\tcontext_percent_str = theme.fg(\n\t\t\t'warning',\n\t\t\tcontext_percent_display,\n\t\t);\n\t}\n\tstats_parts.push(context_percent_str);\n\n\tlet stats_left = stats_parts.join(' ');\n\tlet stats_left_width = visibleWidth(stats_left);\n\tif (stats_left_width > width) {\n\t\tstats_left = truncateToWidth(stats_left, width, '...');\n\t\tstats_left_width = visibleWidth(stats_left);\n\t}\n\n\tconst model_name = ctx.model?.id || 'no-model';\n\tconst thinking_level = get_current_thinking_level(ctx);\n\tlet right_side_without_provider = model_name;\n\tif (ctx.model?.reasoning) {\n\t\tright_side_without_provider =\n\t\t\tthinking_level === 'off'\n\t\t\t\t? `${model_name} • thinking off`\n\t\t\t\t: `${model_name} • ${thinking_level}`;\n\t}\n\n\tlet right_side = right_side_without_provider;\n\tif (footer_data.getAvailableProviderCount() > 1 && ctx.model) {\n\t\tright_side = `(${ctx.model.provider}) ${right_side_without_provider}`;\n\t\tif (stats_left_width + 2 + visibleWidth(right_side) > width) {\n\t\t\tright_side = right_side_without_provider;\n\t\t}\n\t}\n\n\tconst right_side_width = visibleWidth(right_side);\n\tconst total_needed = stats_left_width + 2 + right_side_width;\n\tlet stats_line: string;\n\tif (total_needed <= width) {\n\t\tconst padding = ' '.repeat(\n\t\t\twidth - stats_left_width - right_side_width,\n\t\t);\n\t\tstats_line = stats_left + padding + right_side;\n\t} else {\n\t\tconst available_for_right = width - stats_left_width - 2;\n\t\tif (available_for_right > 0) {\n\t\t\tconst truncated_right = truncateToWidth(\n\t\t\t\tright_side,\n\t\t\t\tavailable_for_right,\n\t\t\t\t'',\n\t\t\t);\n\t\t\tconst truncated_right_width = visibleWidth(truncated_right);\n\t\t\tconst padding = ' '.repeat(\n\t\t\t\tMath.max(0, width - stats_left_width - truncated_right_width),\n\t\t\t);\n\t\t\tstats_line = stats_left + padding + truncated_right;\n\t\t} else {\n\t\t\tstats_line = stats_left;\n\t\t}\n\t}\n\n\tconst dim_stats_left = theme.fg('dim', stats_left);\n\tconst remainder = stats_line.slice(stats_left.length);\n\tconst dim_remainder = theme.fg('dim', remainder);\n\tconst lines = [\n\t\ttruncateToWidth(\n\t\t\ttheme.fg('dim', pwd),\n\t\t\twidth,\n\t\t\ttheme.fg('dim', '...'),\n\t\t),\n\t\tdim_stats_left + dim_remainder,\n\t];\n\n\tconst prompt_status = get_footer_prompt_status(\n\t\tactive_base_name,\n\t\tactive_layers,\n\t);\n\n\tconst other_statuses = Array.from(\n\t\tfooter_data.getExtensionStatuses().entries(),\n\t)\n\t\t.filter(([key]) => key !== 'preset')\n\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t.map(([, text]) => sanitize_status_text(text));\n\tconst combined_status_line = render_footer_status_line(\n\t\ttheme,\n\t\twidth,\n\t\tother_statuses,\n\t\tprompt_status,\n\t);\n\tif (combined_status_line) {\n\t\tlines.push(combined_status_line);\n\t}\n\n\treturn lines;\n}\n\nfunction set_status(\n\tctx: ExtensionContext,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): void {\n\tctx.ui.setStatus('preset', undefined);\n\tif (!ctx.hasUI) return;\n\tctx.ui.setFooter((tui, theme, footer_data) => {\n\t\tconst unsubscribe = footer_data.onBranchChange(() =>\n\t\t\ttui.requestRender(),\n\t\t);\n\t\treturn {\n\t\t\tdispose: unsubscribe,\n\t\t\tinvalidate() {},\n\t\t\trender(width: number) {\n\t\t\t\treturn render_footer_lines(\n\t\t\t\t\tctx,\n\t\t\t\t\ttheme,\n\t\t\t\t\tfooter_data,\n\t\t\t\t\twidth,\n\t\t\t\t\tactive_base_name,\n\t\t\t\t\tactive_layers,\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t});\n}\n\nfunction persist_state(\n\tpi: ExtensionAPI,\n\tctx: ExtensionContext,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): void {\n\tconst state = {\n\t\tbase_name: active_base_name ?? null,\n\t\tlayer_names: [...active_layers].sort(),\n\t};\n\tpi.appendEntry(PRESET_STATE_TYPE, state);\n\tsave_persisted_prompt_state(ctx.cwd, state);\n}\n\nfunction normalize_active_state(\n\tpresets: Record<string, LoadedPromptPreset>,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): {\n\tactive_base_name: string | undefined;\n\tactive_layers: Set<string>;\n} {\n\tconst next_base_name =\n\t\tactive_base_name && presets[active_base_name]?.kind === 'base'\n\t\t\t? active_base_name\n\t\t\t: undefined;\n\tconst next_layers = new Set(\n\t\t[...active_layers].filter(\n\t\t\t(name) => presets[name]?.kind === 'layer',\n\t\t),\n\t);\n\treturn {\n\t\tactive_base_name: next_base_name,\n\t\tactive_layers: next_layers,\n\t};\n}\n\nfunction parse_preset_flag(flag: string): string[] {\n\treturn flag\n\t\t.split(',')\n\t\t.map((item) => item.trim())\n\t\t.filter(Boolean);\n}\n\nfunction is_subcommand(command: string): boolean {\n\treturn [\n\t\t'help',\n\t\t'list',\n\t\t'show',\n\t\t'clear',\n\t\t'edit',\n\t\t'edit-global',\n\t\t'export-defaults',\n\t\t'delete',\n\t\t'reset',\n\t\t'reload',\n\t\t'base',\n\t\t'enable',\n\t\t'disable',\n\t\t'toggle',\n\t].includes(command);\n}\n\nfunction format_prompt_preset_help(): string {\n\treturn `Prompt presets append instructions to the system prompt.\n\nCommands:\n- /prompt-preset Open the preset picker\n- /prompt-preset show Show the active base and layers\n- /prompt-preset <name> Activate a base preset or toggle a layer\n- /prompt-preset base <name> Activate a base preset\n- /prompt-preset enable <layer> Enable a layer\n- /prompt-preset disable <layer> Disable a layer\n- /prompt-preset edit <name> Edit/create .pi/presets/<name>.md\n- /prompt-preset edit-global <name> Edit/create ~/.pi/agent/presets/<name>.md\n- /prompt-preset export-defaults Export built-ins to ~/.pi/agent/presets/*.md\n- /prompt-preset export-defaults project Export built-ins to .pi/presets/*.md\n- /prompt-preset reload Reload presets after manual file edits\n- /prompt-preset clear Clear active base and layers\n\nExamples:\n- /prompt-preset export-defaults\n- /prompt-preset edit-global terse\n- /prompt-preset base detailed\n- /prompt-preset enable bullets\n- /prompt-preset show\n\nAlias: /preset`;\n}\n\nexport default async function prompt_presets(pi: ExtensionAPI) {\n\tlet presets: Record<string, LoadedPromptPreset> = {};\n\tlet active_base_name: string | undefined;\n\tlet active_layers = new Set<string>();\n\n\tfunction get_base(\n\t\tname: string | undefined,\n\t): LoadedPromptPreset | undefined {\n\t\treturn name ? presets[name] : undefined;\n\t}\n\n\tfunction get_layer(name: string): LoadedPromptPreset | undefined {\n\t\tconst preset = presets[name];\n\t\treturn preset?.kind === 'layer' ? preset : undefined;\n\t}\n\n\tfunction commit_state(\n\t\tctx: ExtensionContext,\n\t\tnext_base_name: string | undefined,\n\t\tnext_layers: ReadonlySet<string>,\n\t\toptions?: { persist?: boolean; notify?: string },\n\t): void {\n\t\tactive_base_name = next_base_name;\n\t\tactive_layers = new Set(next_layers);\n\t\tset_status(ctx, active_base_name, active_layers);\n\t\tif (options?.persist !== false) {\n\t\t\tpersist_state(pi, ctx, active_base_name, active_layers);\n\t\t}\n\t\tif (options?.notify) {\n\t\t\tctx.ui.notify(options.notify, 'info');\n\t\t}\n\t}\n\n\tfunction activate_base(\n\t\tname: string | undefined,\n\t\tctx: ExtensionContext,\n\t\toptions?: { persist?: boolean },\n\t): boolean {\n\t\tif (!name) {\n\t\t\tcommit_state(ctx, undefined, active_layers, {\n\t\t\t\tpersist: options?.persist,\n\t\t\t\tnotify: 'Base preset cleared',\n\t\t\t});\n\t\t\treturn true;\n\t\t}\n\n\t\tconst preset = get_base(name);\n\t\tif (!preset) {\n\t\t\tctx.ui.notify(`Unknown base preset: ${name}`, 'warning');\n\t\t\treturn false;\n\t\t}\n\n\t\tcommit_state(ctx, preset.name, active_layers, {\n\t\t\tpersist: options?.persist,\n\t\t\tnotify: `Base preset \"${preset.name}\" activated`,\n\t\t});\n\t\treturn true;\n\t}\n\n\tfunction set_layer_enabled(\n\t\tname: string,\n\t\tenabled: boolean,\n\t\tctx: ExtensionContext,\n\t\toptions?: { persist?: boolean },\n\t): boolean {\n\t\tconst preset = get_layer(name);\n\t\tif (!preset) {\n\t\t\tctx.ui.notify(`Unknown prompt layer: ${name}`, 'warning');\n\t\t\treturn false;\n\t\t}\n\n\t\tconst next_layers = new Set(active_layers);\n\t\tif (enabled) {\n\t\t\tnext_layers.add(preset.name);\n\t\t} else {\n\t\t\tnext_layers.delete(preset.name);\n\t\t}\n\n\t\tcommit_state(ctx, active_base_name, next_layers, {\n\t\t\tpersist: options?.persist,\n\t\t\tnotify: enabled\n\t\t\t\t? `Layer \"${preset.name}\" enabled`\n\t\t\t\t: `Layer \"${preset.name}\" disabled`,\n\t\t});\n\t\treturn true;\n\t}\n\n\tfunction toggle_layer(\n\t\tname: string,\n\t\tctx: ExtensionContext,\n\t\toptions?: { persist?: boolean },\n\t): boolean {\n\t\treturn set_layer_enabled(\n\t\t\tname,\n\t\t\t!active_layers.has(name),\n\t\t\tctx,\n\t\t\toptions,\n\t\t);\n\t}\n\n\tasync function edit_preset(\n\t\tname: string,\n\t\tctx: ExtensionCommandContext,\n\t\tscope: 'project' | 'global' = 'project',\n\t): Promise<void> {\n\t\tconst existing = presets[name];\n\t\tconst kind_choice = await ctx.ui.select('Preset kind', [\n\t\t\texisting?.kind === 'layer'\n\t\t\t\t? 'layer (current)'\n\t\t\t\t: 'base (current)',\n\t\t\texisting?.kind === 'layer' ? 'base' : 'layer',\n\t\t]);\n\t\tif (!kind_choice) return;\n\t\tconst kind: PromptPresetKind = kind_choice.startsWith('layer')\n\t\t\t? 'layer'\n\t\t\t: 'base';\n\n\t\tconst description = await ctx.ui.input(\n\t\t\t`Description for ${name}`,\n\t\t\texisting?.description ?? '',\n\t\t);\n\t\tif (description === undefined) return;\n\n\t\tconst instructions = await ctx.ui.editor(\n\t\t\t`Edit ${kind} preset: ${name}`,\n\t\t\texisting?.instructions ?? '',\n\t\t);\n\t\tif (instructions === undefined) return;\n\n\t\tconst saved_path =\n\t\t\tscope === 'global'\n\t\t\t\t? save_global_prompt_preset_file(name, {\n\t\t\t\t\t\tkind,\n\t\t\t\t\t\tinstructions,\n\t\t\t\t\t\t...(description.trim()\n\t\t\t\t\t\t\t? { description: description.trim() }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t})\n\t\t\t\t: save_project_prompt_preset_file(ctx.cwd, name, {\n\t\t\t\t\t\tkind,\n\t\t\t\t\t\tinstructions,\n\t\t\t\t\t\t...(description.trim()\n\t\t\t\t\t\t\t? { description: description.trim() }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t});\n\n\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\tconst normalized = normalize_active_state(\n\t\t\tpresets,\n\t\t\tactive_base_name,\n\t\t\tactive_layers,\n\t\t);\n\t\tactive_base_name = normalized.active_base_name;\n\t\tactive_layers = normalized.active_layers;\n\n\t\tif (kind === 'base') {\n\t\t\tactivate_base(name, ctx);\n\t\t} else {\n\t\t\tset_layer_enabled(name, true, ctx);\n\t\t}\n\t\tctx.ui.notify(`Saved preset \"${name}\" to ${saved_path}`, 'info');\n\t}\n\n\tfunction export_default_presets(\n\t\tctx: ExtensionCommandContext,\n\t\tscope: 'project' | 'global',\n\t): void {\n\t\tconst dir =\n\t\t\tscope === 'global'\n\t\t\t\t? get_global_presets_dir()\n\t\t\t\t: get_project_presets_dir(ctx.cwd);\n\t\tlet written = 0;\n\t\tlet skipped = 0;\n\t\tfor (const [name, preset] of Object.entries(\n\t\t\tDEFAULT_PROMPT_PRESETS,\n\t\t)) {\n\t\t\tconst path = get_prompt_preset_file_path(dir, name);\n\t\t\tif (existsSync(path)) {\n\t\t\t\tskipped += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tsave_prompt_preset_file(dir, name, preset);\n\t\t\twritten += 1;\n\t\t}\n\n\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\tconst normalized = normalize_active_state(\n\t\t\tpresets,\n\t\t\tactive_base_name,\n\t\t\tactive_layers,\n\t\t);\n\t\tactive_base_name = normalized.active_base_name;\n\t\tactive_layers = normalized.active_layers;\n\t\tset_status(ctx, active_base_name, active_layers);\n\n\t\tctx.ui.notify(\n\t\t\t`Exported ${written} built-in preset file(s) to ${dir}${skipped ? ` (${skipped} already existed)` : ''}`,\n\t\t\t'info',\n\t\t);\n\t}\n\n\tfunction remove_custom_preset(\n\t\tname: string,\n\t\tctx: ExtensionCommandContext,\n\t\tmode: 'delete' | 'reset',\n\t): void {\n\t\tconst result = remove_project_prompt_preset(ctx.cwd, name);\n\t\tif (!result.removed) {\n\t\t\tctx.ui.notify(\n\t\t\t\t`No project-local preset named \"${name}\" to ${mode}`,\n\t\t\t\t'warning',\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\tconst normalized = normalize_active_state(\n\t\t\tpresets,\n\t\t\tactive_base_name,\n\t\t\tactive_layers,\n\t\t);\n\t\tactive_base_name = normalized.active_base_name;\n\t\tactive_layers = normalized.active_layers;\n\t\tset_status(ctx, active_base_name, active_layers);\n\t\tpersist_state(pi, ctx, active_base_name, active_layers);\n\n\t\tconst fallback = presets[name];\n\t\tif (mode === 'reset' && fallback) {\n\t\t\tctx.ui.notify(\n\t\t\t\t`Reset \"${name}\" to ${get_prompt_source_label(fallback.source)} preset`,\n\t\t\t\t'info',\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tctx.ui.notify(\n\t\t\tresult.remaining === 0\n\t\t\t\t? `Removed \"${name}\" and deleted ${result.path}`\n\t\t\t\t: `Removed \"${name}\" from ${result.path}`,\n\t\t\t'info',\n\t\t);\n\t}\n\n\tasync function show_manager(\n\t\tctx: ExtensionCommandContext,\n\t): Promise<void> {\n\t\tconst base_presets = list_base_presets(presets);\n\t\tconst layer_presets = list_layer_presets(presets);\n\t\tif (base_presets.length === 0 && layer_presets.length === 0) {\n\t\t\tctx.ui.notify('No prompt presets available', 'warning');\n\t\t\treturn;\n\t\t}\n\n\t\tconst initial_base = active_base_name;\n\t\tconst initial_layers = new Set(active_layers);\n\t\tlet selected_base = active_base_name;\n\t\tconst enabled_layers = new Set(active_layers);\n\n\t\tconst items: SettingItem[] = [];\n\t\tconst base_ids = new Set<string>();\n\t\tconst layer_ids = new Set<string>();\n\n\t\titems.push({\n\t\t\tid: '__header_base__',\n\t\t\tlabel: `── Base presets (${base_presets.length + 1}) ──`,\n\t\t\tdescription: '',\n\t\t\tcurrentValue: '',\n\t\t});\n\t\titems.push({\n\t\t\tid: NONE_BASE_ID,\n\t\t\tlabel: '(none)',\n\t\t\tdescription: 'No active base preset',\n\t\t\tcurrentValue: UNSELECTED,\n\t\t\tvalues: [SELECTED, UNSELECTED],\n\t\t});\n\t\tbase_ids.add(NONE_BASE_ID);\n\n\t\tfor (const preset of base_presets) {\n\t\t\titems.push({\n\t\t\t\tid: preset.name,\n\t\t\t\tlabel: preset.name,\n\t\t\t\tdescription: [\n\t\t\t\t\t`${get_prompt_source_label(preset.source)} • ${preset.description ?? 'base preset'}`,\n\t\t\t\t].join('\\n'),\n\t\t\t\tcurrentValue: UNSELECTED,\n\t\t\t\tvalues: [SELECTED, UNSELECTED],\n\t\t\t});\n\t\t\tbase_ids.add(preset.name);\n\t\t}\n\n\t\titems.push({\n\t\t\tid: '__header_layers__',\n\t\t\tlabel: `── Prompt layers (${layer_presets.length}) ──`,\n\t\t\tdescription: '',\n\t\t\tcurrentValue: '',\n\t\t});\n\t\tfor (const preset of layer_presets) {\n\t\t\titems.push({\n\t\t\t\tid: preset.name,\n\t\t\t\tlabel: preset.name,\n\t\t\t\tdescription: [\n\t\t\t\t\t`${get_prompt_source_label(preset.source)} • ${preset.description ?? 'layer'}`,\n\t\t\t\t].join('\\n'),\n\t\t\t\tcurrentValue: DISABLED,\n\t\t\t\tvalues: [ENABLED, DISABLED],\n\t\t\t});\n\t\t\tlayer_ids.add(preset.name);\n\t\t}\n\n\t\tfunction sync_values() {\n\t\t\tfor (const item of items) {\n\t\t\t\tif (base_ids.has(item.id)) {\n\t\t\t\t\tconst is_selected =\n\t\t\t\t\t\t(item.id === NONE_BASE_ID && !selected_base) ||\n\t\t\t\t\t\titem.id === selected_base;\n\t\t\t\t\titem.currentValue = is_selected ? SELECTED : UNSELECTED;\n\t\t\t\t} else if (layer_ids.has(item.id)) {\n\t\t\t\t\titem.currentValue = enabled_layers.has(item.id)\n\t\t\t\t\t\t? ENABLED\n\t\t\t\t\t\t: DISABLED;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsync_values();\n\n\t\tawait show_settings_modal(ctx, {\n\t\t\ttitle: 'Prompt presets',\n\t\t\tsubtitle: () =>\n\t\t\t\t`base: ${selected_base ?? '(none)'} • ${enabled_layers.size} layer(s) enabled`,\n\t\t\titems,\n\t\t\tmax_visible: Math.min(Math.max(items.length + 4, 8), 24),\n\t\t\tenable_search: true,\n\t\t\ton_change: (id, new_value) => {\n\t\t\t\tif (id.startsWith('__header_')) return;\n\n\t\t\t\tif (base_ids.has(id)) {\n\t\t\t\t\tselected_base =\n\t\t\t\t\t\tnew_value === SELECTED && id !== NONE_BASE_ID\n\t\t\t\t\t\t\t? id\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\tsync_values();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (layer_ids.has(id)) {\n\t\t\t\t\tif (new_value === ENABLED) {\n\t\t\t\t\t\tenabled_layers.add(id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tenabled_layers.delete(id);\n\t\t\t\t\t}\n\t\t\t\t\tsync_values();\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\tif (\n\t\t\tselected_base !== initial_base ||\n\t\t\t!sets_equal(initial_layers, enabled_layers)\n\t\t) {\n\t\t\tcommit_state(ctx, selected_base, enabled_layers, {\n\t\t\t\tnotify: 'Updated prompt preset selection',\n\t\t\t});\n\t\t}\n\t}\n\n\tpi.registerFlag('preset', {\n\t\tdescription:\n\t\t\t'Activate prompt config on startup. Accepts a base preset or comma-separated preset/layer names.',\n\t\ttype: 'string',\n\t});\n\n\tconst prompt_preset_command: Parameters<\n\t\tExtensionAPI['registerCommand']\n\t>[1] = {\n\t\tdescription:\n\t\t\t'Manage prompt presets and layers. Try: /prompt-preset help, /prompt-preset export-defaults, /prompt-preset edit-global terse',\n\t\tgetArgumentCompletions: (prefix) => {\n\t\t\tconst trimmed = prefix.trim();\n\t\t\tconst parts = trimmed ? trimmed.split(/\\s+/) : [];\n\t\t\tconst base_names = list_base_presets(presets).map(\n\t\t\t\t(preset) => preset.name,\n\t\t\t);\n\t\t\tconst layer_names = list_layer_presets(presets).map(\n\t\t\t\t(preset) => preset.name,\n\t\t\t);\n\t\t\tconst all_names = [...base_names, ...layer_names];\n\n\t\t\tif (parts.length <= 1) {\n\t\t\t\tconst query = parts[0] ?? '';\n\t\t\t\tconst subcommands = [\n\t\t\t\t\t'help',\n\t\t\t\t\t'list',\n\t\t\t\t\t'show',\n\t\t\t\t\t'clear',\n\t\t\t\t\t'edit',\n\t\t\t\t\t'edit-global',\n\t\t\t\t\t'export-defaults',\n\t\t\t\t\t'delete',\n\t\t\t\t\t'reset',\n\t\t\t\t\t'reload',\n\t\t\t\t\t'base',\n\t\t\t\t\t'enable',\n\t\t\t\t\t'disable',\n\t\t\t\t\t'toggle',\n\t\t\t\t];\n\t\t\t\treturn [\n\t\t\t\t\t...subcommands\n\t\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t\t.map((item) => ({ value: item, label: item })),\n\t\t\t\t\t...all_names\n\t\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t\t.map((item) => ({ value: item, label: item })),\n\t\t\t\t];\n\t\t\t}\n\n\t\t\tconst command = parts[0];\n\t\t\tconst query = parts.slice(1).join(' ');\n\t\t\tif (command === 'base') {\n\t\t\t\treturn base_names\n\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t.map((item) => ({ value: `base ${item}`, label: item }));\n\t\t\t}\n\t\t\tif (['enable', 'disable', 'toggle'].includes(command)) {\n\t\t\t\treturn layer_names\n\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t.map((item) => ({\n\t\t\t\t\t\tvalue: `${command} ${item}`,\n\t\t\t\t\t\tlabel: item,\n\t\t\t\t\t}));\n\t\t\t}\n\t\t\tif (command === 'edit' || command === 'edit-global') {\n\t\t\t\treturn all_names\n\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t.map((item) => ({\n\t\t\t\t\t\tvalue: `${command} ${item}`,\n\t\t\t\t\t\tlabel: item,\n\t\t\t\t\t}));\n\t\t\t}\n\t\t\tif (['delete', 'reset'].includes(command)) {\n\t\t\t\treturn all_names\n\t\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t\t.map((item) => ({\n\t\t\t\t\t\tvalue: `${command} ${item}`,\n\t\t\t\t\t\tlabel: item,\n\t\t\t\t\t}));\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\thandler: async (args, ctx) => {\n\t\t\tconst trimmed = args.trim();\n\t\t\tif (!trimmed) {\n\t\t\t\tif (ctx.hasUI) {\n\t\t\t\t\tawait show_manager(ctx);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\tformat_summary(active_base_name, active_layers, presets),\n\t\t\t\t\t'info',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst [first, ...rest] = trimmed.split(/\\s+/);\n\t\t\tconst arg = rest.join(' ').trim();\n\n\t\t\tswitch (first) {\n\t\t\t\tcase 'help':\n\t\t\t\t\tctx.ui.notify(format_prompt_preset_help(), 'info');\n\t\t\t\t\treturn;\n\t\t\t\tcase 'list':\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\tformat_summary(active_base_name, active_layers, presets),\n\t\t\t\t\t\t'info',\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'show':\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\tformat_active_details(\n\t\t\t\t\t\t\tactive_base_name,\n\t\t\t\t\t\t\tactive_layers,\n\t\t\t\t\t\t\tpresets,\n\t\t\t\t\t\t),\n\t\t\t\t\t\t'info',\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'clear':\n\t\t\t\t\tcommit_state(ctx, undefined, new Set(), {\n\t\t\t\t\t\tnotify: 'Cleared base preset and prompt layers',\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\tcase 'reload': {\n\t\t\t\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\t\t\t\tconst normalized = normalize_active_state(\n\t\t\t\t\t\tpresets,\n\t\t\t\t\t\tactive_base_name,\n\t\t\t\t\t\tactive_layers,\n\t\t\t\t\t);\n\t\t\t\t\tactive_base_name = normalized.active_base_name;\n\t\t\t\t\tactive_layers = normalized.active_layers;\n\t\t\t\t\tset_status(ctx, active_base_name, active_layers);\n\t\t\t\t\tctx.ui.notify('Reloaded prompt presets', 'info');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcase 'base':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset base <name> (alias: /preset)',\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\tactivate_base(arg, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'enable':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset enable <layer> (alias: /preset)',\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tset_layer_enabled(arg, true, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'disable':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset disable <layer> (alias: /preset)',\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tset_layer_enabled(arg, false, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'toggle':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset toggle <layer> (alias: /preset)',\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\ttoggle_layer(arg, ctx);\n\t\t\t\t\treturn;\n\t\t\t\tcase 'edit': {\n\t\t\t\t\tlet scope: 'project' | 'global' = 'project';\n\t\t\t\t\tlet name = arg;\n\t\t\t\t\tif (arg.startsWith('--global ')) {\n\t\t\t\t\t\tscope = 'global';\n\t\t\t\t\t\tname = arg.slice('--global '.length).trim();\n\t\t\t\t\t} else if (arg.startsWith('--project ')) {\n\t\t\t\t\t\tname = arg.slice('--project '.length).trim();\n\t\t\t\t\t}\n\t\t\t\t\tif (!name) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset edit [--global|--project] <name> (alias: /preset)',\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\tawait edit_preset(name, ctx, scope);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcase 'edit-global':\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: /prompt-preset edit-global <name> (alias: /preset)',\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\tawait edit_preset(arg, ctx, 'global');\n\t\t\t\t\treturn;\n\t\t\t\tcase 'export-defaults': {\n\t\t\t\t\tconst scope = arg || 'global';\n\t\t\t\t\tif (scope !== 'global' && scope !== 'project') {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset export-defaults [global|project] (alias: /preset)',\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\texport_default_presets(ctx, scope);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcase 'delete':\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: /prompt-preset delete <name> (alias: /preset)',\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\tremove_custom_preset(arg, ctx, 'delete');\n\t\t\t\t\treturn;\n\t\t\t\tcase 'reset':\n\t\t\t\t\tif (!arg) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Usage: /prompt-preset reset <name> (alias: /preset)',\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\tremove_custom_preset(arg, ctx, 'reset');\n\t\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (is_subcommand(first)) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Unsupported preset command: ${first}`,\n\t\t\t\t\t'warning',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst preset = presets[trimmed];\n\t\t\tif (!preset) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Unknown preset or layer: ${trimmed}. Try /prompt-preset help.`,\n\t\t\t\t\t'warning',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (preset.kind === 'base') {\n\t\t\t\tactivate_base(preset.name, ctx);\n\t\t\t} else {\n\t\t\t\ttoggle_layer(preset.name, ctx);\n\t\t\t}\n\t\t},\n\t};\n\n\tfor (const command_name of [\n\t\t'prompt-preset',\n\t\t'prompt-presets',\n\t\t'preset',\n\t]) {\n\t\tpi.registerCommand(command_name, prompt_preset_command);\n\t}\n\n\tpi.on('session_start', async (_event, ctx) => {\n\t\tpresets = load_prompt_presets(ctx.cwd);\n\t\tactive_base_name = undefined;\n\t\tactive_layers = new Set();\n\n\t\tconst preset_flag = pi.getFlag('preset');\n\t\tif (typeof preset_flag === 'string' && preset_flag.trim()) {\n\t\t\tfor (const name of parse_preset_flag(preset_flag)) {\n\t\t\t\tconst preset = presets[name];\n\t\t\t\tif (!preset) continue;\n\t\t\t\tif (preset.kind === 'base') {\n\t\t\t\t\tactive_base_name = name;\n\t\t\t\t} else {\n\t\t\t\t\tactive_layers.add(name);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst normalized = normalize_active_state(\n\t\t\t\tpresets,\n\t\t\t\tactive_base_name,\n\t\t\t\tactive_layers,\n\t\t\t);\n\t\t\tactive_base_name = normalized.active_base_name;\n\t\t\tactive_layers = normalized.active_layers;\n\t\t\tset_status(ctx, active_base_name, active_layers);\n\t\t\treturn;\n\t\t}\n\n\t\tconst restored = get_last_preset_state(ctx) ??\n\t\t\tload_persisted_prompt_state(ctx.cwd) ?? {\n\t\t\t\tbase_name: DEFAULT_BASE_PROMPT_PRESET_NAME,\n\t\t\t\tlayer_names: [],\n\t\t\t};\n\t\tactive_base_name = restored.base_name ?? undefined;\n\t\tactive_layers = new Set(restored.layer_names ?? []);\n\t\tconst normalized = normalize_active_state(\n\t\t\tpresets,\n\t\t\tactive_base_name,\n\t\t\tactive_layers,\n\t\t);\n\t\tactive_base_name = normalized.active_base_name;\n\t\tactive_layers = normalized.active_layers;\n\t\tset_status(ctx, active_base_name, active_layers);\n\t});\n\n\tpi.on('before_agent_start', async (event) => {\n\t\tconst blocks: string[] = [];\n\t\tconst base = get_base(active_base_name);\n\t\tif (base?.instructions.trim()) {\n\t\t\tblocks.push(\n\t\t\t\t`## Active Base Prompt: ${base.name}\\n${base.instructions.trim()}`,\n\t\t\t);\n\t\t}\n\n\t\tconst layer_blocks = [...active_layers]\n\t\t\t.sort()\n\t\t\t.map((name) => presets[name])\n\t\t\t.filter((preset): preset is LoadedPromptPreset =>\n\t\t\t\tBoolean(preset?.instructions.trim()),\n\t\t\t)\n\t\t\t.map(\n\t\t\t\t(preset) =>\n\t\t\t\t\t`### ${preset.name}\\n${preset.instructions.trim()}`,\n\t\t\t);\n\t\tif (layer_blocks.length > 0) {\n\t\t\tblocks.push(\n\t\t\t\t`## Active Prompt Layers\\n\\n${layer_blocks.join('\\n\\n')}`,\n\t\t\t);\n\t\t}\n\n\t\tif (blocks.length === 0) return;\n\t\treturn {\n\t\t\tsystemPrompt: `${event.systemPrompt}\\n\\n${blocks.join('\\n\\n')}`,\n\t\t};\n\t});\n\n\tpi.on('session_shutdown', async (_event, ctx) => {\n\t\tctx.ui.setStatus('preset', undefined);\n\t\tctx.ui.setFooter(undefined);\n\t});\n}\n","// Session name — AI-powered session naming\n// Adapted from Thomas Lopes' pi dotfiles\n\nimport { complete, type Message } from '@mariozechner/pi-ai';\nimport type {\n\tExtensionAPI,\n\tSessionEntry,\n} from '@mariozechner/pi-coding-agent';\nimport {\n\tBorderedLoader,\n\tconvertToLlm,\n\tserializeConversation,\n} from '@mariozechner/pi-coding-agent';\n\nconst SYSTEM_PROMPT = `You are a session naming assistant. Given a conversation history, generate a short, descriptive session name (2-5 words) that captures the main topic or task.\n\nGuidelines:\n- Be concise but specific\n- Use kebab-case or natural language\n- Focus on the core task/question\n- Avoid generic names like \"discussion\" or \"conversation\"\n- No quotes, no punctuation at the end\n\nExamples:\n- \"fix auth bug\" -> \"fix-auth-bug\" or \"authentication fix\"\n- \"how do I deploy to vercel\" -> \"vercel deployment\"\n- \"explain react hooks\" -> \"react hooks explanation\"\n- \"optimize database queries\" -> \"db query optimization\"\n\nOutput ONLY the session name, nothing else.`;\n\nconst AUTO_NAME_THRESHOLD = 1;\nconst MAX_CHARS = 4000;\nconst MAX_NAME_LEN = 50;\n\nfunction clean_name(value: string): string {\n\treturn value\n\t\t.replace(/^[\"']|[\"']$/g, '')\n\t\t.replace(/\\n/g, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim()\n\t\t.slice(0, MAX_NAME_LEN);\n}\n\nfunction truncate_conversation(value: string): string {\n\treturn value.length > MAX_CHARS\n\t\t? value.slice(0, MAX_CHARS) + '\\n...'\n\t\t: value;\n}\n\nasync function generate_session_name(\n\tctx: {\n\t\tmodelRegistry: {\n\t\t\tgetApiKeyAndHeaders: (\n\t\t\t\tmodel: NonNullable<\n\t\t\t\t\tParameters<\n\t\t\t\t\t\tParameters<ExtensionAPI['registerCommand']>[1]['handler']\n\t\t\t\t\t>[1]['model']\n\t\t\t\t>,\n\t\t\t) => Promise<any>;\n\t\t};\n\t},\n\tmodel: NonNullable<\n\t\tParameters<\n\t\t\tParameters<ExtensionAPI['registerCommand']>[1]['handler']\n\t\t>[1]['model']\n\t>,\n\tconversation_text: string,\n\tsignal?: AbortSignal,\n): Promise<string | null> {\n\tconst auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);\n\tif (!auth.ok || !auth.apiKey) {\n\t\tthrow new Error(\n\t\t\tauth.ok ? `No API key for ${model.provider}` : auth.error,\n\t\t);\n\t}\n\n\tconst user_message: Message = {\n\t\trole: 'user',\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: 'text',\n\t\t\t\ttext: `## Conversation History\\n\\n${truncate_conversation(conversation_text)}\\n\\nGenerate a concise session name for this conversation.`,\n\t\t\t},\n\t\t],\n\t\ttimestamp: Date.now(),\n\t};\n\n\tconst response = await complete(\n\t\tmodel,\n\t\t{ systemPrompt: SYSTEM_PROMPT, messages: [user_message] },\n\t\t{ apiKey: auth.apiKey, headers: auth.headers, signal },\n\t);\n\n\tif (response.stopReason === 'aborted') {\n\t\treturn null;\n\t}\n\n\treturn clean_name(\n\t\tresponse.content\n\t\t\t.filter(\n\t\t\t\t(c): c is { type: 'text'; text: string } => c.type === 'text',\n\t\t\t)\n\t\t\t.map((c) => c.text.trim())\n\t\t\t.join(' '),\n\t);\n}\n\nexport default async function session_name(pi: ExtensionAPI) {\n\tlet auto_named_attempted = false;\n\n\tpi.on('agent_end', async (_event, ctx) => {\n\t\tif (!ctx.hasUI || !ctx.model) return;\n\t\tif (pi.getSessionName() || auto_named_attempted) return;\n\n\t\tconst branch = ctx.sessionManager.getBranch();\n\t\tconst user_messages = branch.filter(\n\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\tentry.type === 'message' && entry.message.role === 'user',\n\t\t);\n\t\tif (user_messages.length < AUTO_NAME_THRESHOLD) return;\n\n\t\tauto_named_attempted = true;\n\t\tconst messages = branch\n\t\t\t.filter(\n\t\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\t\tentry.type === 'message',\n\t\t\t)\n\t\t\t.map((entry) => entry.message);\n\t\tif (messages.length === 0) return;\n\n\t\tconst conversation_text = serializeConversation(\n\t\t\tconvertToLlm(messages),\n\t\t);\n\n\t\tgenerate_session_name(ctx, ctx.model, conversation_text)\n\t\t\t.then((name) => {\n\t\t\t\tif (!name) return;\n\t\t\t\tpi.setSessionName(name);\n\t\t\t\tctx.ui.notify(`Auto-named: ${name}`, 'info');\n\t\t\t})\n\t\t\t.catch((err) => {\n\t\t\t\tconsole.error('Auto-naming failed:', err);\n\t\t\t});\n\t});\n\n\tpi.on('session_start', async () => {\n\t\tauto_named_attempted = false;\n\t});\n\n\tpi.registerCommand('session-name', {\n\t\tdescription:\n\t\t\t'Set, show, or auto-generate the current session name',\n\t\thandler: async (args, ctx) => {\n\t\t\tconst trimmed = args.trim();\n\n\t\t\tif (!trimmed) {\n\t\t\t\tconst current = pi.getSessionName();\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\tcurrent ? `Session: ${current}` : 'No session name set',\n\t\t\t\t\t'info',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (trimmed === '--auto' || trimmed === '-a') {\n\t\t\t\tif (!ctx.hasUI || !ctx.model) {\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t'Auto-naming requires interactive mode and a selected model',\n\t\t\t\t\t\t'error',\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst branch = ctx.sessionManager.getBranch();\n\t\t\t\tconst messages = branch\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\t\t\t\tentry.type === 'message',\n\t\t\t\t\t)\n\t\t\t\t\t.map((entry) => entry.message);\n\t\t\t\tif (messages.length === 0) {\n\t\t\t\t\tctx.ui.notify('No conversation to analyze', 'error');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst conversation_text = serializeConversation(\n\t\t\t\t\tconvertToLlm(messages),\n\t\t\t\t);\n\n\t\t\t\tconst result = await ctx.ui.custom<string | null>(\n\t\t\t\t\t(tui, theme, _kb, done) => {\n\t\t\t\t\t\tconst loader = new BorderedLoader(\n\t\t\t\t\t\t\ttui,\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\t'Generating session name...',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tloader.onAbort = () => done(null);\n\n\t\t\t\t\t\tgenerate_session_name(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\tctx.model!,\n\t\t\t\t\t\t\tconversation_text,\n\t\t\t\t\t\t\tloader.signal,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.then(done)\n\t\t\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\t\t\tconsole.error('Auto-naming failed:', err);\n\t\t\t\t\t\t\t\tdone(null);\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn loader;\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (result === null) {\n\t\t\t\t\tctx.ui.notify('Auto-naming cancelled', 'info');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!result) {\n\t\t\t\t\tctx.ui.notify('Failed to generate name', 'error');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tpi.setSessionName(result);\n\t\t\t\tctx.ui.notify(`Session named: ${result}`, 'info');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tpi.setSessionName(clean_name(trimmed));\n\t\t\tctx.ui.notify(`Session named: ${clean_name(trimmed)}`, 'info');\n\t\t},\n\t});\n}\n","// Composable programmatic API for my-pi\n// Extension loading patterns inspired by pi-vs-claude-code\n\nimport type { Api, Model } from '@mariozechner/pi-ai';\nimport {\n\tInteractiveMode,\n\tSessionManager,\n\tcreateAgentSessionFromServices,\n\tcreateAgentSessionRuntime,\n\tcreateAgentSessionServices,\n\tgetAgentDir,\n\trunPrintMode,\n\trunRpcMode,\n\ttype ExtensionFactory,\n\ttype LoadExtensionsResult,\n} from '@mariozechner/pi-coding-agent';\nimport confirm_destructive_extension from '@spences10/pi-confirm-destructive';\nimport lsp_extension from '@spences10/pi-lsp';\nimport mcp_extension from '@spences10/pi-mcp';\nimport nopeek_extension from '@spences10/pi-nopeek';\nimport omnisearch_extension from '@spences10/pi-omnisearch';\nimport { apply_project_trust_untrusted_defaults } from '@spences10/pi-project-trust';\nimport recall_extension from '@spences10/pi-recall';\nimport filter_output_extension from '@spences10/pi-redact';\nimport skills_extension, {\n\tcreate_skills_manager,\n} from '@spences10/pi-skills';\nimport sqlite_tools_extension from '@spences10/pi-sqlite-tools';\nimport team_mode_extension from '@spences10/pi-team-mode';\nimport { create_telemetry_extension } from '@spences10/pi-telemetry';\nimport { createRequire } from 'node:module';\nimport { dirname, isAbsolute, relative, resolve } from 'node:path';\nimport hooks_resolution_extension from './extensions/hooks-resolution/index.js';\nimport {\n\tBUILTIN_EXTENSIONS,\n\tis_builtin_extension_active,\n\tload_builtin_extensions_config,\n\ttype BuiltinExtensionKey,\n} from './extensions/manager/config.js';\nimport { create_extensions_extension } from './extensions/manager/index.js';\nimport prompt_presets_extension from './extensions/prompt-presets/index.js';\nimport session_name_extension from './extensions/session-name/index.js';\n\nexport type MyPiRuntimeMode =\n\t| 'interactive'\n\t| 'print'\n\t| 'json'\n\t| 'rpc';\n\nexport interface CreateMyPiOptions {\n\tcwd?: string;\n\tagent_dir?: string;\n\textensions?: string[];\n\textensionFactories?: ExtensionFactory[];\n\truntime_mode?: MyPiRuntimeMode;\n\tmcp?: boolean;\n\tskills?: boolean;\n\tfilter_output?: boolean;\n\trecall?: boolean;\n\tnopeek?: boolean;\n\tomnisearch?: boolean;\n\tsqlite_tools?: boolean;\n\tprompt_presets?: boolean;\n\tlsp?: boolean;\n\tsession_name?: boolean;\n\tconfirm_destructive?: boolean;\n\thooks_resolution?: boolean;\n\tteam_mode?: boolean;\n\ttelemetry?: boolean;\n\ttelemetry_db_path?: string;\n\tmodel?: string;\n\tselected_tools?: string[];\n\tselected_skills?: string[];\n\tsession_dir?: string;\n\tsystem_prompt?: string;\n\tappend_system_prompt?: string;\n\tuntrusted_repo?: boolean;\n}\n\nconst BUILTIN_EXTENSION_FACTORIES: Record<\n\tBuiltinExtensionKey,\n\tExtensionFactory\n> = {\n\tmcp: mcp_extension,\n\tskills: skills_extension,\n\t'filter-output': filter_output_extension,\n\trecall: recall_extension,\n\tnopeek: nopeek_extension,\n\tomnisearch: omnisearch_extension,\n\t'sqlite-tools': sqlite_tools_extension,\n\t'prompt-presets': prompt_presets_extension,\n\tlsp: lsp_extension,\n\t'session-name': session_name_extension,\n\t'confirm-destructive': confirm_destructive_extension,\n\t'hooks-resolution': hooks_resolution_extension,\n\t'team-mode': team_mode_extension,\n};\n\nconst require = createRequire(import.meta.url);\nconst PACKAGE_THEME_DIR = resolve(\n\tdirname(require.resolve('@spences10/pi-themes/package.json')),\n\t'themes',\n);\nconst PI_AGENT_DIR_ENV = 'PI_CODING_AGENT_DIR';\nconst MY_PI_RUNTIME_MODE_ENV = 'MY_PI_RUNTIME_MODE';\n\nconst UNTRUSTED_CHILD_ENV_DEFAULTS: Record<string, string> = {\n\tMY_PI_CHILD_ENV_ALLOWLIST: '',\n\tMY_PI_MCP_ENV_ALLOWLIST: '',\n\tMY_PI_LSP_ENV_ALLOWLIST: '',\n\tMY_PI_HOOKS_ENV_ALLOWLIST: '',\n\tMY_PI_TEAM_MODE_ENV_ALLOWLIST: '',\n};\n\nexport function apply_untrusted_repo_defaults(\n\tenv: NodeJS.ProcessEnv = process.env,\n): string[] {\n\tconst applied = apply_project_trust_untrusted_defaults(env);\n\tfor (const [key, value] of Object.entries(\n\t\tUNTRUSTED_CHILD_ENV_DEFAULTS,\n\t)) {\n\t\tif (env[key] !== undefined) continue;\n\t\tenv[key] = value;\n\t\tapplied.push(key);\n\t}\n\treturn applied;\n}\n\nfunction is_resource_enabled(value: string | undefined): boolean {\n\tconst normalized = value?.trim().toLowerCase();\n\tif (!normalized) return true;\n\tif (['0', 'false', 'no', 'skip', 'disable'].includes(normalized)) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport function is_project_local_skill_path(\n\tcwd: string,\n\tfile_path: string | undefined,\n): boolean {\n\tif (!file_path) return false;\n\tconst absolute = resolve(cwd, file_path);\n\tconst relative_path = relative(cwd, absolute);\n\tif (\n\t\t!relative_path ||\n\t\trelative_path.startsWith('..') ||\n\t\tisAbsolute(relative_path)\n\t) {\n\t\treturn false;\n\t}\n\tconst parts = relative_path.split(/[\\\\/]+/);\n\treturn parts.some(\n\t\t(part, index) =>\n\t\t\t(part === '.pi' || part === '.claude') &&\n\t\t\tparts[index + 1] === 'skills',\n\t);\n}\n\nfunction resolve_agent_dir(cwd: string, agent_dir?: string): string {\n\treturn agent_dir ? resolve(cwd, agent_dir) : getAgentDir();\n}\n\nconst NON_INTERACTIVE_UI_ONLY_BUILTINS: BuiltinExtensionKey[] = [\n\t'session-name',\n];\n\ninterface ModelRegistryLike {\n\tgetAll(): Model<Api>[];\n}\n\nexport function resolve_model_reference(\n\tmodel_reference: string | undefined,\n\tmodel_registry: ModelRegistryLike,\n): Model<Api> | undefined {\n\tif (!model_reference) return undefined;\n\tconst models = model_registry.getAll();\n\tconst lower_reference = model_reference.toLowerCase();\n\tconst slash_index = model_reference.indexOf('/');\n\n\tif (slash_index !== -1) {\n\t\tconst maybe_provider = model_reference.slice(0, slash_index);\n\t\tconst model_id = model_reference.slice(slash_index + 1);\n\t\tconst provider = models.find(\n\t\t\t(model) =>\n\t\t\t\tmodel.provider.toLowerCase() === maybe_provider.toLowerCase(),\n\t\t)?.provider;\n\n\t\tif (provider) {\n\t\t\tconst provider_match = models.find(\n\t\t\t\t(model) =>\n\t\t\t\t\tmodel.provider === provider &&\n\t\t\t\t\tmodel.id.toLowerCase() === model_id.toLowerCase(),\n\t\t\t);\n\t\t\tif (provider_match) return provider_match;\n\t\t}\n\t}\n\n\treturn models.find((model) => {\n\t\tconst id = model.id.toLowerCase();\n\t\tconst full_id = `${model.provider}/${model.id}`.toLowerCase();\n\t\treturn id === lower_reference || full_id === lower_reference;\n\t});\n}\n\nexport function get_force_disabled_builtins(\n\toptions: Pick<\n\t\tCreateMyPiOptions,\n\t\t| 'runtime_mode'\n\t\t| 'mcp'\n\t\t| 'skills'\n\t\t| 'filter_output'\n\t\t| 'recall'\n\t\t| 'nopeek'\n\t\t| 'omnisearch'\n\t\t| 'sqlite_tools'\n\t\t| 'prompt_presets'\n\t\t| 'lsp'\n\t\t| 'session_name'\n\t\t| 'confirm_destructive'\n\t\t| 'hooks_resolution'\n\t\t| 'team_mode'\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.filter_output) force_disabled.add('filter-output');\n\tif (!options.recall) force_disabled.add('recall');\n\tif (!options.nopeek) force_disabled.add('nopeek');\n\tif (!options.omnisearch) force_disabled.add('omnisearch');\n\tif (!options.sqlite_tools) force_disabled.add('sqlite-tools');\n\tif (!options.prompt_presets) force_disabled.add('prompt-presets');\n\tif (!options.lsp) force_disabled.add('lsp');\n\tif (!options.session_name) force_disabled.add('session-name');\n\tif (!options.confirm_destructive)\n\t\tforce_disabled.add('confirm-destructive');\n\tif (!options.hooks_resolution)\n\t\tforce_disabled.add('hooks-resolution');\n\tif (!options.team_mode) force_disabled.add('team-mode');\n\tif (\n\t\toptions.runtime_mode &&\n\t\toptions.runtime_mode !== 'interactive'\n\t) {\n\t\tfor (const key of NON_INTERACTIVE_UI_ONLY_BUILTINS) {\n\t\t\tforce_disabled.add(key);\n\t\t}\n\t}\n\treturn force_disabled;\n}\n\nfunction create_builtin_extension_factory(\n\tkey: BuiltinExtensionKey,\n\textension: ExtensionFactory,\n\tforce_disabled: ReadonlySet<BuiltinExtensionKey>,\n): ExtensionFactory {\n\treturn async (pi) => {\n\t\tconst config = load_builtin_extensions_config();\n\t\tif (!is_builtin_extension_active(config, key, force_disabled)) {\n\t\t\treturn;\n\t\t}\n\t\tawait extension(pi);\n\t};\n}\n\nfunction create_extensions_override(\n\tmanaged_inline_paths: string[],\n): (base: LoadExtensionsResult) => LoadExtensionsResult {\n\tconst managed_paths = new Set(managed_inline_paths);\n\treturn (base) => {\n\t\tconst managed = new Map(\n\t\t\tbase.extensions.map((extension) => [extension.path, extension]),\n\t\t);\n\t\tconst ordered_managed = managed_inline_paths\n\t\t\t.map((path) => managed.get(path))\n\t\t\t.filter(\n\t\t\t\t(\n\t\t\t\t\textension,\n\t\t\t\t): extension is LoadExtensionsResult['extensions'][number] =>\n\t\t\t\t\tBoolean(extension),\n\t\t\t);\n\t\tconst others = base.extensions.filter(\n\t\t\t(extension) => !managed_paths.has(extension.path),\n\t\t);\n\t\treturn {\n\t\t\t...base,\n\t\t\textensions: [...ordered_managed, ...others],\n\t\t};\n\t};\n}\n\nexport async function create_my_pi(options: CreateMyPiOptions = {}) {\n\tconst {\n\t\tcwd = process.cwd(),\n\t\tagent_dir,\n\t\textensions = [],\n\t\textensionFactories: user_factories = [],\n\t\truntime_mode = 'interactive',\n\t\tmcp = true,\n\t\tskills = true,\n\t\tfilter_output = true,\n\t\trecall = true,\n\t\tnopeek = true,\n\t\tomnisearch = true,\n\t\tsqlite_tools = true,\n\t\tprompt_presets = true,\n\t\tlsp = true,\n\t\tsession_name = true,\n\t\tconfirm_destructive = true,\n\t\thooks_resolution = true,\n\t\tteam_mode = true,\n\t\ttelemetry,\n\t\ttelemetry_db_path,\n\t\tmodel,\n\t\tselected_tools,\n\t\tselected_skills,\n\t\tsession_dir,\n\t\tsystem_prompt,\n\t\tappend_system_prompt,\n\t\tuntrusted_repo = false,\n\t} = options;\n\n\tif (untrusted_repo) {\n\t\tapply_untrusted_repo_defaults();\n\t}\n\n\tconst effective_agent_dir = resolve_agent_dir(cwd, agent_dir);\n\tif (agent_dir) {\n\t\tprocess.env[PI_AGENT_DIR_ENV] = effective_agent_dir;\n\t}\n\tprocess.env[MY_PI_RUNTIME_MODE_ENV] = runtime_mode;\n\n\tconst resolved_extensions = extensions.map((p) => resolve(cwd, p));\n\tconst force_disabled = get_force_disabled_builtins({\n\t\truntime_mode,\n\t\tmcp,\n\t\tskills,\n\t\tfilter_output,\n\t\trecall,\n\t\tnopeek,\n\t\tomnisearch,\n\t\tsqlite_tools,\n\t\tprompt_presets,\n\t\tlsp,\n\t\tsession_name,\n\t\tconfirm_destructive,\n\t\thooks_resolution,\n\t\tteam_mode,\n\t});\n\tconst managed_extension_factories: ExtensionFactory[] = [\n\t\tcreate_telemetry_extension({\n\t\t\tenabled: telemetry,\n\t\t\tdb_path: telemetry_db_path,\n\t\t\tcwd,\n\t\t}),\n\t\tcreate_extensions_extension({ force_disabled }),\n\t\t...BUILTIN_EXTENSIONS.map((extension) =>\n\t\t\tcreate_builtin_extension_factory(\n\t\t\t\textension.key,\n\t\t\t\tBUILTIN_EXTENSION_FACTORIES[extension.key],\n\t\t\t\tforce_disabled,\n\t\t\t),\n\t\t),\n\t];\n\tconst managed_inline_paths = managed_extension_factories.map(\n\t\t(_, index) => `<inline:${index + 1}>`,\n\t);\n\n\tconst create_runtime = async ({\n\t\tcwd: runtime_cwd,\n\t\tsessionManager,\n\t\tsessionStartEvent,\n\t}: {\n\t\tcwd: string;\n\t\tsessionManager: SessionManager;\n\t\tsessionStartEvent?: unknown;\n\t}) => {\n\t\tconst services = await createAgentSessionServices({\n\t\t\tcwd: runtime_cwd,\n\t\t\tagentDir: effective_agent_dir,\n\t\t\tresourceLoaderOptions: {\n\t\t\t\t...(system_prompt !== undefined\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tsystemPromptOverride: () => system_prompt,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\t...(append_system_prompt !== undefined\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tappendSystemPromptOverride: (base: string[]) => [\n\t\t\t\t\t\t\t\t...base,\n\t\t\t\t\t\t\t\tappend_system_prompt,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\tadditionalExtensionPaths: [...resolved_extensions],\n\t\t\t\t...(runtime_mode === 'interactive'\n\t\t\t\t\t? { additionalThemePaths: [PACKAGE_THEME_DIR] }\n\t\t\t\t\t: {}),\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 include_project_skills = is_resource_enabled(\n\t\t\t\t\t\tprocess.env.MY_PI_PROJECT_SKILLS,\n\t\t\t\t\t);\n\t\t\t\t\tconst skills_manager = create_skills_manager();\n\t\t\t\t\tconst selected_skill_names = selected_skills?.length\n\t\t\t\t\t\t? new Set(selected_skills)\n\t\t\t\t\t\t: undefined;\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\tif (\n\t\t\t\t\t\t\t\t!include_project_skills &&\n\t\t\t\t\t\t\t\tis_project_local_skill_path(\n\t\t\t\t\t\t\t\t\truntime_cwd,\n\t\t\t\t\t\t\t\t\tskill.filePath,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tselected_skill_names &&\n\t\t\t\t\t\t\t\t!selected_skill_names.has(skill.name)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn skills_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\tconst requested_model = resolve_model_reference(\n\t\t\tmodel,\n\t\t\tservices.modelRegistry,\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\t...(requested_model ? { model: requested_model } : {}),\n\t\t\t\t...(selected_tools?.length ? { tools: selected_tools } : {}),\n\t\t\t})),\n\t\t\tservices,\n\t\t\tdiagnostics: services.diagnostics,\n\t\t};\n\t};\n\n\treturn createAgentSessionRuntime(create_runtime, {\n\t\tcwd,\n\t\tagentDir: effective_agent_dir,\n\t\tsessionManager: SessionManager.create(\n\t\t\tcwd,\n\t\t\tsession_dir ? resolve(cwd, session_dir) : undefined,\n\t\t),\n\t});\n}\n\nexport { InteractiveMode, runPrintMode, runRpcMode };\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 { a as is_project_local_skill_path, c as runRpcMode, i as get_force_disabled_builtins, n as apply_untrusted_repo_defaults, o as resolve_model_reference, r as create_my_pi, s as runPrintMode, t as InteractiveMode } from "./api-ByzD9jne.js";
1
+ import { a as is_project_local_skill_path, c as runRpcMode, i as get_force_disabled_builtins, n as apply_untrusted_repo_defaults, o as resolve_model_reference, r as create_my_pi, s as runPrintMode, t as InteractiveMode } from "./api-CJN_JYzx.js";
2
2
  export { InteractiveMode, apply_untrusted_repo_defaults, create_my_pi, get_force_disabled_builtins, is_project_local_skill_path, resolve_model_reference, runPrintMode, runRpcMode };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { r as create_my_pi } from "./api-ByzD9jne.js";
2
+ import { r as create_my_pi } from "./api-CJN_JYzx.js";
3
3
  import { InteractiveMode, runPrintMode, runRpcMode } from "@mariozechner/pi-coding-agent";
4
4
  import { defineCommand, renderUsage, runMain } from "citty";
5
5
  import { readFileSync } from "node:fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-pi",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "description": "Composable pi coding agent with MCP, LSP, prompt presets, and local eval telemetry",
5
5
  "keywords": [
6
6
  "cli",
@@ -37,26 +37,26 @@
37
37
  "./cli": "./dist/index.js"
38
38
  },
39
39
  "dependencies": {
40
- "@mariozechner/pi-ai": "^0.70.6",
41
- "@mariozechner/pi-coding-agent": "^0.70.6",
42
- "@mariozechner/pi-tui": "^0.70.6",
40
+ "@mariozechner/pi-ai": "^0.71.1",
41
+ "@mariozechner/pi-coding-agent": "^0.71.1",
42
+ "@mariozechner/pi-tui": "^0.71.1",
43
43
  "citty": "^0.2.2",
44
- "typebox": "^1.1.35",
45
- "@spences10/pi-child-env": "0.1.2",
46
- "@spences10/pi-lsp": "0.0.8",
44
+ "typebox": "^1.1.36",
47
45
  "@spences10/pi-confirm-destructive": "0.0.5",
46
+ "@spences10/pi-mcp": "0.0.11",
47
+ "@spences10/pi-child-env": "0.1.2",
48
+ "@spences10/pi-omnisearch": "0.0.3",
48
49
  "@spences10/pi-nopeek": "0.0.3",
50
+ "@spences10/pi-lsp": "0.0.9",
49
51
  "@spences10/pi-project-trust": "0.0.3",
50
- "@spences10/pi-mcp": "0.0.9",
52
+ "@spences10/pi-recall": "0.0.3",
51
53
  "@spences10/pi-redact": "0.0.3",
52
- "@spences10/pi-omnisearch": "0.0.3",
53
- "@spences10/pi-skills": "0.0.5",
54
+ "@spences10/pi-skills": "0.0.7",
54
55
  "@spences10/pi-sqlite-tools": "0.0.3",
55
- "@spences10/pi-recall": "0.0.3",
56
- "@spences10/pi-team-mode": "0.0.6",
57
- "@spences10/pi-telemetry": "0.0.3",
56
+ "@spences10/pi-team-mode": "0.0.8",
58
57
  "@spences10/pi-themes": "0.0.2",
59
- "@spences10/pi-tui-modal": "0.0.2"
58
+ "@spences10/pi-telemetry": "0.0.4",
59
+ "@spences10/pi-tui-modal": "0.0.4"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@changesets/cli": "^2.31.0",
@@ -74,7 +74,7 @@
74
74
  "check": "pnpm --filter \"./packages/*\" run build && vp check && pnpm --filter \"./packages/*\" run check",
75
75
  "check:fix": "vp check --fix",
76
76
  "format": "vp check --fix",
77
- "test": "pnpm --filter \"./packages/*\" run build && sh -c 'if [ \"$#\" -gt 0 ]; then vp test \"$@\"; else vp test && pnpm --filter \"./packages/*\" run test; fi' --",
77
+ "test": "pnpm --filter \"./packages/*\" run build && vp pack && sh -c 'if [ \"$#\" -gt 0 ]; then vp test \"$@\"; else vp test && pnpm --filter \"./packages/*\" run test; fi' --",
78
78
  "test:watch": "vp test watch",
79
79
  "changeset": "changeset",
80
80
  "version": "changeset version",