my-pi 0.1.47 → 0.1.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +1 -1
- package/dist/{builtin-registry-DZ9GaW_e.js → builtin-registry-DpLtHlYK.js} +3 -3
- package/dist/{builtin-registry-DZ9GaW_e.js.map → builtin-registry-DpLtHlYK.js.map} +1 -1
- package/dist/{hooks-resolution-D89Ewkyw.js → hooks-resolution-DNTz2NXs.js} +43 -35
- package/dist/hooks-resolution-DNTz2NXs.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/{prompt-presets-Cl3vBbc-.js → prompt-presets-BhlErXaD.js} +58 -55
- package/dist/prompt-presets-BhlErXaD.js.map +1 -0
- package/package.json +17 -15
- package/dist/hooks-resolution-D89Ewkyw.js.map +0 -1
- package/dist/prompt-presets-Cl3vBbc-.js.map +0 -1
package/dist/api.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as BUILTIN_EXTENSION_REGISTRY, t as BUILTIN_EXTENSIONS } from "./builtin-registry-
|
|
1
|
+
import { n as BUILTIN_EXTENSION_REGISTRY, t as BUILTIN_EXTENSIONS } from "./builtin-registry-DpLtHlYK.js";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -169,7 +169,7 @@ const BUILTIN_EXTENSION_REGISTRY = [
|
|
|
169
169
|
"preset",
|
|
170
170
|
"presets"
|
|
171
171
|
],
|
|
172
|
-
load: async () => (await import("./prompt-presets-
|
|
172
|
+
load: async () => (await import("./prompt-presets-BhlErXaD.js")).default
|
|
173
173
|
},
|
|
174
174
|
{
|
|
175
175
|
key: "git-ui",
|
|
@@ -259,7 +259,7 @@ const BUILTIN_EXTENSION_REGISTRY = [
|
|
|
259
259
|
cli_flag: "--no-hooks",
|
|
260
260
|
cli_description: "Disable Claude-style hook execution",
|
|
261
261
|
aliases: ["hooks-resolution", "hooks"],
|
|
262
|
-
load: async () => (await import("./hooks-resolution-
|
|
262
|
+
load: async () => (await import("./hooks-resolution-DNTz2NXs.js")).default
|
|
263
263
|
},
|
|
264
264
|
{
|
|
265
265
|
key: "svelte-guardrails",
|
|
@@ -313,4 +313,4 @@ const BUILTIN_EXTENSIONS = BUILTIN_EXTENSION_REGISTRY.map(({ load: _load, ...ext
|
|
|
313
313
|
//#endregion
|
|
314
314
|
export { BUILTIN_EXTENSION_REGISTRY as n, BUILTIN_EXTENSIONS as t };
|
|
315
315
|
|
|
316
|
-
//# sourceMappingURL=builtin-registry-
|
|
316
|
+
//# sourceMappingURL=builtin-registry-DpLtHlYK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtin-registry-DZ9GaW_e.js","names":[],"sources":["../src/extensions/builtin-registry.ts"],"sourcesContent":["import type { ExtensionFactory } from '@earendil-works/pi-coding-agent';\n\nexport type BuiltinExtensionRuntimeMode =\n\t| 'interactive'\n\t| 'print'\n\t| 'json'\n\t| 'rpc';\n\ntype BuiltinExtensionLoader = () => Promise<ExtensionFactory>;\n\nexport interface BuiltinExtensionManifestEntry {\n\tkey: string;\n\tlabel: string;\n\tdocs_label: string;\n\tdescription: string;\n\tdefault_enabled: boolean;\n\toption_name: string;\n\tcli_arg: string;\n\tcli_flag: `--${string}`;\n\tcli_description: string;\n\taliases: readonly string[];\n\tmode_constraints?: {\n\t\tdisabled_in: readonly BuiltinExtensionRuntimeMode[];\n\t\treason: string;\n\t};\n\tload: BuiltinExtensionLoader;\n}\n\nexport const BUILTIN_EXTENSION_REGISTRY = [\n\t{\n\t\tkey: 'context-sidecar',\n\t\tlabel: 'Context sidecar',\n\t\tdocs_label: 'SQLite context sidecar',\n\t\tdescription: 'Local SQLite FTS sidecar for oversized tool output',\n\t\tdefault_enabled: true,\n\t\toption_name: 'context_sidecar',\n\t\tcli_arg: 'no-context-sidecar',\n\t\tcli_flag: '--no-context-sidecar',\n\t\tcli_description:\n\t\t\t'Disable SQLite context sidecar for large tool output',\n\t\taliases: ['context-sidecar', 'context', 'sidecar'],\n\t\tload: async () => (await import('@spences10/pi-context')).default,\n\t},\n\t{\n\t\tkey: 'mcp',\n\t\tlabel: 'MCP',\n\t\tdocs_label: 'MCP',\n\t\tdescription: 'MCP server integration and /mcp command',\n\t\tdefault_enabled: true,\n\t\toption_name: 'mcp',\n\t\tcli_arg: 'no-mcp',\n\t\tcli_flag: '--no-mcp',\n\t\tcli_description: 'Disable built-in MCP extension',\n\t\taliases: ['mcp'],\n\t\tload: async () => (await import('@spences10/pi-mcp')).default,\n\t},\n\t{\n\t\tkey: 'skills',\n\t\tlabel: 'Skills',\n\t\tdocs_label: 'Skills',\n\t\tdescription: 'Managed pi-native skills and /skills command',\n\t\tdefault_enabled: true,\n\t\toption_name: 'skills',\n\t\tcli_arg: 'no-skills',\n\t\tcli_flag: '--no-skills',\n\t\tcli_description: 'Disable built-in skills extension',\n\t\taliases: ['skills', 'skill'],\n\t\tload: async () => (await import('@spences10/pi-skills')).default,\n\t},\n\t{\n\t\tkey: 'filter-output',\n\t\tlabel: 'Secret redaction',\n\t\tdocs_label: 'Secret redaction',\n\t\tdescription:\n\t\t\t'Redacts secrets from tool output before the model sees them',\n\t\tdefault_enabled: true,\n\t\toption_name: 'filter_output',\n\t\tcli_arg: 'no-filter',\n\t\tcli_flag: '--no-filter',\n\t\tcli_description: 'Disable secret redaction in tool output',\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\t'secret-redaction',\n\t\t\t'output-redaction',\n\t\t],\n\t\tload: async () => (await import('@spences10/pi-redact')).default,\n\t},\n\t{\n\t\tkey: 'recall',\n\t\tlabel: 'Recall',\n\t\tdocs_label: 'Recall',\n\t\tdescription: 'pirecall reminder and background session sync',\n\t\tdefault_enabled: true,\n\t\toption_name: 'recall',\n\t\tcli_arg: 'no-recall',\n\t\tcli_flag: '--no-recall',\n\t\tcli_description: 'Disable recall extension',\n\t\taliases: ['recall', 'pirecall'],\n\t\tload: async () => (await import('@spences10/pi-recall')).default,\n\t},\n\t{\n\t\tkey: 'nopeek',\n\t\tlabel: 'Nopeek',\n\t\tdocs_label: 'Nopeek',\n\t\tdescription:\n\t\t\t'nopeek reminder for secret-safe environment loading',\n\t\tdefault_enabled: true,\n\t\toption_name: 'nopeek',\n\t\tcli_arg: 'no-nopeek',\n\t\tcli_flag: '--no-nopeek',\n\t\tcli_description: 'Disable nopeek reminder extension',\n\t\taliases: ['nopeek', 'secrets', 'secret-loading'],\n\t\tload: async () => (await import('@spences10/pi-nopeek')).default,\n\t},\n\t{\n\t\tkey: 'omnisearch',\n\t\tlabel: 'Omnisearch',\n\t\tdocs_label: 'Omnisearch',\n\t\tdescription: 'mcp-omnisearch reminder for verified web research',\n\t\tdefault_enabled: true,\n\t\toption_name: 'omnisearch',\n\t\tcli_arg: 'no-omnisearch',\n\t\tcli_flag: '--no-omnisearch',\n\t\tcli_description: 'Disable mcp-omnisearch reminder extension',\n\t\taliases: ['omnisearch', 'search', 'web-search', 'research'],\n\t\tload: async () =>\n\t\t\t(await import('@spences10/pi-omnisearch')).default,\n\t},\n\t{\n\t\tkey: 'sqlite-tools',\n\t\tlabel: 'SQLite tools',\n\t\tdocs_label: 'SQLite tools',\n\t\tdescription:\n\t\t\t'mcp-sqlite-tools reminder for safer SQLite database work',\n\t\tdefault_enabled: true,\n\t\toption_name: 'sqlite_tools',\n\t\tcli_arg: 'no-sqlite-tools',\n\t\tcli_flag: '--no-sqlite-tools',\n\t\tcli_description: 'Disable mcp-sqlite-tools reminder extension',\n\t\taliases: ['sqlite-tools', 'sqlite', 'mcp-sqlite-tools'],\n\t\tload: async () =>\n\t\t\t(await import('@spences10/pi-sqlite-tools')).default,\n\t},\n\t{\n\t\tkey: 'startup-screen',\n\t\tlabel: 'Startup screen',\n\t\tdocs_label: 'Startup screen',\n\t\tdescription:\n\t\t\t'Pixel-art gradient startup header for interactive sessions',\n\t\tdefault_enabled: true,\n\t\toption_name: 'startup_screen',\n\t\tcli_arg: 'no-startup-screen',\n\t\tcli_flag: '--no-startup-screen',\n\t\tcli_description: 'Disable the custom startup screen',\n\t\taliases: ['startup-screen', 'startup', 'header', 'splash'],\n\t\tmode_constraints: {\n\t\t\tdisabled_in: ['print', 'json', 'rpc'],\n\t\t\treason: 'Startup screen only renders in the interactive TUI',\n\t\t},\n\t\tload: async () =>\n\t\t\t(await import('./startup-screen/index.js')).default,\n\t},\n\t{\n\t\tkey: 'prompt-presets',\n\t\tlabel: 'Prompt presets',\n\t\tdocs_label: 'Prompt presets',\n\t\tdescription:\n\t\t\t'Runtime prompt preset selection and /prompt-preset command',\n\t\tdefault_enabled: true,\n\t\toption_name: 'prompt_presets',\n\t\tcli_arg: 'no-prompt-presets',\n\t\tcli_flag: '--no-prompt-presets',\n\t\tcli_description: 'Disable prompt presets extension',\n\t\taliases: ['prompt-preset', 'preset', 'presets'],\n\t\tload: async () =>\n\t\t\t(await import('./prompt-presets/index.js')).default,\n\t},\n\t{\n\t\tkey: 'git-ui',\n\t\tlabel: 'Git UI',\n\t\tdocs_label: 'Git staging UI',\n\t\tdescription: 'Interactive source control staging panel',\n\t\tdefault_enabled: true,\n\t\toption_name: 'git_ui',\n\t\tcli_arg: 'no-git-ui',\n\t\tcli_flag: '--no-git-ui',\n\t\tcli_description: 'Disable built-in Git staging UI',\n\t\taliases: ['git-ui', 'git', 'source-control', 'scm'],\n\t\tmode_constraints: {\n\t\t\tdisabled_in: ['print', 'json', 'rpc'],\n\t\t\treason: 'Git UI is only useful in interactive mode',\n\t\t},\n\t\tload: async () => (await import('@spences10/pi-git-ui')).default,\n\t},\n\t{\n\t\tkey: 'lsp',\n\t\tlabel: 'LSP',\n\t\tdocs_label: 'LSP',\n\t\tdescription:\n\t\t\t'Language Server Protocol tools (diagnostics, hover, definition, references)',\n\t\tdefault_enabled: true,\n\t\toption_name: 'lsp',\n\t\tcli_arg: 'no-lsp',\n\t\tcli_flag: '--no-lsp',\n\t\tcli_description: 'Disable LSP extension',\n\t\taliases: ['lsp', 'language-server'],\n\t\tload: async () => (await import('@spences10/pi-lsp')).default,\n\t},\n\t{\n\t\tkey: 'session-name',\n\t\tlabel: 'Session name',\n\t\tdocs_label: 'Session auto-naming',\n\t\tdescription:\n\t\t\t'AI-powered session auto-naming and /session-name command',\n\t\tdefault_enabled: true,\n\t\toption_name: 'session_name',\n\t\tcli_arg: 'no-session-name',\n\t\tcli_flag: '--no-session-name',\n\t\tcli_description: 'Disable session name extension',\n\t\taliases: ['session-name', 'session', 'auto-name'],\n\t\tmode_constraints: {\n\t\t\tdisabled_in: ['print', 'json', 'rpc'],\n\t\t\treason:\n\t\t\t\t'UI-only session naming is only useful in interactive mode',\n\t\t},\n\t\tload: async () =>\n\t\t\t(await import('./session-name/index.js')).default,\n\t},\n\t{\n\t\tkey: 'confirm-destructive',\n\t\tlabel: 'Confirm destructive',\n\t\tdocs_label: 'Destructive action confirmation',\n\t\tdescription:\n\t\t\t'Prompt before destructive tool calls like file deletes, overwrites, and hard resets',\n\t\tdefault_enabled: true,\n\t\toption_name: 'confirm_destructive',\n\t\tcli_arg: 'no-confirm-destructive',\n\t\tcli_flag: '--no-confirm-destructive',\n\t\tcli_description: 'Disable destructive action confirmations',\n\t\taliases: ['confirm-destructive', 'confirm'],\n\t\tload: async () =>\n\t\t\t(await import('@spences10/pi-confirm-destructive')).default,\n\t},\n\t{\n\t\tkey: 'hooks-resolution',\n\t\tlabel: 'Hooks resolution',\n\t\tdocs_label: 'Hooks resolution',\n\t\tdescription:\n\t\t\t'Claude Code style PreToolUse and PostToolUse hook compatibility from .claude, .rulesync, and .pi configs',\n\t\tdefault_enabled: true,\n\t\toption_name: 'hooks_resolution',\n\t\tcli_arg: 'no-hooks',\n\t\tcli_flag: '--no-hooks',\n\t\tcli_description: 'Disable Claude-style hook execution',\n\t\taliases: ['hooks-resolution', 'hooks'],\n\t\tload: async () =>\n\t\t\t(await import('./hooks-resolution/index.js')).default,\n\t},\n\t{\n\t\tkey: 'svelte-guardrails',\n\t\tlabel: 'Svelte guardrails',\n\t\tdocs_label: 'Svelte guardrails',\n\t\tdescription:\n\t\t\t'Blocks discouraged Svelte patterns like $effect before agents write them',\n\t\tdefault_enabled: true,\n\t\toption_name: 'svelte_guardrails',\n\t\tcli_arg: 'no-svelte-guardrails',\n\t\tcli_flag: '--no-svelte-guardrails',\n\t\tcli_description: 'Disable Svelte guardrails',\n\t\taliases: ['svelte-guardrails', 'svelte'],\n\t\tload: async () =>\n\t\t\t(await import('@spences10/pi-svelte-guardrails')).default,\n\t},\n\t{\n\t\tkey: 'coding-preferences',\n\t\tlabel: 'Coding preferences',\n\t\tdocs_label: 'Coding preferences',\n\t\tdescription:\n\t\t\t'Blocks configured coding workflow anti-patterns from JSON preferences',\n\t\tdefault_enabled: true,\n\t\toption_name: 'coding_preferences',\n\t\tcli_arg: 'no-coding-preferences',\n\t\tcli_flag: '--no-coding-preferences',\n\t\tcli_description: 'Disable coding preferences guardrails',\n\t\taliases: ['coding-preferences', 'preferences', 'prefs'],\n\t\tload: async () =>\n\t\t\t(await import('@spences10/pi-coding-preferences')).default,\n\t},\n\t{\n\t\tkey: 'team-mode',\n\t\tlabel: 'Team mode',\n\t\tdocs_label: 'Team mode',\n\t\tdescription:\n\t\t\t'Experimental orchestrator/team mode with RPC teammates, tasks, and mailboxes',\n\t\tdefault_enabled: true,\n\t\toption_name: 'team_mode',\n\t\tcli_arg: 'no-team-mode',\n\t\tcli_flag: '--no-team-mode',\n\t\tcli_description: 'Disable experimental team mode extension',\n\t\taliases: ['team-mode', 'team', 'teammates'],\n\t\tload: async () =>\n\t\t\t(await import('@spences10/pi-team-mode')).default,\n\t},\n] as const satisfies readonly BuiltinExtensionManifestEntry[];\n\nexport type BuiltinExtensionKey =\n\t(typeof BUILTIN_EXTENSION_REGISTRY)[number]['key'];\n\nexport type BuiltinExtensionOptionName =\n\t(typeof BUILTIN_EXTENSION_REGISTRY)[number]['option_name'];\n\nexport type BuiltinExtensionInfo = Omit<\n\tBuiltinExtensionManifestEntry,\n\t'load'\n> & {\n\tkey: BuiltinExtensionKey;\n\toption_name: BuiltinExtensionOptionName;\n};\n\nexport const BUILTIN_EXTENSIONS: BuiltinExtensionInfo[] =\n\tBUILTIN_EXTENSION_REGISTRY.map(\n\t\t({ load: _load, ...extension }) => extension,\n\t);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"builtin-registry-DpLtHlYK.js","names":[],"sources":["../src/extensions/builtin-registry.ts"],"sourcesContent":["import type { ExtensionFactory } from '@earendil-works/pi-coding-agent';\n\nexport type BuiltinExtensionRuntimeMode =\n\t| 'interactive'\n\t| 'print'\n\t| 'json'\n\t| 'rpc';\n\ntype BuiltinExtensionLoader = () => Promise<ExtensionFactory>;\n\nexport interface BuiltinExtensionManifestEntry {\n\tkey: string;\n\tlabel: string;\n\tdocs_label: string;\n\tdescription: string;\n\tdefault_enabled: boolean;\n\toption_name: string;\n\tcli_arg: string;\n\tcli_flag: `--${string}`;\n\tcli_description: string;\n\taliases: readonly string[];\n\tmode_constraints?: {\n\t\tdisabled_in: readonly BuiltinExtensionRuntimeMode[];\n\t\treason: string;\n\t};\n\tload: BuiltinExtensionLoader;\n}\n\nexport const BUILTIN_EXTENSION_REGISTRY = [\n\t{\n\t\tkey: 'context-sidecar',\n\t\tlabel: 'Context sidecar',\n\t\tdocs_label: 'SQLite context sidecar',\n\t\tdescription: 'Local SQLite FTS sidecar for oversized tool output',\n\t\tdefault_enabled: true,\n\t\toption_name: 'context_sidecar',\n\t\tcli_arg: 'no-context-sidecar',\n\t\tcli_flag: '--no-context-sidecar',\n\t\tcli_description:\n\t\t\t'Disable SQLite context sidecar for large tool output',\n\t\taliases: ['context-sidecar', 'context', 'sidecar'],\n\t\tload: async () => (await import('@spences10/pi-context')).default,\n\t},\n\t{\n\t\tkey: 'mcp',\n\t\tlabel: 'MCP',\n\t\tdocs_label: 'MCP',\n\t\tdescription: 'MCP server integration and /mcp command',\n\t\tdefault_enabled: true,\n\t\toption_name: 'mcp',\n\t\tcli_arg: 'no-mcp',\n\t\tcli_flag: '--no-mcp',\n\t\tcli_description: 'Disable built-in MCP extension',\n\t\taliases: ['mcp'],\n\t\tload: async () => (await import('@spences10/pi-mcp')).default,\n\t},\n\t{\n\t\tkey: 'skills',\n\t\tlabel: 'Skills',\n\t\tdocs_label: 'Skills',\n\t\tdescription: 'Managed pi-native skills and /skills command',\n\t\tdefault_enabled: true,\n\t\toption_name: 'skills',\n\t\tcli_arg: 'no-skills',\n\t\tcli_flag: '--no-skills',\n\t\tcli_description: 'Disable built-in skills extension',\n\t\taliases: ['skills', 'skill'],\n\t\tload: async () => (await import('@spences10/pi-skills')).default,\n\t},\n\t{\n\t\tkey: 'filter-output',\n\t\tlabel: 'Secret redaction',\n\t\tdocs_label: 'Secret redaction',\n\t\tdescription:\n\t\t\t'Redacts secrets from tool output before the model sees them',\n\t\tdefault_enabled: true,\n\t\toption_name: 'filter_output',\n\t\tcli_arg: 'no-filter',\n\t\tcli_flag: '--no-filter',\n\t\tcli_description: 'Disable secret redaction in tool output',\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\t'secret-redaction',\n\t\t\t'output-redaction',\n\t\t],\n\t\tload: async () => (await import('@spences10/pi-redact')).default,\n\t},\n\t{\n\t\tkey: 'recall',\n\t\tlabel: 'Recall',\n\t\tdocs_label: 'Recall',\n\t\tdescription: 'pirecall reminder and background session sync',\n\t\tdefault_enabled: true,\n\t\toption_name: 'recall',\n\t\tcli_arg: 'no-recall',\n\t\tcli_flag: '--no-recall',\n\t\tcli_description: 'Disable recall extension',\n\t\taliases: ['recall', 'pirecall'],\n\t\tload: async () => (await import('@spences10/pi-recall')).default,\n\t},\n\t{\n\t\tkey: 'nopeek',\n\t\tlabel: 'Nopeek',\n\t\tdocs_label: 'Nopeek',\n\t\tdescription:\n\t\t\t'nopeek reminder for secret-safe environment loading',\n\t\tdefault_enabled: true,\n\t\toption_name: 'nopeek',\n\t\tcli_arg: 'no-nopeek',\n\t\tcli_flag: '--no-nopeek',\n\t\tcli_description: 'Disable nopeek reminder extension',\n\t\taliases: ['nopeek', 'secrets', 'secret-loading'],\n\t\tload: async () => (await import('@spences10/pi-nopeek')).default,\n\t},\n\t{\n\t\tkey: 'omnisearch',\n\t\tlabel: 'Omnisearch',\n\t\tdocs_label: 'Omnisearch',\n\t\tdescription: 'mcp-omnisearch reminder for verified web research',\n\t\tdefault_enabled: true,\n\t\toption_name: 'omnisearch',\n\t\tcli_arg: 'no-omnisearch',\n\t\tcli_flag: '--no-omnisearch',\n\t\tcli_description: 'Disable mcp-omnisearch reminder extension',\n\t\taliases: ['omnisearch', 'search', 'web-search', 'research'],\n\t\tload: async () =>\n\t\t\t(await import('@spences10/pi-omnisearch')).default,\n\t},\n\t{\n\t\tkey: 'sqlite-tools',\n\t\tlabel: 'SQLite tools',\n\t\tdocs_label: 'SQLite tools',\n\t\tdescription:\n\t\t\t'mcp-sqlite-tools reminder for safer SQLite database work',\n\t\tdefault_enabled: true,\n\t\toption_name: 'sqlite_tools',\n\t\tcli_arg: 'no-sqlite-tools',\n\t\tcli_flag: '--no-sqlite-tools',\n\t\tcli_description: 'Disable mcp-sqlite-tools reminder extension',\n\t\taliases: ['sqlite-tools', 'sqlite', 'mcp-sqlite-tools'],\n\t\tload: async () =>\n\t\t\t(await import('@spences10/pi-sqlite-tools')).default,\n\t},\n\t{\n\t\tkey: 'startup-screen',\n\t\tlabel: 'Startup screen',\n\t\tdocs_label: 'Startup screen',\n\t\tdescription:\n\t\t\t'Pixel-art gradient startup header for interactive sessions',\n\t\tdefault_enabled: true,\n\t\toption_name: 'startup_screen',\n\t\tcli_arg: 'no-startup-screen',\n\t\tcli_flag: '--no-startup-screen',\n\t\tcli_description: 'Disable the custom startup screen',\n\t\taliases: ['startup-screen', 'startup', 'header', 'splash'],\n\t\tmode_constraints: {\n\t\t\tdisabled_in: ['print', 'json', 'rpc'],\n\t\t\treason: 'Startup screen only renders in the interactive TUI',\n\t\t},\n\t\tload: async () =>\n\t\t\t(await import('./startup-screen/index.js')).default,\n\t},\n\t{\n\t\tkey: 'prompt-presets',\n\t\tlabel: 'Prompt presets',\n\t\tdocs_label: 'Prompt presets',\n\t\tdescription:\n\t\t\t'Runtime prompt preset selection and /prompt-preset command',\n\t\tdefault_enabled: true,\n\t\toption_name: 'prompt_presets',\n\t\tcli_arg: 'no-prompt-presets',\n\t\tcli_flag: '--no-prompt-presets',\n\t\tcli_description: 'Disable prompt presets extension',\n\t\taliases: ['prompt-preset', 'preset', 'presets'],\n\t\tload: async () =>\n\t\t\t(await import('./prompt-presets/index.js')).default,\n\t},\n\t{\n\t\tkey: 'git-ui',\n\t\tlabel: 'Git UI',\n\t\tdocs_label: 'Git staging UI',\n\t\tdescription: 'Interactive source control staging panel',\n\t\tdefault_enabled: true,\n\t\toption_name: 'git_ui',\n\t\tcli_arg: 'no-git-ui',\n\t\tcli_flag: '--no-git-ui',\n\t\tcli_description: 'Disable built-in Git staging UI',\n\t\taliases: ['git-ui', 'git', 'source-control', 'scm'],\n\t\tmode_constraints: {\n\t\t\tdisabled_in: ['print', 'json', 'rpc'],\n\t\t\treason: 'Git UI is only useful in interactive mode',\n\t\t},\n\t\tload: async () => (await import('@spences10/pi-git-ui')).default,\n\t},\n\t{\n\t\tkey: 'lsp',\n\t\tlabel: 'LSP',\n\t\tdocs_label: 'LSP',\n\t\tdescription:\n\t\t\t'Language Server Protocol tools (diagnostics, hover, definition, references)',\n\t\tdefault_enabled: true,\n\t\toption_name: 'lsp',\n\t\tcli_arg: 'no-lsp',\n\t\tcli_flag: '--no-lsp',\n\t\tcli_description: 'Disable LSP extension',\n\t\taliases: ['lsp', 'language-server'],\n\t\tload: async () => (await import('@spences10/pi-lsp')).default,\n\t},\n\t{\n\t\tkey: 'session-name',\n\t\tlabel: 'Session name',\n\t\tdocs_label: 'Session auto-naming',\n\t\tdescription:\n\t\t\t'AI-powered session auto-naming and /session-name command',\n\t\tdefault_enabled: true,\n\t\toption_name: 'session_name',\n\t\tcli_arg: 'no-session-name',\n\t\tcli_flag: '--no-session-name',\n\t\tcli_description: 'Disable session name extension',\n\t\taliases: ['session-name', 'session', 'auto-name'],\n\t\tmode_constraints: {\n\t\t\tdisabled_in: ['print', 'json', 'rpc'],\n\t\t\treason:\n\t\t\t\t'UI-only session naming is only useful in interactive mode',\n\t\t},\n\t\tload: async () =>\n\t\t\t(await import('./session-name/index.js')).default,\n\t},\n\t{\n\t\tkey: 'confirm-destructive',\n\t\tlabel: 'Confirm destructive',\n\t\tdocs_label: 'Destructive action confirmation',\n\t\tdescription:\n\t\t\t'Prompt before destructive tool calls like file deletes, overwrites, and hard resets',\n\t\tdefault_enabled: true,\n\t\toption_name: 'confirm_destructive',\n\t\tcli_arg: 'no-confirm-destructive',\n\t\tcli_flag: '--no-confirm-destructive',\n\t\tcli_description: 'Disable destructive action confirmations',\n\t\taliases: ['confirm-destructive', 'confirm'],\n\t\tload: async () =>\n\t\t\t(await import('@spences10/pi-confirm-destructive')).default,\n\t},\n\t{\n\t\tkey: 'hooks-resolution',\n\t\tlabel: 'Hooks resolution',\n\t\tdocs_label: 'Hooks resolution',\n\t\tdescription:\n\t\t\t'Claude Code style PreToolUse and PostToolUse hook compatibility from .claude, .rulesync, and .pi configs',\n\t\tdefault_enabled: true,\n\t\toption_name: 'hooks_resolution',\n\t\tcli_arg: 'no-hooks',\n\t\tcli_flag: '--no-hooks',\n\t\tcli_description: 'Disable Claude-style hook execution',\n\t\taliases: ['hooks-resolution', 'hooks'],\n\t\tload: async () =>\n\t\t\t(await import('./hooks-resolution/index.js')).default,\n\t},\n\t{\n\t\tkey: 'svelte-guardrails',\n\t\tlabel: 'Svelte guardrails',\n\t\tdocs_label: 'Svelte guardrails',\n\t\tdescription:\n\t\t\t'Blocks discouraged Svelte patterns like $effect before agents write them',\n\t\tdefault_enabled: true,\n\t\toption_name: 'svelte_guardrails',\n\t\tcli_arg: 'no-svelte-guardrails',\n\t\tcli_flag: '--no-svelte-guardrails',\n\t\tcli_description: 'Disable Svelte guardrails',\n\t\taliases: ['svelte-guardrails', 'svelte'],\n\t\tload: async () =>\n\t\t\t(await import('@spences10/pi-svelte-guardrails')).default,\n\t},\n\t{\n\t\tkey: 'coding-preferences',\n\t\tlabel: 'Coding preferences',\n\t\tdocs_label: 'Coding preferences',\n\t\tdescription:\n\t\t\t'Blocks configured coding workflow anti-patterns from JSON preferences',\n\t\tdefault_enabled: true,\n\t\toption_name: 'coding_preferences',\n\t\tcli_arg: 'no-coding-preferences',\n\t\tcli_flag: '--no-coding-preferences',\n\t\tcli_description: 'Disable coding preferences guardrails',\n\t\taliases: ['coding-preferences', 'preferences', 'prefs'],\n\t\tload: async () =>\n\t\t\t(await import('@spences10/pi-coding-preferences')).default,\n\t},\n\t{\n\t\tkey: 'team-mode',\n\t\tlabel: 'Team mode',\n\t\tdocs_label: 'Team mode',\n\t\tdescription:\n\t\t\t'Experimental orchestrator/team mode with RPC teammates, tasks, and mailboxes',\n\t\tdefault_enabled: true,\n\t\toption_name: 'team_mode',\n\t\tcli_arg: 'no-team-mode',\n\t\tcli_flag: '--no-team-mode',\n\t\tcli_description: 'Disable experimental team mode extension',\n\t\taliases: ['team-mode', 'team', 'teammates'],\n\t\tload: async () =>\n\t\t\t(await import('@spences10/pi-team-mode')).default,\n\t},\n] as const satisfies readonly BuiltinExtensionManifestEntry[];\n\nexport type BuiltinExtensionKey =\n\t(typeof BUILTIN_EXTENSION_REGISTRY)[number]['key'];\n\nexport type BuiltinExtensionOptionName =\n\t(typeof BUILTIN_EXTENSION_REGISTRY)[number]['option_name'];\n\nexport type BuiltinExtensionInfo = Omit<\n\tBuiltinExtensionManifestEntry,\n\t'load'\n> & {\n\tkey: BuiltinExtensionKey;\n\toption_name: BuiltinExtensionOptionName;\n};\n\nexport const BUILTIN_EXTENSIONS: BuiltinExtensionInfo[] =\n\tBUILTIN_EXTENSION_REGISTRY.map(\n\t\t({ load: _load, ...extension }) => extension,\n\t);\n"],"mappings":"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"}
|
|
@@ -2,42 +2,10 @@ import { existsSync, readFileSync, statSync } from "node:fs";
|
|
|
2
2
|
import { basename, dirname, join, resolve } from "node:path";
|
|
3
3
|
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
4
4
|
import { is_project_subject_trusted, read_project_trust_store, resolve_project_trust } from "@spences10/pi-project-trust";
|
|
5
|
-
import { spawn } from "node:child_process";
|
|
6
5
|
import { createHash } from "node:crypto";
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
7
|
import { create_child_process_env } from "@spences10/pi-child-env";
|
|
8
|
-
//#region src/extensions/hooks-resolution/
|
|
9
|
-
function create_child_process_env$1(explicit_env = {}, source_env = process.env) {
|
|
10
|
-
return create_child_process_env({
|
|
11
|
-
profile: "hooks",
|
|
12
|
-
explicit_env,
|
|
13
|
-
source_env
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
//#endregion
|
|
17
|
-
//#region src/extensions/hooks-resolution/trust.ts
|
|
18
|
-
const HOOKS_CONFIG_ENV$1 = "MY_PI_HOOKS_CONFIG";
|
|
19
|
-
function default_hooks_trust_store_path() {
|
|
20
|
-
return join(getAgentDir(), "trusted-hooks.json");
|
|
21
|
-
}
|
|
22
|
-
function create_hooks_config_trust_subject(project_dir, hash) {
|
|
23
|
-
return {
|
|
24
|
-
kind: "hooks-config",
|
|
25
|
-
id: project_dir,
|
|
26
|
-
store_key: project_dir,
|
|
27
|
-
hash,
|
|
28
|
-
env_key: HOOKS_CONFIG_ENV$1,
|
|
29
|
-
prompt_title: "Project hook config can execute shell commands after tool use. Trust these hooks?"
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
function is_hooks_config_trusted(project_dir, hash, trust_store_path = default_hooks_trust_store_path()) {
|
|
33
|
-
if (is_project_subject_trusted(create_hooks_config_trust_subject(project_dir, hash), trust_store_path)) return true;
|
|
34
|
-
const legacy_entry = read_project_trust_store(trust_store_path)[project_dir];
|
|
35
|
-
return legacy_entry?.project_dir === project_dir && legacy_entry.hash === hash;
|
|
36
|
-
}
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region src/extensions/hooks-resolution/index.ts
|
|
39
|
-
const HOOK_TIMEOUT_MS = 600 * 1e3;
|
|
40
|
-
const HOOKS_CONFIG_ENV = "MY_PI_HOOKS_CONFIG";
|
|
8
|
+
//#region src/extensions/hooks-resolution/config.ts
|
|
41
9
|
function is_file(path) {
|
|
42
10
|
try {
|
|
43
11
|
return statSync(path).isFile();
|
|
@@ -206,6 +174,8 @@ function get_hooks_config_info(cwd) {
|
|
|
206
174
|
hooks
|
|
207
175
|
};
|
|
208
176
|
}
|
|
177
|
+
//#endregion
|
|
178
|
+
//#region src/extensions/hooks-resolution/payload.ts
|
|
209
179
|
function to_claude_tool_name(tool_name) {
|
|
210
180
|
if (tool_name === "ls") return "LS";
|
|
211
181
|
if (tool_name.length === 0) return tool_name;
|
|
@@ -267,6 +237,18 @@ function build_hook_payload(event, event_name, ctx, project_dir) {
|
|
|
267
237
|
if ("content" in event) payload.tool_response = build_tool_response(event, normalized_input);
|
|
268
238
|
return payload;
|
|
269
239
|
}
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region src/extensions/hooks-resolution/env.ts
|
|
242
|
+
function create_child_process_env$1(explicit_env = {}, source_env = process.env) {
|
|
243
|
+
return create_child_process_env({
|
|
244
|
+
profile: "hooks",
|
|
245
|
+
explicit_env,
|
|
246
|
+
source_env
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
//#endregion
|
|
250
|
+
//#region src/extensions/hooks-resolution/runner.ts
|
|
251
|
+
const HOOK_TIMEOUT_MS = 600 * 1e3;
|
|
270
252
|
async function run_command_hook(command, cwd, payload) {
|
|
271
253
|
return await new Promise((resolve) => {
|
|
272
254
|
const started_at = Date.now();
|
|
@@ -351,6 +333,30 @@ function hook_name(command) {
|
|
|
351
333
|
if (sh_path_match) return basename(sh_path_match[0]);
|
|
352
334
|
return basename(command.trim().split(/\s+/)[0] ?? "hook");
|
|
353
335
|
}
|
|
336
|
+
//#endregion
|
|
337
|
+
//#region src/extensions/hooks-resolution/trust.ts
|
|
338
|
+
const HOOKS_CONFIG_ENV$1 = "MY_PI_HOOKS_CONFIG";
|
|
339
|
+
function default_hooks_trust_store_path() {
|
|
340
|
+
return join(getAgentDir(), "trusted-hooks.json");
|
|
341
|
+
}
|
|
342
|
+
function create_hooks_config_trust_subject(project_dir, hash) {
|
|
343
|
+
return {
|
|
344
|
+
kind: "hooks-config",
|
|
345
|
+
id: project_dir,
|
|
346
|
+
store_key: project_dir,
|
|
347
|
+
hash,
|
|
348
|
+
env_key: HOOKS_CONFIG_ENV$1,
|
|
349
|
+
prompt_title: "Project hook config can execute shell commands after tool use. Trust these hooks?"
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function is_hooks_config_trusted(project_dir, hash, trust_store_path = default_hooks_trust_store_path()) {
|
|
353
|
+
if (is_project_subject_trusted(create_hooks_config_trust_subject(project_dir, hash), trust_store_path)) return true;
|
|
354
|
+
const legacy_entry = read_project_trust_store(trust_store_path)[project_dir];
|
|
355
|
+
return legacy_entry?.project_dir === project_dir && legacy_entry.hash === hash;
|
|
356
|
+
}
|
|
357
|
+
//#endregion
|
|
358
|
+
//#region src/extensions/hooks-resolution/trust-gate.ts
|
|
359
|
+
const HOOKS_CONFIG_ENV = "MY_PI_HOOKS_CONFIG";
|
|
354
360
|
function create_hooks_trust_subject(info) {
|
|
355
361
|
const source_lines = info.sources.map((source) => `- ${source}`);
|
|
356
362
|
const hook_lines = info.hooks.length === 0 ? ["- no valid command hooks detected"] : info.hooks.map((hook) => {
|
|
@@ -392,6 +398,8 @@ async function should_load_hooks_config(cwd, ctx) {
|
|
|
392
398
|
});
|
|
393
399
|
return decision.action === "allow-once" || decision.action === "trust-persisted";
|
|
394
400
|
}
|
|
401
|
+
//#endregion
|
|
402
|
+
//#region src/extensions/hooks-resolution/index.ts
|
|
395
403
|
function create_hooks_resolution_extension(options = {}) {
|
|
396
404
|
const load_hooks_impl = options.load_hooks ?? load_hooks;
|
|
397
405
|
const run_command_hook_impl = options.run_command_hook ?? run_command_hook;
|
|
@@ -455,4 +463,4 @@ var hooks_resolution_default = create_hooks_resolution_extension();
|
|
|
455
463
|
//#endregion
|
|
456
464
|
export { hooks_resolution_default as default };
|
|
457
465
|
|
|
458
|
-
//# sourceMappingURL=hooks-resolution-
|
|
466
|
+
//# sourceMappingURL=hooks-resolution-DNTz2NXs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-resolution-DNTz2NXs.js","names":["create_child_process_env","create_shared_child_process_env","create_child_process_env","HOOKS_CONFIG_ENV"],"sources":["../src/extensions/hooks-resolution/config.ts","../src/extensions/hooks-resolution/payload.ts","../src/extensions/hooks-resolution/env.ts","../src/extensions/hooks-resolution/runner.ts","../src/extensions/hooks-resolution/trust.ts","../src/extensions/hooks-resolution/trust-gate.ts","../src/extensions/hooks-resolution/index.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport type {\n\tHookEventName,\n\tHooksConfigInfo,\n\tHookState,\n\tJsonValue,\n\tResolvedCommandHook,\n} from './types.js';\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 === 'PreToolUse'\n\t\t\t? ['PreToolUse', 'preToolUse']\n\t\t\t: event_name === 'PostToolUse'\n\t\t\t\t? ['PostToolUse', 'postToolUse']\n\t\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'PreToolUse',\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'PreToolUse',\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","import type {\n\tExtensionContext,\n\tToolCallEvent,\n\tToolResultEvent,\n} from '@earendil-works/pi-coding-agent';\nimport type { HookEventName, ResolvedCommandHook } from './types.js';\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: ToolCallEvent | 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\tconst payload: Record<string, unknown> = {\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};\n\n\tif ('content' in event) {\n\t\tpayload.tool_response = build_tool_response(\n\t\t\tevent,\n\t\t\tnormalized_input,\n\t\t);\n\t}\n\n\treturn payload;\n}\n","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 type { ToolResultEvent } from '@earendil-works/pi-coding-agent';\nimport { spawn } from 'node:child_process';\nimport { basename } from 'node:path';\nimport { as_record } from './config.js';\nimport { create_child_process_env } from './env.js';\nimport type { CommandRunResult, HookEventName } from './types.js';\n\nconst HOOK_TIMEOUT_MS = 10 * 60 * 1000;\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 hook_block_reason(\n\tresult: CommandRunResult,\n): string | undefined {\n\tconst parse_json = (\n\t\ttext: string,\n\t): Record<string, unknown> | undefined => {\n\t\tconst trimmed = text.trim();\n\t\tif (!trimmed) return undefined;\n\t\ttry {\n\t\t\treturn as_record(JSON.parse(trimmed));\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t};\n\n\tconst json = parse_json(result.stdout) ?? parse_json(result.stderr);\n\tif (json?.decision === 'block') {\n\t\treturn typeof json.reason === 'string'\n\t\t\t? json.reason\n\t\t\t: 'Blocked by hook';\n\t}\n\tif (result.code === 2) {\n\t\treturn (\n\t\t\tresult.stderr.trim() ||\n\t\t\tresult.stdout.trim() ||\n\t\t\t'Blocked by hook'\n\t\t);\n\t}\n\treturn undefined;\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","import { getAgentDir } from '@earendil-works/pi-coding-agent';\nimport {\n\tis_project_subject_trusted,\n\tread_project_trust_store,\n\ttrust_project_subject,\n\ttype ProjectTrustSubject,\n} from '@spences10/pi-project-trust';\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(getAgentDir(), '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","import type { ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n\tresolve_project_trust,\n\ttype ProjectTrustSubject,\n} from '@spences10/pi-project-trust';\nimport { get_hooks_config_info } from './config.js';\nimport {\n\tdefault_hooks_trust_store_path,\n\tis_hooks_config_trusted,\n} from './trust.js';\nimport type { HooksConfigInfo } from './types.js';\n\nconst HOOKS_CONFIG_ENV = 'MY_PI_HOOKS_CONFIG';\n\nexport function 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\nexport async 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","// Hooks resolution — Claude Code style hook compatibility\n\nimport type {\n\tExtensionAPI,\n\tExtensionContext,\n\tExtensionFactory,\n\tToolCallEventResult,\n} from '@earendil-works/pi-coding-agent';\nimport { load_hooks } from './config.js';\nimport { build_hook_payload, matches_hook } from './payload.js';\nimport {\n\tformat_duration,\n\thook_block_reason,\n\thook_event_name_for_result,\n\thook_name,\n\trun_command_hook,\n} from './runner.js';\nimport { should_load_hooks_config } from './trust-gate.js';\nimport type { CommandRunResult, HookState } from './types.js';\n\nexport {\n\tas_record,\n\tcompile_matcher,\n\tcreate_hook,\n\tfind_nearest_git_root,\n\tfind_project_dir,\n\tget_hook_entries,\n\tget_hooks_config_info,\n\thas_hooks_config,\n\tis_file,\n\tload_hooks,\n\tparse_claude_settings_hooks,\n\tparse_simple_hooks_file,\n\tread_json_file,\n\tresolve_hook_command,\n\twalk_up_directories,\n} from './config.js';\nexport {\n\tbuild_hook_payload,\n\tbuild_tool_response,\n\textract_text_content,\n\tmatches_hook,\n\tnormalize_tool_input,\n\tto_claude_tool_name,\n} from './payload.js';\nexport {\n\tformat_duration,\n\thook_block_reason,\n\thook_event_name_for_result,\n\thook_name,\n\trun_command_hook,\n} from './runner.js';\nexport type {\n\tCommandRunResult,\n\tHookEventName,\n\tHooksConfigInfo,\n\tHookState,\n\tResolvedCommandHook,\n} from './types.js';\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(\n\t\t\t'tool_call',\n\t\t\tasync (\n\t\t\t\tevent,\n\t\t\t\tctx,\n\t\t\t): Promise<ToolCallEventResult | undefined> => {\n\t\t\t\tif (state.hooks.length === 0) return;\n\n\t\t\t\tconst matching_hooks = state.hooks.filter(\n\t\t\t\t\t(hook) =>\n\t\t\t\t\t\thook.event_name === 'PreToolUse' &&\n\t\t\t\t\t\tmatches_hook(hook, event.toolName),\n\t\t\t\t);\n\t\t\t\tif (matching_hooks.length === 0) return;\n\n\t\t\t\tconst payload = build_hook_payload(\n\t\t\t\t\tevent,\n\t\t\t\t\t'PreToolUse',\n\t\t\t\t\tctx,\n\t\t\t\t\tstate.project_dir,\n\t\t\t\t);\n\t\t\t\tconst executed_commands = new Set<string>();\n\n\t\t\t\tfor (const hook of matching_hooks) {\n\t\t\t\t\tif (executed_commands.has(hook.command)) continue;\n\t\t\t\t\texecuted_commands.add(hook.command);\n\n\t\t\t\t\tconst result = await run_command_hook_impl(\n\t\t\t\t\t\thook.command,\n\t\t\t\t\t\tstate.project_dir,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t);\n\t\t\t\t\tconst reason = hook_block_reason(result);\n\t\t\t\t\tif (reason) return { block: true, reason };\n\t\t\t\t}\n\t\t\t},\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"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as BUILTIN_EXTENSIONS } from "./builtin-registry-
|
|
2
|
+
import { t as BUILTIN_EXTENSIONS } from "./builtin-registry-DpLtHlYK.js";
|
|
3
3
|
import { defineCommand, renderUsage, runMain } from "citty";
|
|
4
4
|
import { existsSync, readFileSync } from "node:fs";
|
|
5
5
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -242,6 +242,52 @@ function set_status(ctx, active_base_name, active_layers) {
|
|
|
242
242
|
});
|
|
243
243
|
}
|
|
244
244
|
//#endregion
|
|
245
|
+
//#region src/extensions/prompt-presets/help.ts
|
|
246
|
+
function is_subcommand(command) {
|
|
247
|
+
return [
|
|
248
|
+
"help",
|
|
249
|
+
"list",
|
|
250
|
+
"show",
|
|
251
|
+
"clear",
|
|
252
|
+
"edit",
|
|
253
|
+
"edit-global",
|
|
254
|
+
"export-defaults",
|
|
255
|
+
"delete",
|
|
256
|
+
"reset",
|
|
257
|
+
"reload",
|
|
258
|
+
"base",
|
|
259
|
+
"enable",
|
|
260
|
+
"disable",
|
|
261
|
+
"toggle"
|
|
262
|
+
].includes(command);
|
|
263
|
+
}
|
|
264
|
+
function format_prompt_preset_help() {
|
|
265
|
+
return `Prompt presets append instructions to the system prompt.
|
|
266
|
+
|
|
267
|
+
Commands:
|
|
268
|
+
- /prompt-preset Open the preset picker
|
|
269
|
+
- /prompt-preset show Show the active base and layers
|
|
270
|
+
- /prompt-preset <name> Activate a base preset or toggle a layer
|
|
271
|
+
- /prompt-preset base <name> Activate a base preset
|
|
272
|
+
- /prompt-preset enable <layer> Enable a layer
|
|
273
|
+
- /prompt-preset disable <layer> Disable a layer
|
|
274
|
+
- /prompt-preset edit <name> Edit/create .pi/presets/<name>.md
|
|
275
|
+
- /prompt-preset edit-global <name> Edit/create ~/.pi/agent/presets/<name>.md
|
|
276
|
+
- /prompt-preset export-defaults Export built-ins to ~/.pi/agent/presets/*.md
|
|
277
|
+
- /prompt-preset export-defaults project Export built-ins to .pi/presets/*.md
|
|
278
|
+
- /prompt-preset reload Reload presets after manual file edits
|
|
279
|
+
- /prompt-preset clear Clear active base and layers
|
|
280
|
+
|
|
281
|
+
Examples:
|
|
282
|
+
- /prompt-preset export-defaults
|
|
283
|
+
- /prompt-preset edit-global terse
|
|
284
|
+
- /prompt-preset base detailed
|
|
285
|
+
- /prompt-preset enable bullets
|
|
286
|
+
- /prompt-preset show
|
|
287
|
+
|
|
288
|
+
Alias: /preset`;
|
|
289
|
+
}
|
|
290
|
+
//#endregion
|
|
245
291
|
//#region src/extensions/prompt-presets/storage.ts
|
|
246
292
|
const PROJECT_PROMPT_PRESETS_ENV = "MY_PI_PROMPT_PRESETS_PROJECT";
|
|
247
293
|
function normalize_prompt_presets(input) {
|
|
@@ -496,18 +542,17 @@ function save_persisted_prompt_state(cwd, state, path = get_persisted_prompt_sta
|
|
|
496
542
|
return path;
|
|
497
543
|
}
|
|
498
544
|
//#endregion
|
|
499
|
-
//#region src/extensions/prompt-presets/
|
|
545
|
+
//#region src/extensions/prompt-presets/state.ts
|
|
500
546
|
const PRESET_STATE_TYPE = "prompt-preset-state";
|
|
501
547
|
const ENABLED = "● enabled";
|
|
502
548
|
const DISABLED = "○ disabled";
|
|
503
549
|
const SELECTED = "● selected";
|
|
504
|
-
const UNSELECTED = "○";
|
|
505
550
|
const NONE_BASE_ID = "__base_none__";
|
|
506
551
|
function get_last_preset_state(ctx) {
|
|
507
552
|
const entries = ctx.sessionManager.getEntries();
|
|
508
553
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
509
554
|
const entry = entries[i];
|
|
510
|
-
if (entry.type === "custom" && entry.customType ===
|
|
555
|
+
if (entry.type === "custom" && entry.customType === "prompt-preset-state" && entry.data) return entry.data;
|
|
511
556
|
}
|
|
512
557
|
}
|
|
513
558
|
function sets_equal(a, b) {
|
|
@@ -532,50 +577,8 @@ function normalize_active_state(presets, active_base_name, active_layers) {
|
|
|
532
577
|
function parse_preset_flag(flag) {
|
|
533
578
|
return flag.split(",").map((item) => item.trim()).filter(Boolean);
|
|
534
579
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
"help",
|
|
538
|
-
"list",
|
|
539
|
-
"show",
|
|
540
|
-
"clear",
|
|
541
|
-
"edit",
|
|
542
|
-
"edit-global",
|
|
543
|
-
"export-defaults",
|
|
544
|
-
"delete",
|
|
545
|
-
"reset",
|
|
546
|
-
"reload",
|
|
547
|
-
"base",
|
|
548
|
-
"enable",
|
|
549
|
-
"disable",
|
|
550
|
-
"toggle"
|
|
551
|
-
].includes(command);
|
|
552
|
-
}
|
|
553
|
-
function format_prompt_preset_help() {
|
|
554
|
-
return `Prompt presets append instructions to the system prompt.
|
|
555
|
-
|
|
556
|
-
Commands:
|
|
557
|
-
- /prompt-preset Open the preset picker
|
|
558
|
-
- /prompt-preset show Show the active base and layers
|
|
559
|
-
- /prompt-preset <name> Activate a base preset or toggle a layer
|
|
560
|
-
- /prompt-preset base <name> Activate a base preset
|
|
561
|
-
- /prompt-preset enable <layer> Enable a layer
|
|
562
|
-
- /prompt-preset disable <layer> Disable a layer
|
|
563
|
-
- /prompt-preset edit <name> Edit/create .pi/presets/<name>.md
|
|
564
|
-
- /prompt-preset edit-global <name> Edit/create ~/.pi/agent/presets/<name>.md
|
|
565
|
-
- /prompt-preset export-defaults Export built-ins to ~/.pi/agent/presets/*.md
|
|
566
|
-
- /prompt-preset export-defaults project Export built-ins to .pi/presets/*.md
|
|
567
|
-
- /prompt-preset reload Reload presets after manual file edits
|
|
568
|
-
- /prompt-preset clear Clear active base and layers
|
|
569
|
-
|
|
570
|
-
Examples:
|
|
571
|
-
- /prompt-preset export-defaults
|
|
572
|
-
- /prompt-preset edit-global terse
|
|
573
|
-
- /prompt-preset base detailed
|
|
574
|
-
- /prompt-preset enable bullets
|
|
575
|
-
- /prompt-preset show
|
|
576
|
-
|
|
577
|
-
Alias: /preset`;
|
|
578
|
-
}
|
|
580
|
+
//#endregion
|
|
581
|
+
//#region src/extensions/prompt-presets/index.ts
|
|
579
582
|
async function prompt_presets(pi) {
|
|
580
583
|
let presets = {};
|
|
581
584
|
let active_base_name;
|
|
@@ -719,8 +722,8 @@ async function prompt_presets(pi) {
|
|
|
719
722
|
id: NONE_BASE_ID,
|
|
720
723
|
label: "(none)",
|
|
721
724
|
description: "No active base preset",
|
|
722
|
-
currentValue:
|
|
723
|
-
values: [SELECTED,
|
|
725
|
+
currentValue: "○",
|
|
726
|
+
values: [SELECTED, "○"]
|
|
724
727
|
});
|
|
725
728
|
base_ids.add(NONE_BASE_ID);
|
|
726
729
|
for (const preset of base_presets) {
|
|
@@ -728,8 +731,8 @@ async function prompt_presets(pi) {
|
|
|
728
731
|
id: preset.name,
|
|
729
732
|
label: preset.name,
|
|
730
733
|
description: [`${get_prompt_source_label(preset.source)} • ${preset.description ?? "base preset"}`].join("\n"),
|
|
731
|
-
currentValue:
|
|
732
|
-
values: [SELECTED,
|
|
734
|
+
currentValue: "○",
|
|
735
|
+
values: [SELECTED, "○"]
|
|
733
736
|
});
|
|
734
737
|
base_ids.add(preset.name);
|
|
735
738
|
}
|
|
@@ -750,7 +753,7 @@ async function prompt_presets(pi) {
|
|
|
750
753
|
layer_ids.add(preset.name);
|
|
751
754
|
}
|
|
752
755
|
function sync_values() {
|
|
753
|
-
for (const item of items) if (base_ids.has(item.id)) item.currentValue = item.id ===
|
|
756
|
+
for (const item of items) if (base_ids.has(item.id)) item.currentValue = item.id === "__base_none__" && !selected_base || item.id === selected_base ? SELECTED : "○";
|
|
754
757
|
else if (layer_ids.has(item.id)) item.currentValue = enabled_layers.has(item.id) ? ENABLED : DISABLED;
|
|
755
758
|
}
|
|
756
759
|
sync_values();
|
|
@@ -763,12 +766,12 @@ async function prompt_presets(pi) {
|
|
|
763
766
|
on_change: (id, new_value) => {
|
|
764
767
|
if (id.startsWith("__header_")) return;
|
|
765
768
|
if (base_ids.has(id)) {
|
|
766
|
-
selected_base = new_value ===
|
|
769
|
+
selected_base = new_value === "● selected" && id !== "__base_none__" ? id : void 0;
|
|
767
770
|
sync_values();
|
|
768
771
|
return;
|
|
769
772
|
}
|
|
770
773
|
if (layer_ids.has(id)) {
|
|
771
|
-
if (new_value ===
|
|
774
|
+
if (new_value === "● enabled") enabled_layers.add(id);
|
|
772
775
|
else enabled_layers.delete(id);
|
|
773
776
|
sync_values();
|
|
774
777
|
}
|
|
@@ -1004,4 +1007,4 @@ async function prompt_presets(pi) {
|
|
|
1004
1007
|
//#endregion
|
|
1005
1008
|
export { prompt_presets as default };
|
|
1006
1009
|
|
|
1007
|
-
//# sourceMappingURL=prompt-presets-
|
|
1010
|
+
//# sourceMappingURL=prompt-presets-BhlErXaD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-presets-BhlErXaD.js","names":[],"sources":["../src/extensions/prompt-presets/catalog.ts","../src/extensions/prompt-presets/defaults.ts","../src/extensions/prompt-presets/footer.ts","../src/extensions/prompt-presets/help.ts","../src/extensions/prompt-presets/storage.ts","../src/extensions/prompt-presets/state.ts","../src/extensions/prompt-presets/index.ts"],"sourcesContent":["import type {\n\tLoadedPromptPreset,\n\tPromptPresetSource,\n} from './types.js';\n\nexport function get_prompt_source_label(\n\tsource: PromptPresetSource,\n): 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\nexport function 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\nexport function 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\nexport function 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\nexport function 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","import type { PromptPresetMap } from './types.js';\n\nexport const DEFAULT_BASE_PROMPT_PRESET_NAME = 'terse';\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","import {\n\tclampThinkingLevel,\n\tgetSupportedThinkingLevels,\n\ttype ModelThinkingLevel,\n} from '@earendil-works/pi-ai';\nimport type {\n\tExtensionContext,\n\tReadonlyFooterDataProvider,\n} from '@earendil-works/pi-coding-agent';\nimport {\n\ttruncateToWidth,\n\tvisibleWidth,\n} from '@earendil-works/pi-tui';\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\nconst VALID_THINKING_LEVELS = new Set<ModelThinkingLevel>([\n\t'off',\n\t'minimal',\n\t'low',\n\t'medium',\n\t'high',\n\t'xhigh',\n]);\n\nfunction is_model_thinking_level(\n\tlevel: string,\n): level is ModelThinkingLevel {\n\treturn VALID_THINKING_LEVELS.has(level as ModelThinkingLevel);\n}\n\nexport function get_default_footer_thinking_level(\n\tmodel: ExtensionContext['model'],\n): ModelThinkingLevel {\n\tif (!model?.reasoning) return 'off';\n\treturn clampThinkingLevel(model, 'medium');\n}\n\nexport function get_current_thinking_level(\n\tctx: Pick<ExtensionContext, 'model' | 'sessionManager'>,\n): ModelThinkingLevel {\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\tis_model_thinking_level(entry.thinkingLevel)\n\t\t) {\n\t\t\tif (!ctx.model?.reasoning) return 'off';\n\t\t\treturn getSupportedThinkingLevels(ctx.model).includes(\n\t\t\t\tentry.thinkingLevel,\n\t\t\t)\n\t\t\t\t? entry.thinkingLevel\n\t\t\t\t: clampThinkingLevel(ctx.model, entry.thinkingLevel);\n\t\t}\n\t}\n\treturn get_default_footer_thinking_level(ctx.model);\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\nexport function 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","export function 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\nexport function 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","import { getAgentDir } from '@earendil-works/pi-coding-agent';\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';\nimport { DEFAULT_PROMPT_PRESETS } from './defaults.js';\nimport type {\n\tLoadedPromptPreset,\n\tPromptPreset,\n\tPromptPresetMap,\n\tPromptPresetSource,\n\tPromptPresetState,\n} from './types.js';\n\nconst PROJECT_PROMPT_PRESETS_ENV = 'MY_PI_PROMPT_PRESETS_PROJECT';\n\ninterface PersistedPromptPresetStates {\n\tversion: number;\n\tprojects: Record<string, PromptPresetState>;\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\nexport function get_global_presets_dir(): string {\n\treturn join(getAgentDir(), 'presets');\n}\n\nexport function 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\nexport function 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\nexport function 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\nexport function 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","import type {\n\tExtensionAPI,\n\tExtensionContext,\n} from '@earendil-works/pi-coding-agent';\nimport { save_persisted_prompt_state } from './storage.js';\nimport type {\n\tLoadedPromptPreset,\n\tPromptPresetState,\n} from './types.js';\n\nexport const PRESET_STATE_TYPE = 'prompt-preset-state';\nexport const ENABLED = '● enabled';\nexport const DISABLED = '○ disabled';\nexport const SELECTED = '● selected';\nexport const UNSELECTED = '○';\nexport const NONE_BASE_ID = '__base_none__';\n\nexport function 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\nexport function 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\nexport function 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\nexport function 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\nexport function 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","import {\n\ttype ExtensionAPI,\n\ttype ExtensionCommandContext,\n\ttype ExtensionContext,\n} from '@earendil-works/pi-coding-agent';\nimport type { SettingItem } from '@earendil-works/pi-tui';\nimport { show_settings_modal } from '@spences10/pi-tui-modal';\nimport { existsSync } from 'node:fs';\nimport {\n\tformat_active_details,\n\tformat_summary,\n\tget_prompt_source_label,\n\tlist_base_presets,\n\tlist_layer_presets,\n} from './catalog.js';\nimport {\n\tDEFAULT_BASE_PROMPT_PRESET_NAME,\n\tDEFAULT_PROMPT_PRESETS,\n} from './defaults.js';\nimport { set_status } from './footer.js';\nimport { format_prompt_preset_help, is_subcommand } from './help.js';\nimport {\n\tDISABLED,\n\tENABLED,\n\tget_last_preset_state,\n\tNONE_BASE_ID,\n\tnormalize_active_state,\n\tparse_preset_flag,\n\tpersist_state,\n\tSELECTED,\n\tsets_equal,\n\tUNSELECTED,\n} from './state.js';\nimport {\n\tget_global_presets_dir,\n\tget_project_presets_dir,\n\tget_prompt_preset_file_path,\n\tload_persisted_prompt_state,\n\tload_prompt_presets,\n\tremove_project_prompt_preset,\n\tsave_global_prompt_preset_file,\n\tsave_project_prompt_preset_file,\n\tsave_prompt_preset_file,\n} from './storage.js';\nimport type {\n\tLoadedPromptPreset,\n\tPromptPresetKind,\n} from './types.js';\n\nexport {\n\tDEFAULT_BASE_PROMPT_PRESET_NAME,\n\tDEFAULT_PROMPT_PRESETS,\n} from './defaults.js';\nexport {\n\tget_current_thinking_level,\n\tget_default_footer_thinking_level,\n\trender_footer_status_line,\n} from './footer.js';\nexport {\n\tload_persisted_prompt_state,\n\tload_prompt_presets,\n\tmerge_prompt_presets,\n\tnormalize_prompt_presets,\n\tread_prompt_presets_dir,\n\tremove_project_prompt_preset,\n\tsave_persisted_prompt_state,\n\tsave_project_prompt_presets,\n\tsave_prompt_preset_file,\n} from './storage.js';\nexport type {\n\tLoadedPromptPreset,\n\tPromptPreset,\n\tPromptPresetKind,\n\tPromptPresetMap,\n\tPromptPresetSource,\n\tPromptPresetState,\n} from './types.js';\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 ['prompt-preset', 'preset']) {\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"],"mappings":";;;;;;;AAKA,SAAgB,wBACf,QACS;CACT,QAAQ,QAAR;EACC,KAAK,WACJ,OAAO;EACR,KAAK,QACJ,OAAO;EACR,KAAK,WACJ,OAAO;;;AAIV,SAAgB,kBACf,SACuB;CACvB,OAAO,OAAO,OAAO,QAAQ,CAC3B,QAAQ,WAAW,OAAO,SAAS,OAAO,CAC1C,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC;;AAG/C,SAAgB,mBACf,SACuB;CACvB,OAAO,OAAO,OAAO,QAAQ,CAC3B,QAAQ,WAAW,OAAO,SAAS,QAAQ,CAC3C,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC;;AAG/C,SAAgB,eACf,kBACA,eACA,SACS;CACT,MAAM,QAAQ,CAAC,SAAS,oBAAoB,WAAW;CAEvD,MAAM,cAAc,CAAC,GAAG,cAAc,CAAC,MAAM;CAC7C,IAAI,YAAY,WAAW,GAC1B,MAAM,KAAK,iBAAiB;MACtB;EACN,MAAM,KAAK,UAAU;EACrB,KAAK,MAAM,QAAQ,aAAa;GAC/B,MAAM,SAAS,QAAQ;GACvB,MAAM,cAAc,QAAQ,cACzB,MAAM,OAAO,gBACb;GACH,MAAM,KAAK,KAAK,OAAO,cAAc;;;CAIvC,OAAO,MAAM,KAAK,KAAK;;AAGxB,SAAgB,sBACf,kBACA,eACA,SACS;CACT,MAAM,QAAkB,EAAE;CAE1B,IAAI,kBAAkB;EACrB,MAAM,OAAO,QAAQ;EACrB,IAAI,MAAM;GACT,MAAM,KAAK,SAAS,KAAK,OAAO;GAChC,IAAI,KAAK,aACR,MAAM,KAAK,gBAAgB,KAAK,cAAc;GAC/C,MAAM,KAAK,WAAW,wBAAwB,KAAK,OAAO,GAAG;GAC7D,MAAM,KAAK,IAAI,KAAK,aAAa,MAAM,CAAC;;;CAI1C,MAAM,cAAc,CAAC,GAAG,cAAc,CAAC,MAAM;CAC7C,IAAI,YAAY,SAAS,GAAG;EAC3B,IAAI,MAAM,SAAS,GAAG,MAAM,KAAK,IAAI,OAAO,GAAG;EAC/C,MAAM,KAAK,UAAU;EACrB,KAAK,MAAM,QAAQ,aAAa;GAC/B,MAAM,QAAQ,QAAQ;GACtB,IAAI,CAAC,OAAO;GACZ,MAAM,KACL,KAAK,MAAM,KAAK,IAAI,wBAAwB,MAAM,OAAO,CAAC,GAC1D;GACD,IAAI,MAAM,aAAa,MAAM,KAAK,KAAK,MAAM,cAAc;;;CAI7D,OAAO,MAAM,KAAK,KAAK,IAAI;;ACtF5B,MAAa,yBAA0C;CACtD,OAAO;EACN,MAAM;EACN,aAAa;EACb,cACC;EACD;CACD,UAAU;EACT,MAAM;EACN,aAAa;EACb,cACC;EACD;CACD,UAAU;EACT,MAAM;EACN,aAAa;EACb,cACC;EACD;CACD,mBAAmB;EAClB,MAAM;EACN,aAAa;EACb,cACC;EACD;CACD,SAAS;EACR,MAAM;EACN,aAAa;EACb,cACC;EACD;CACD,iBAAiB;EAChB,MAAM;EACN,aACC;EACD,cACC;EACD;CACD,iBAAiB;EAChB,MAAM;EACN,aAAa;EACb,cACC;EACD;CACD;;;AClCD,SAAS,yBACR,kBACA,eACqB;CACrB,IAAI,CAAC,oBAAoB,cAAc,SAAS,GAC/C;CAMD,OAAO,UAHO,oBAAoB,SAEjC,cAAc,OAAO,IAAI,KAAK,cAAc,SAAS;;AAIvD,SAAS,qBAAqB,MAAsB;CACnD,OAAO,KACL,QAAQ,aAAa,IAAI,CACzB,QAAQ,OAAO,IAAI,CACnB,MAAM;;AAGT,SAAS,mBAAmB,OAAuB;CAClD,IAAI,QAAQ,KAAM,OAAO,MAAM,UAAU;CACzC,IAAI,QAAQ,KAAO,OAAO,IAAI,QAAQ,KAAM,QAAQ,EAAE,CAAC;CACvD,IAAI,QAAQ,KAAS,OAAO,GAAG,KAAK,MAAM,QAAQ,IAAK,CAAC;CACxD,IAAI,QAAQ,KAAU,OAAO,IAAI,QAAQ,KAAS,QAAQ,EAAE,CAAC;CAC7D,OAAO,GAAG,KAAK,MAAM,QAAQ,IAAQ,CAAC;;AAGvC,SAAgB,0BACf,OACA,OACA,YACA,YACqB;CACrB,MAAM,OAAO,qBAAqB,WAAW,KAAK,IAAI,CAAC;CACvD,MAAM,QAAQ,aAAa,qBAAqB,WAAW,GAAG;CAC9D,IAAI,CAAC,QAAQ,CAAC,OAAO,OAAO,KAAA;CAC5B,IAAI,CAAC,OACJ,OAAO,gBACN,MAAM,GAAG,OAAO,KAAK,EACrB,OACA,MAAM,GAAG,OAAO,MAAM,CACtB;CAEF,IAAI,CAAC,MAAM;EACV,MAAM,eAAe,MAAM,GAAG,OAAO,MAAM;EAC3C,MAAM,cAAc,aAAa,aAAa;EAC9C,OAAO,eAAe,QACnB,gBAAgB,cAAc,OAAO,MAAM,GAAG,OAAO,MAAM,CAAC,GAC5D,GAAG,IAAI,OAAO,QAAQ,YAAY,GAAG;;CAGzC,MAAM,cAAc,aAAa,MAAM;CACvC,IAAI,eAAe,OAClB,OAAO,gBACN,MAAM,GAAG,OAAO,MAAM,EACtB,OACA,MAAM,GAAG,OAAO,MAAM,CACtB;CAGF,MAAM,UAAU;CAEhB,MAAM,iBAAiB,gBAAgB,MADhB,KAAK,IAAI,GAAG,QAAQ,cAAc,QACE,EAAE,MAAM;CACnE,MAAM,aAAa,aAAa,eAAe;CAC/C,MAAM,MAAM,KAAK,IAAI,SAAS,QAAQ,aAAa,YAAY;CAC/D,OACC,MAAM,GAAG,OAAO,eAAe,GAC/B,IAAI,OAAO,IAAI,GACf,MAAM,GAAG,OAAO,MAAM;;AAIxB,MAAM,wBAAwB,IAAI,IAAwB;CACzD;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;AAEF,SAAS,wBACR,OAC8B;CAC9B,OAAO,sBAAsB,IAAI,MAA4B;;AAG9D,SAAgB,kCACf,OACqB;CACrB,IAAI,CAAC,OAAO,WAAW,OAAO;CAC9B,OAAO,mBAAmB,OAAO,SAAS;;AAG3C,SAAgB,2BACf,KACqB;CACrB,MAAM,UAAU,IAAI,eAAe,YAAY;CAC/C,KAAK,IAAI,IAAI,QAAQ,SAAS,GAAG,KAAK,GAAG,KAAK;EAC7C,MAAM,QAAQ,QAAQ;EAItB,IACC,MAAM,SAAS,2BACf,OAAO,MAAM,kBAAkB,YAC/B,wBAAwB,MAAM,cAAc,EAC3C;GACD,IAAI,CAAC,IAAI,OAAO,WAAW,OAAO;GAClC,OAAO,2BAA2B,IAAI,MAAM,CAAC,SAC5C,MAAM,cACN,GACE,MAAM,gBACN,mBAAmB,IAAI,OAAO,MAAM,cAAc;;;CAGvD,OAAO,kCAAkC,IAAI,MAAM;;AAGpD,SAAS,oBACR,KACA,OACA,aACA,OACA,kBACA,eACW;CACX,IAAI,cAAc;CAClB,IAAI,eAAe;CACnB,IAAI,mBAAmB;CACvB,IAAI,oBAAoB;CACxB,IAAI,aAAa;CACjB,KAAK,MAAM,SAAS,IAAI,eAAe,YAAY,EAClD,IACC,MAAM,SAAS,aACf,MAAM,QAAQ,SAAS,aACtB;EACD,eAAe,MAAM,QAAQ,MAAM;EACnC,gBAAgB,MAAM,QAAQ,MAAM;EACpC,oBAAoB,MAAM,QAAQ,MAAM;EACxC,qBAAqB,MAAM,QAAQ,MAAM;EACzC,cAAc,MAAM,QAAQ,MAAM,KAAK;;CAIzC,MAAM,gBAAgB,IAAI,iBAAiB;CAC3C,MAAM,iBACL,eAAe,iBAAiB,IAAI,OAAO,iBAAiB;CAC7D,MAAM,wBAAwB,eAAe,WAAW;CACxD,MAAM,kBACL,eAAe,YAAY,OACxB,sBAAsB,QAAQ,EAAE,GAChC;CAEJ,IAAI,MAAM,IAAI;CACd,MAAM,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI;CAC7C,IAAI,QAAQ,IAAI,WAAW,KAAK,EAC/B,MAAM,IAAI,IAAI,MAAM,KAAK,OAAO;CAGjC,MAAM,SAAS,YAAY,cAAc;CACzC,IAAI,QACH,MAAM,GAAG,IAAI,IAAI,OAAO;CAGzB,MAAM,eAAe,IAAI,eAAe,gBAAgB;CACxD,IAAI,cACH,MAAM,GAAG,IAAI,KAAK;CAGnB,MAAM,cAAwB,EAAE;CAChC,IAAI,aACH,YAAY,KAAK,IAAI,mBAAmB,YAAY,GAAG;CACxD,IAAI,cACH,YAAY,KAAK,IAAI,mBAAmB,aAAa,GAAG;CACzD,IAAI,kBACH,YAAY,KAAK,IAAI,mBAAmB,iBAAiB,GAAG;CAC7D,IAAI,mBACH,YAAY,KAAK,IAAI,mBAAmB,kBAAkB,GAAG;CAE9D,MAAM,qBAAqB,IAAI,QAC5B,IAAI,cAAc,aAAa,IAAI,MAAM,GACzC;CACH,IAAI,cAAc,oBACjB,YAAY,KACX,IAAI,WAAW,QAAQ,EAAE,GAAG,qBAAqB,WAAW,KAC5D;CAGF,MAAM,0BACL,oBAAoB,MACjB,KAAK,mBAAmB,eAAe,KACvC,GAAG,gBAAgB,IAAI,mBAAmB,eAAe;CAC7D,IAAI,sBAAsB;CAC1B,IAAI,wBAAwB,IAC3B,sBAAsB,MAAM,GAAG,SAAS,wBAAwB;MAC1D,IAAI,wBAAwB,IAClC,sBAAsB,MAAM,GAC3B,WACA,wBACA;CAEF,YAAY,KAAK,oBAAoB;CAErC,IAAI,aAAa,YAAY,KAAK,IAAI;CACtC,IAAI,mBAAmB,aAAa,WAAW;CAC/C,IAAI,mBAAmB,OAAO;EAC7B,aAAa,gBAAgB,YAAY,OAAO,MAAM;EACtD,mBAAmB,aAAa,WAAW;;CAG5C,MAAM,aAAa,IAAI,OAAO,MAAM;CACpC,MAAM,iBAAiB,2BAA2B,IAAI;CACtD,IAAI,8BAA8B;CAClC,IAAI,IAAI,OAAO,WACd,8BACC,mBAAmB,QAChB,GAAG,WAAW,mBACd,GAAG,WAAW,KAAK;CAGxB,IAAI,aAAa;CACjB,IAAI,YAAY,2BAA2B,GAAG,KAAK,IAAI,OAAO;EAC7D,aAAa,IAAI,IAAI,MAAM,SAAS,IAAI;EACxC,IAAI,mBAAmB,IAAI,aAAa,WAAW,GAAG,OACrD,aAAa;;CAIf,MAAM,mBAAmB,aAAa,WAAW;CACjD,MAAM,eAAe,mBAAmB,IAAI;CAC5C,IAAI;CACJ,IAAI,gBAAgB,OAAO;EAC1B,MAAM,UAAU,IAAI,OACnB,QAAQ,mBAAmB,iBAC3B;EACD,aAAa,aAAa,UAAU;QAC9B;EACN,MAAM,sBAAsB,QAAQ,mBAAmB;EACvD,IAAI,sBAAsB,GAAG;GAC5B,MAAM,kBAAkB,gBACvB,YACA,qBACA,GACA;GACD,MAAM,wBAAwB,aAAa,gBAAgB;GAC3D,MAAM,UAAU,IAAI,OACnB,KAAK,IAAI,GAAG,QAAQ,mBAAmB,sBAAsB,CAC7D;GACD,aAAa,aAAa,UAAU;SAEpC,aAAa;;CAIf,MAAM,iBAAiB,MAAM,GAAG,OAAO,WAAW;CAClD,MAAM,YAAY,WAAW,MAAM,WAAW,OAAO;CACrD,MAAM,gBAAgB,MAAM,GAAG,OAAO,UAAU;CAChD,MAAM,QAAQ,CACb,gBACC,MAAM,GAAG,OAAO,IAAI,EACpB,OACA,MAAM,GAAG,OAAO,MAAM,CACtB,EACD,iBAAiB,cACjB;CAED,MAAM,gBAAgB,yBACrB,kBACA,cACA;CAQD,MAAM,uBAAuB,0BAC5B,OACA,OARsB,MAAM,KAC5B,YAAY,sBAAsB,CAAC,SAAS,CAC5C,CACC,QAAQ,CAAC,SAAS,QAAQ,SAAS,CACnC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC,CACtC,KAAK,GAAG,UAAU,qBAAqB,KAAK,CAI/B,EACd,cACA;CACD,IAAI,sBACH,MAAM,KAAK,qBAAqB;CAGjC,OAAO;;AAGR,SAAgB,WACf,KACA,kBACA,eACO;CACP,IAAI,GAAG,UAAU,UAAU,KAAA,EAAU;CACrC,IAAI,CAAC,IAAI,OAAO;CAChB,IAAI,GAAG,WAAW,KAAK,OAAO,gBAAgB;EAI7C,OAAO;GACN,SAJmB,YAAY,qBAC/B,IAAI,eAAe,CAGC;GACpB,aAAa;GACb,OAAO,OAAe;IACrB,OAAO,oBACN,KACA,OACA,aACA,OACA,kBACA,cACA;;GAEF;GACA;;;;AC5UH,SAAgB,cAAc,SAA0B;CACvD,OAAO;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,CAAC,SAAS,QAAQ;;AAGpB,SAAgB,4BAAoC;CACnD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAR,MAAM,6BAA6B;AAOnC,SAAgB,yBACf,OACkB;CAClB,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU,OAAO,EAAE;CAElD,MAAM,aAA8B,EAAE;CACtC,KAAK,MAAM,CAAC,UAAU,cAAc,OAAO,QAAQ,MAAM,EAAE;EAC1D,MAAM,OAAO,SAAS,MAAM;EAC5B,IAAI,CAAC,MAAM;EAEX,IAAI,OAAO,cAAc,UAAU;GAClC,WAAW,QAAQ;IAClB,MAAM;IACN,cAAc;IACd;GACD;;EAGD,IAAI,CAAC,aAAa,OAAO,cAAc,UAAU;EACjD,MAAM,YAAY;EAKlB,IAAI,OAAO,UAAU,iBAAiB,UAAU;EAEhD,WAAW,QAAQ;GAClB,cAAc,UAAU;GACxB,GAAI,UAAU,SAAS,UACpB,EAAE,MAAM,SAAkB,GAC1B,EAAE;GACL,GAAI,OAAO,UAAU,gBAAgB,WAClC,EAAE,aAAa,UAAU,aAAa,GACtC,EAAE;GACL;;CAGF,OAAO;;AASR,SAAS,yBACR,SACA,QACqC;CACrC,OAAO,OAAO,YACb,OAAO,QAAQ,QAAQ,CAAC,KAAK,CAAC,MAAM,YAAY,CAC/C,MACA;EACC;EACA,MAAM,OAAO,SAAS,UAAU,UAAU;EAC1C;EACA,GAAG;EACH,CACD,CAAC,CACF;;AAGF,SAAS,0BAAkC;CAC1C,OAAO,KAAK,aAAa,EAAE,eAAe;;AAG3C,SAAS,yBAAyB,KAAqB;CACtD,OAAO,KAAK,KAAK,OAAO,eAAe;;AAGxC,SAAgB,yBAAiC;CAChD,OAAO,KAAK,aAAa,EAAE,UAAU;;AAGtC,SAAgB,wBAAwB,KAAqB;CAC5D,OAAO,KAAK,KAAK,OAAO,UAAU;;AAGnC,SAAS,iCAAiC,MAAsB;CAC/D,MAAM,YAAY,KAChB,MAAM,CACN,QAAQ,iBAAiB,IAAI,CAC7B,QAAQ,SAAS,GAAG,CACpB,QAAQ,QAAQ,GAAG,CACnB,QAAQ,QAAQ,GAAG;CACrB,IAAI,CAAC,WACJ,MAAM,IAAI,MACT,wDACA;CAEF,OAAO;;AAGR,SAAgB,4BACf,KACA,MACS;CACT,OAAO,KAAK,KAAK,GAAG,iCAAiC,KAAK,CAAC,KAAK;;AAGjE,SAAS,kCAA0C;CAClD,OAAO,KAAK,aAAa,EAAE,2BAA2B;;AAGvD,SAAS,yBAAyB,MAA+B;CAChE,IAAI,CAAC,WAAW,KAAK,EAAE,OAAO,EAAE;CAEhC,IAAI;EACH,OAAO,yBACN,KAAK,MAAM,aAAa,MAAM,QAAQ,CAAC,CACvC;SACM;EACP,OAAO,EAAE;;;AAIX,SAAS,0BAA0B,OAAuB;CACzD,MAAM,UAAU,MAAM,MAAM;CAC5B,IAAI,QAAQ,WAAW,KAAI,IAAI,QAAQ,SAAS,KAAI,EACnD,IAAI;EACH,OAAO,KAAK,MAAM,QAAQ;SACnB;EACP,OAAO,QAAQ,MAAM,GAAG,GAAG;;CAG7B,IAAI,QAAQ,WAAW,IAAI,IAAI,QAAQ,SAAS,IAAI,EACnD,OAAO,QAAQ,MAAM,GAAG,GAAG;CAE5B,OAAO;;AAGR,SAAS,6BAA6B,SAGpC;CACD,MAAM,aAAa,QAAQ,QAAQ,SAAS,KAAK;CACjD,IAAI,CAAC,WAAW,WAAW,QAAQ,EAClC,OAAO;EAAE,UAAU,EAAE;EAAE,MAAM,WAAW,MAAM;EAAE;CAGjD,MAAM,QAAQ,WAAW,MAAM,KAAK;CACpC,MAAM,MAAM,MAAM,WAChB,MAAM,UAAU,QAAQ,KAAK,KAAK,MAAM,KAAK,MAC9C;CACD,IAAI,QAAQ,IACX,OAAO;EAAE,UAAU,EAAE;EAAE,MAAM,WAAW,MAAM;EAAE;CAGjD,MAAM,WAAmC,EAAE;CAC3C,KAAK,MAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,EAAE;EACvC,MAAM,YAAY,KAAK,QAAQ,IAAI;EACnC,IAAI,cAAc,IAAI;EACtB,MAAM,MAAM,KAAK,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,aAAa;EACzD,MAAM,QAAQ,KAAK,MAAM,YAAY,EAAE,CAAC,MAAM;EAC9C,IAAI,CAAC,KAAK;EACV,SAAS,OAAO,0BAA0B,MAAM;;CAGjD,OAAO;EACN;EACA,MAAM,MACJ,MAAM,MAAM,EAAE,CACd,KAAK,KAAK,CACV,MAAM;EACR;;AAGF,SAAgB,wBACf,MACkB;CAClB,IAAI,CAAC,WAAW,KAAK,EAAE,OAAO,EAAE;CAEhC,IAAI;EACH,MAAM,UAA2B,EAAE;EACnC,KAAK,MAAM,SAAS,YAAY,MAAM,EAAE,eAAe,MAAM,CAAC,CAC5D,QAAQ,SAAS,KAAK,QAAQ,IAAI,KAAK,KAAK,SAAS,MAAM,CAAC,CAC5D,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,EAAE;GAC/C,MAAM,OAAO,MAAM,KAAK,MAAM,GAAG,GAAG,CAAC,MAAM;GAC3C,IAAI,CAAC,MAAM;GACX,MAAM,EAAE,UAAU,SAAS,6BAC1B,aAAa,KAAK,MAAM,MAAM,KAAK,EAAE,QAAQ,CAC7C;GACD,IAAI,CAAC,MAAM;GACX,QAAQ,QAAQ;IACf,MAAM,SAAS,SAAS,UAAU,UAAU;IAC5C,cAAc;IACd,GAAI,SAAS,cACV,EAAE,aAAa,SAAS,aAAa,GACrC,EAAE;IACL;;EAEF,OAAO;SACA;EACP,OAAO,EAAE;;;AAIX,SAAS,8BAA8B,QAA8B;CACpE,MAAM,QAAQ,CACb,OACA,SAAS,OAAO,SAAS,UAAU,UAAU,SAC7C;CACD,IAAI,OAAO,aAAa,MAAM,EAC7B,MAAM,KACL,gBAAgB,KAAK,UAAU,OAAO,YAAY,MAAM,CAAC,GACzD;CAEF,MAAM,KAAK,OAAO,IAAI,OAAO,aAAa,MAAM,EAAE,GAAG;CACrD,OAAO,MAAM,KAAK,KAAK;;AAGxB,SAAgB,wBACf,KACA,MACA,QACS;CACT,IAAI,CAAC,WAAW,IAAI,EACnB,UAAU,KAAK;EAAE,WAAW;EAAM,MAAM;EAAO,CAAC;CAGjD,MAAM,OAAO,4BAA4B,KAAK,KAAK;CACnD,MAAM,MAAM,GAAG,KAAK,OAAO,KAAK,KAAK;CACrC,cAAc,KAAK,8BAA8B,OAAO,EAAE,EACzD,MAAM,KACN,CAAC;CACF,WAAW,KAAK,KAAK;CACrB,OAAO;;AAGR,SAAgB,gCACf,KACA,MACA,QACS;CACT,OAAO,wBACN,wBAAwB,IAAI,EAC5B,MACA,OACA;;AAGF,SAAgB,+BACf,MACA,QACS;CACT,OAAO,wBACN,wBAAwB,EACxB,MACA,OACA;;AAGF,SAAS,qCAA8C;CACtD,MAAM,aAAa,QAAQ,IAAI,6BAC5B,MAAM,CACP,aAAa;CACf,OAAO,CAAC;EAAC;EAAK;EAAS;EAAM;EAAQ;EAAU,CAAC,SAC/C,cAAc,GACd;;AAGF,SAAgB,oBACf,KACqC;CACrC,OAAO,OAAO,OACb,EAAE,EACF,yBAAyB,wBAAwB,UAAU,EAC3D,yBACC,yBAAyB,yBAAyB,CAAC,EACnD,OACA,EACD,yBACC,wBAAwB,wBAAwB,CAAC,EACjD,OACA,EACD,GAAI,oCAAoC,GACrC,CACA,yBACC,yBAAyB,yBAAyB,IAAI,CAAC,EACvD,UACA,EACD,yBACC,wBAAwB,wBAAwB,IAAI,CAAC,EACrD,UACA,CACD,GACA,EAAE,CACL;;AAGF,SAAS,oBACR,SACkB;CAClB,OAAO,OAAO,YACb,OAAO,QAAQ,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC,CAC9D;;AAGF,SAAgB,4BACf,KACA,SACS;CACT,MAAM,OAAO,yBAAyB,IAAI;CAC1C,MAAM,MAAM,QAAQ,KAAK;CACzB,IAAI,CAAC,WAAW,IAAI,EACnB,UAAU,KAAK;EAAE,WAAW;EAAM,MAAM;EAAO,CAAC;CAGjD,MAAM,MAAM,GAAG,KAAK,OAAO,KAAK,KAAK;CACrC,cACC,KACA,KAAK,UAAU,oBAAoB,QAAQ,EAAE,MAAM,IAAK,GAAG,MAC3D,EAAE,MAAM,KAAO,CACf;CACD,WAAW,KAAK,KAAK;CACrB,OAAO;;AAGR,SAAgB,6BACf,KACA,MAKC;CACD,MAAM,YAAY,yBAAyB,IAAI;CAC/C,MAAM,kBAAkB,yBAAyB,UAAU;CAC3D,IAAI,UAAU;CACd,IAAI,eAAe;CAEnB,IAAI,QAAQ,iBAAiB;EAC5B,OAAO,gBAAgB;EACvB,UAAU;EACV,eAAe;EACf,IAAI,OAAO,KAAK,gBAAgB,CAAC,WAAW;OACvC,WAAW,UAAU,EACxB,WAAW,UAAU;SAGtB,4BAA4B,KAAK,gBAAgB;;CAInD,MAAM,YAAY,4BACjB,wBAAwB,IAAI,EAC5B,KACA;CACD,IAAI,WAAW,UAAU,EAAE;EAC1B,WAAW,UAAU;EACrB,UAAU;EACV,eAAe;;CAGhB,MAAM,YACL,OAAO,KAAK,yBAAyB,UAAU,CAAC,CAAC,SACjD,OAAO,KAAK,wBAAwB,wBAAwB,IAAI,CAAC,CAAC,CAChE;CAEH,OAAO;EAAE;EAAS,MAAM;EAAc;EAAW;;AAGlD,SAAS,8BACR,OACgC;CAChC,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU,OAAO,KAAA;CAEhD,MAAM,YAAY;CAsBlB,OAAO;EACN,WAlBA,OAAO,UAAU,cAAc,YAC/B,UAAU,UAAU,MAAM,GACvB,UAAU,UAAU,MAAM,GAC1B;EAgBH,aAfmB,MAAM,QAAQ,UAAU,YAAY,GACrD,CACA,GAAG,IAAI,IACN,UAAU,YACR,QACC,UACA,OAAO,UAAU,YAAY,MAAM,MAAM,CAAC,SAAS,EACpD,CACA,KAAK,UAAU,MAAM,MAAM,CAAC,CAC9B,CACD,CAAC,MAAM,GACP,EAAE;EAKJ;;AAGF,SAAS,6BACR,OAAO,iCAAiC,EACV;CAC9B,IAAI,CAAC,WAAW,KAAK,EACpB,OAAO;EAAE,SAAS;EAAG,UAAU,EAAE;EAAE;CAGpC,IAAI;EACH,MAAM,SAAS,KAAK,MAAM,aAAa,MAAM,QAAQ,CAAC;EAItD,MAAM,eACL,OAAO,YAAY,OAAO,OAAO,aAAa,WAC3C,OAAO,WACP,EAAE;EACN,MAAM,WAA8C,EAAE;EACtD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,aAAa,EAAE;GACxD,MAAM,aAAa,8BAA8B,MAAM;GACvD,IAAI,CAAC,YAAY;GACjB,SAAS,OAAO;;EAEjB,OAAO;GACN,SACC,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;GACvD;GACA;SACM;EACP,OAAO;GAAE,SAAS;GAAG,UAAU,EAAE;GAAE;;;AAIrC,SAAgB,4BACf,KACA,OAAO,iCAAiC,EACR;CAChC,OAAO,6BAA6B,KAAK,CAAC,SAAS;;AAGpD,SAAgB,4BACf,KACA,OACA,OAAO,iCAAiC,EAC/B;CACT,MAAM,YAAY,6BAA6B,KAAK;CACpD,UAAU,SAAS,OAAO,8BAA8B,MAAM,IAAI;EACjE,WAAW;EACX,aAAa,EAAE;EACf;CAED,MAAM,MAAM,QAAQ,KAAK;CACzB,IAAI,CAAC,WAAW,IAAI,EACnB,UAAU,KAAK;EAAE,WAAW;EAAM,MAAM;EAAO,CAAC;CAGjD,MAAM,MAAM,GAAG,KAAK,OAAO,KAAK,KAAK;CACrC,cACC,KACA,KAAK,UACJ;EACC,SAAS;EACT,UAAU,OAAO,YAChB,OAAO,QAAQ,UAAU,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,OAC9C,EAAE,cAAc,EAAE,CAClB,CACD;EACD,EACD,MACA,IACA,GAAG,MACJ,EAAE,MAAM,KAAO,CACf;CACD,WAAW,KAAK,KAAK;CACrB,OAAO;;;;ACteR,MAAa,oBAAoB;AACjC,MAAa,UAAU;AACvB,MAAa,WAAW;AACxB,MAAa,WAAW;AAExB,MAAa,eAAe;AAE5B,SAAgB,sBACf,KACgC;CAChC,MAAM,UAAU,IAAI,eAAe,YAAY;CAC/C,KAAK,IAAI,IAAI,QAAQ,SAAS,GAAG,KAAK,GAAG,KAAK;EAC7C,MAAM,QAAQ,QAAQ;EAKtB,IACC,MAAM,SAAS,YACf,MAAM,eAAA,yBACN,MAAM,MAEN,OAAO,MAAM;;;AAMhB,SAAgB,WACf,GACA,GACU;CACV,IAAI,EAAE,SAAS,EAAE,MAAM,OAAO;CAC9B,KAAK,MAAM,SAAS,GACnB,IAAI,CAAC,EAAE,IAAI,MAAM,EAAE,OAAO;CAE3B,OAAO;;AAGR,SAAgB,cACf,IACA,KACA,kBACA,eACO;CACP,MAAM,QAAQ;EACb,WAAW,oBAAoB;EAC/B,aAAa,CAAC,GAAG,cAAc,CAAC,MAAM;EACtC;CACD,GAAG,YAAY,mBAAmB,MAAM;CACxC,4BAA4B,IAAI,KAAK,MAAM;;AAG5C,SAAgB,uBACf,SACA,kBACA,eAIC;CAUD,OAAO;EACN,kBATA,oBAAoB,QAAQ,mBAAmB,SAAS,SACrD,mBACA,KAAA;EAQH,eAAe,IAPQ,IACvB,CAAC,GAAG,cAAc,CAAC,QACjB,SAAS,QAAQ,OAAO,SAAS,QAClC,CAIyB;EAC1B;;AAGF,SAAgB,kBAAkB,MAAwB;CACzD,OAAO,KACL,MAAM,IAAI,CACV,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ;;;;ACZlB,eAA8B,eAAe,IAAkB;CAC9D,IAAI,UAA8C,EAAE;CACpD,IAAI;CACJ,IAAI,gCAAgB,IAAI,KAAa;CAErC,SAAS,SACR,MACiC;EACjC,OAAO,OAAO,QAAQ,QAAQ,KAAA;;CAG/B,SAAS,UAAU,MAA8C;EAChE,MAAM,SAAS,QAAQ;EACvB,OAAO,QAAQ,SAAS,UAAU,SAAS,KAAA;;CAG5C,SAAS,aACR,KACA,gBACA,aACA,SACO;EACP,mBAAmB;EACnB,gBAAgB,IAAI,IAAI,YAAY;EACpC,WAAW,KAAK,kBAAkB,cAAc;EAChD,IAAI,SAAS,YAAY,OACxB,cAAc,IAAI,KAAK,kBAAkB,cAAc;EAExD,IAAI,SAAS,QACZ,IAAI,GAAG,OAAO,QAAQ,QAAQ,OAAO;;CAIvC,SAAS,cACR,MACA,KACA,SACU;EACV,IAAI,CAAC,MAAM;GACV,aAAa,KAAK,KAAA,GAAW,eAAe;IAC3C,SAAS,SAAS;IAClB,QAAQ;IACR,CAAC;GACF,OAAO;;EAGR,MAAM,SAAS,SAAS,KAAK;EAC7B,IAAI,CAAC,QAAQ;GACZ,IAAI,GAAG,OAAO,wBAAwB,QAAQ,UAAU;GACxD,OAAO;;EAGR,aAAa,KAAK,OAAO,MAAM,eAAe;GAC7C,SAAS,SAAS;GAClB,QAAQ,gBAAgB,OAAO,KAAK;GACpC,CAAC;EACF,OAAO;;CAGR,SAAS,kBACR,MACA,SACA,KACA,SACU;EACV,MAAM,SAAS,UAAU,KAAK;EAC9B,IAAI,CAAC,QAAQ;GACZ,IAAI,GAAG,OAAO,yBAAyB,QAAQ,UAAU;GACzD,OAAO;;EAGR,MAAM,cAAc,IAAI,IAAI,cAAc;EAC1C,IAAI,SACH,YAAY,IAAI,OAAO,KAAK;OAE5B,YAAY,OAAO,OAAO,KAAK;EAGhC,aAAa,KAAK,kBAAkB,aAAa;GAChD,SAAS,SAAS;GAClB,QAAQ,UACL,UAAU,OAAO,KAAK,aACtB,UAAU,OAAO,KAAK;GACzB,CAAC;EACF,OAAO;;CAGR,SAAS,aACR,MACA,KACA,SACU;EACV,OAAO,kBACN,MACA,CAAC,cAAc,IAAI,KAAK,EACxB,KACA,QACA;;CAGF,eAAe,YACd,MACA,KACA,QAA8B,WACd;EAChB,MAAM,WAAW,QAAQ;EACzB,MAAM,cAAc,MAAM,IAAI,GAAG,OAAO,eAAe,CACtD,UAAU,SAAS,UAChB,oBACA,kBACH,UAAU,SAAS,UAAU,SAAS,QACtC,CAAC;EACF,IAAI,CAAC,aAAa;EAClB,MAAM,OAAyB,YAAY,WAAW,QAAQ,GAC3D,UACA;EAEH,MAAM,cAAc,MAAM,IAAI,GAAG,MAChC,mBAAmB,QACnB,UAAU,eAAe,GACzB;EACD,IAAI,gBAAgB,KAAA,GAAW;EAE/B,MAAM,eAAe,MAAM,IAAI,GAAG,OACjC,QAAQ,KAAK,WAAW,QACxB,UAAU,gBAAgB,GAC1B;EACD,IAAI,iBAAiB,KAAA,GAAW;EAEhC,MAAM,aACL,UAAU,WACP,+BAA+B,MAAM;GACrC;GACA;GACA,GAAI,YAAY,MAAM,GACnB,EAAE,aAAa,YAAY,MAAM,EAAE,GACnC,EAAE;GACL,CAAC,GACD,gCAAgC,IAAI,KAAK,MAAM;GAC/C;GACA;GACA,GAAI,YAAY,MAAM,GACnB,EAAE,aAAa,YAAY,MAAM,EAAE,GACnC,EAAE;GACL,CAAC;EAEL,UAAU,oBAAoB,IAAI,IAAI;EACtC,MAAM,aAAa,uBAClB,SACA,kBACA,cACA;EACD,mBAAmB,WAAW;EAC9B,gBAAgB,WAAW;EAE3B,IAAI,SAAS,QACZ,cAAc,MAAM,IAAI;OAExB,kBAAkB,MAAM,MAAM,IAAI;EAEnC,IAAI,GAAG,OAAO,iBAAiB,KAAK,OAAO,cAAc,OAAO;;CAGjE,SAAS,uBACR,KACA,OACO;EACP,MAAM,MACL,UAAU,WACP,wBAAwB,GACxB,wBAAwB,IAAI,IAAI;EACpC,IAAI,UAAU;EACd,IAAI,UAAU;EACd,KAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QACnC,uBACA,EAAE;GAEF,IAAI,WADS,4BAA4B,KAAK,KAC3B,CAAC,EAAE;IACrB,WAAW;IACX;;GAED,wBAAwB,KAAK,MAAM,OAAO;GAC1C,WAAW;;EAGZ,UAAU,oBAAoB,IAAI,IAAI;EACtC,MAAM,aAAa,uBAClB,SACA,kBACA,cACA;EACD,mBAAmB,WAAW;EAC9B,gBAAgB,WAAW;EAC3B,WAAW,KAAK,kBAAkB,cAAc;EAEhD,IAAI,GAAG,OACN,YAAY,QAAQ,8BAA8B,MAAM,UAAU,KAAK,QAAQ,qBAAqB,MACpG,OACA;;CAGF,SAAS,qBACR,MACA,KACA,MACO;EACP,MAAM,SAAS,6BAA6B,IAAI,KAAK,KAAK;EAC1D,IAAI,CAAC,OAAO,SAAS;GACpB,IAAI,GAAG,OACN,kCAAkC,KAAK,OAAO,QAC9C,UACA;GACD;;EAGD,UAAU,oBAAoB,IAAI,IAAI;EACtC,MAAM,aAAa,uBAClB,SACA,kBACA,cACA;EACD,mBAAmB,WAAW;EAC9B,gBAAgB,WAAW;EAC3B,WAAW,KAAK,kBAAkB,cAAc;EAChD,cAAc,IAAI,KAAK,kBAAkB,cAAc;EAEvD,MAAM,WAAW,QAAQ;EACzB,IAAI,SAAS,WAAW,UAAU;GACjC,IAAI,GAAG,OACN,UAAU,KAAK,OAAO,wBAAwB,SAAS,OAAO,CAAC,UAC/D,OACA;GACD;;EAGD,IAAI,GAAG,OACN,OAAO,cAAc,IAClB,YAAY,KAAK,gBAAgB,OAAO,SACxC,YAAY,KAAK,SAAS,OAAO,QACpC,OACA;;CAGF,eAAe,aACd,KACgB;EAChB,MAAM,eAAe,kBAAkB,QAAQ;EAC/C,MAAM,gBAAgB,mBAAmB,QAAQ;EACjD,IAAI,aAAa,WAAW,KAAK,cAAc,WAAW,GAAG;GAC5D,IAAI,GAAG,OAAO,+BAA+B,UAAU;GACvD;;EAGD,MAAM,eAAe;EACrB,MAAM,iBAAiB,IAAI,IAAI,cAAc;EAC7C,IAAI,gBAAgB;EACpB,MAAM,iBAAiB,IAAI,IAAI,cAAc;EAE7C,MAAM,QAAuB,EAAE;EAC/B,MAAM,2BAAW,IAAI,KAAa;EAClC,MAAM,4BAAY,IAAI,KAAa;EAEnC,MAAM,KAAK;GACV,IAAI;GACJ,OAAO,oBAAoB,aAAa,SAAS,EAAE;GACnD,aAAa;GACb,cAAc;GACd,CAAC;EACF,MAAM,KAAK;GACV,IAAI;GACJ,OAAO;GACP,aAAa;GACb,cAAA;GACA,QAAQ,CAAC,UAAA,IAAqB;GAC9B,CAAC;EACF,SAAS,IAAI,aAAa;EAE1B,KAAK,MAAM,UAAU,cAAc;GAClC,MAAM,KAAK;IACV,IAAI,OAAO;IACX,OAAO,OAAO;IACd,aAAa,CACZ,GAAG,wBAAwB,OAAO,OAAO,CAAC,KAAK,OAAO,eAAe,gBACrE,CAAC,KAAK,KAAK;IACZ,cAAA;IACA,QAAQ,CAAC,UAAA,IAAqB;IAC9B,CAAC;GACF,SAAS,IAAI,OAAO,KAAK;;EAG1B,MAAM,KAAK;GACV,IAAI;GACJ,OAAO,qBAAqB,cAAc,OAAO;GACjD,aAAa;GACb,cAAc;GACd,CAAC;EACF,KAAK,MAAM,UAAU,eAAe;GACnC,MAAM,KAAK;IACV,IAAI,OAAO;IACX,OAAO,OAAO;IACd,aAAa,CACZ,GAAG,wBAAwB,OAAO,OAAO,CAAC,KAAK,OAAO,eAAe,UACrE,CAAC,KAAK,KAAK;IACZ,cAAc;IACd,QAAQ,CAAC,SAAS,SAAS;IAC3B,CAAC;GACF,UAAU,IAAI,OAAO,KAAK;;EAG3B,SAAS,cAAc;GACtB,KAAK,MAAM,QAAQ,OAClB,IAAI,SAAS,IAAI,KAAK,GAAG,EAIxB,KAAK,eAFH,KAAK,OAAA,mBAAuB,CAAC,iBAC9B,KAAK,OAAO,gBACqB,WAAA;QAC5B,IAAI,UAAU,IAAI,KAAK,GAAG,EAChC,KAAK,eAAe,eAAe,IAAI,KAAK,GAAG,GAC5C,UACA;;EAKN,aAAa;EAEb,MAAM,oBAAoB,KAAK;GAC9B,OAAO;GACP,gBACC,SAAS,iBAAiB,SAAS,KAAK,eAAe,KAAK;GAC7D;GACA,aAAa,KAAK,IAAI,KAAK,IAAI,MAAM,SAAS,GAAG,EAAE,EAAE,GAAG;GACxD,eAAe;GACf,YAAY,IAAI,cAAc;IAC7B,IAAI,GAAG,WAAW,YAAY,EAAE;IAEhC,IAAI,SAAS,IAAI,GAAG,EAAE;KACrB,gBACC,cAAA,gBAA0B,OAAA,kBACvB,KACA,KAAA;KACJ,aAAa;KACb;;IAGD,IAAI,UAAU,IAAI,GAAG,EAAE;KACtB,IAAI,cAAA,aACH,eAAe,IAAI,GAAG;UAEtB,eAAe,OAAO,GAAG;KAE1B,aAAa;;;GAGf,CAAC;EAEF,IACC,kBAAkB,gBAClB,CAAC,WAAW,gBAAgB,eAAe,EAE3C,aAAa,KAAK,eAAe,gBAAgB,EAChD,QAAQ,mCACR,CAAC;;CAIJ,GAAG,aAAa,UAAU;EACzB,aACC;EACD,MAAM;EACN,CAAC;CAEF,MAAM,wBAEC;EACN,aACC;EACD,yBAAyB,WAAW;GACnC,MAAM,UAAU,OAAO,MAAM;GAC7B,MAAM,QAAQ,UAAU,QAAQ,MAAM,MAAM,GAAG,EAAE;GACjD,MAAM,aAAa,kBAAkB,QAAQ,CAAC,KAC5C,WAAW,OAAO,KACnB;GACD,MAAM,cAAc,mBAAmB,QAAQ,CAAC,KAC9C,WAAW,OAAO,KACnB;GACD,MAAM,YAAY,CAAC,GAAG,YAAY,GAAG,YAAY;GAEjD,IAAI,MAAM,UAAU,GAAG;IACtB,MAAM,QAAQ,MAAM,MAAM;IAiB1B,OAAO,CACN,GAAG;KAhBH;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KAGc,CACZ,QAAQ,SAAS,KAAK,WAAW,MAAM,CAAC,CACxC,KAAK,UAAU;KAAE,OAAO;KAAM,OAAO;KAAM,EAAE,EAC/C,GAAG,UACD,QAAQ,SAAS,KAAK,WAAW,MAAM,CAAC,CACxC,KAAK,UAAU;KAAE,OAAO;KAAM,OAAO;KAAM,EAAE,CAC/C;;GAGF,MAAM,UAAU,MAAM;GACtB,MAAM,QAAQ,MAAM,MAAM,EAAE,CAAC,KAAK,IAAI;GACtC,IAAI,YAAY,QACf,OAAO,WACL,QAAQ,SAAS,KAAK,WAAW,MAAM,CAAC,CACxC,KAAK,UAAU;IAAE,OAAO,QAAQ;IAAQ,OAAO;IAAM,EAAE;GAE1D,IAAI;IAAC;IAAU;IAAW;IAAS,CAAC,SAAS,QAAQ,EACpD,OAAO,YACL,QAAQ,SAAS,KAAK,WAAW,MAAM,CAAC,CACxC,KAAK,UAAU;IACf,OAAO,GAAG,QAAQ,GAAG;IACrB,OAAO;IACP,EAAE;GAEL,IAAI,YAAY,UAAU,YAAY,eACrC,OAAO,UACL,QAAQ,SAAS,KAAK,WAAW,MAAM,CAAC,CACxC,KAAK,UAAU;IACf,OAAO,GAAG,QAAQ,GAAG;IACrB,OAAO;IACP,EAAE;GAEL,IAAI,CAAC,UAAU,QAAQ,CAAC,SAAS,QAAQ,EACxC,OAAO,UACL,QAAQ,SAAS,KAAK,WAAW,MAAM,CAAC,CACxC,KAAK,UAAU;IACf,OAAO,GAAG,QAAQ,GAAG;IACrB,OAAO;IACP,EAAE;GAEL,OAAO;;EAER,SAAS,OAAO,MAAM,QAAQ;GAC7B,MAAM,UAAU,KAAK,MAAM;GAC3B,IAAI,CAAC,SAAS;IACb,IAAI,IAAI,OAAO;KACd,MAAM,aAAa,IAAI;KACvB;;IAED,IAAI,GAAG,OACN,eAAe,kBAAkB,eAAe,QAAQ,EACxD,OACA;IACD;;GAGD,MAAM,CAAC,OAAO,GAAG,QAAQ,QAAQ,MAAM,MAAM;GAC7C,MAAM,MAAM,KAAK,KAAK,IAAI,CAAC,MAAM;GAEjC,QAAQ,OAAR;IACC,KAAK;KACJ,IAAI,GAAG,OAAO,2BAA2B,EAAE,OAAO;KAClD;IACD,KAAK;KACJ,IAAI,GAAG,OACN,eAAe,kBAAkB,eAAe,QAAQ,EACxD,OACA;KACD;IACD,KAAK;KACJ,IAAI,GAAG,OACN,sBACC,kBACA,eACA,QACA,EACD,OACA;KACD;IACD,KAAK;KACJ,aAAa,KAAK,KAAA,mBAAW,IAAI,KAAK,EAAE,EACvC,QAAQ,yCACR,CAAC;KACF;IACD,KAAK,UAAU;KACd,UAAU,oBAAoB,IAAI,IAAI;KACtC,MAAM,aAAa,uBAClB,SACA,kBACA,cACA;KACD,mBAAmB,WAAW;KAC9B,gBAAgB,WAAW;KAC3B,WAAW,KAAK,kBAAkB,cAAc;KAChD,IAAI,GAAG,OAAO,2BAA2B,OAAO;KAChD;;IAED,KAAK;KACJ,IAAI,CAAC,KAAK;MACT,IAAI,GAAG,OACN,sDACA,UACA;MACD;;KAED,cAAc,KAAK,IAAI;KACvB;IACD,KAAK;KACJ,IAAI,CAAC,KAAK;MACT,IAAI,GAAG,OACN,yDACA,UACA;MACD;;KAED,kBAAkB,KAAK,MAAM,IAAI;KACjC;IACD,KAAK;KACJ,IAAI,CAAC,KAAK;MACT,IAAI,GAAG,OACN,0DACA,UACA;MACD;;KAED,kBAAkB,KAAK,OAAO,IAAI;KAClC;IACD,KAAK;KACJ,IAAI,CAAC,KAAK;MACT,IAAI,GAAG,OACN,yDACA,UACA;MACD;;KAED,aAAa,KAAK,IAAI;KACtB;IACD,KAAK,QAAQ;KACZ,IAAI,QAA8B;KAClC,IAAI,OAAO;KACX,IAAI,IAAI,WAAW,YAAY,EAAE;MAChC,QAAQ;MACR,OAAO,IAAI,MAAM,EAAmB,CAAC,MAAM;YACrC,IAAI,IAAI,WAAW,aAAa,EACtC,OAAO,IAAI,MAAM,GAAoB,CAAC,MAAM;KAE7C,IAAI,CAAC,MAAM;MACV,IAAI,GAAG,OACN,2EACA,UACA;MACD;;KAED,MAAM,YAAY,MAAM,KAAK,MAAM;KACnC;;IAED,KAAK;KACJ,IAAI,CAAC,KAAK;MACT,IAAI,GAAG,OACN,6DACA,UACA;MACD;;KAED,MAAM,YAAY,KAAK,KAAK,SAAS;KACrC;IACD,KAAK,mBAAmB;KACvB,MAAM,QAAQ,OAAO;KACrB,IAAI,UAAU,YAAY,UAAU,WAAW;MAC9C,IAAI,GAAG,OACN,2EACA,UACA;MACD;;KAED,uBAAuB,KAAK,MAAM;KAClC;;IAED,KAAK;KACJ,IAAI,CAAC,KAAK;MACT,IAAI,GAAG,OACN,wDACA,UACA;MACD;;KAED,qBAAqB,KAAK,KAAK,SAAS;KACxC;IACD,KAAK;KACJ,IAAI,CAAC,KAAK;MACT,IAAI,GAAG,OACN,uDACA,UACA;MACD;;KAED,qBAAqB,KAAK,KAAK,QAAQ;KACvC;;GAGF,IAAI,cAAc,MAAM,EAAE;IACzB,IAAI,GAAG,OACN,+BAA+B,SAC/B,UACA;IACD;;GAGD,MAAM,SAAS,QAAQ;GACvB,IAAI,CAAC,QAAQ;IACZ,IAAI,GAAG,OACN,4BAA4B,QAAQ,6BACpC,UACA;IACD;;GAED,IAAI,OAAO,SAAS,QACnB,cAAc,OAAO,MAAM,IAAI;QAE/B,aAAa,OAAO,MAAM,IAAI;;EAGhC;CAED,KAAK,MAAM,gBAAgB,CAAC,iBAAiB,SAAS,EACrD,GAAG,gBAAgB,cAAc,sBAAsB;CAGxD,GAAG,GAAG,iBAAiB,OAAO,QAAQ,QAAQ;EAC7C,UAAU,oBAAoB,IAAI,IAAI;EACtC,mBAAmB,KAAA;EACnB,gCAAgB,IAAI,KAAK;EAEzB,MAAM,cAAc,GAAG,QAAQ,SAAS;EACxC,IAAI,OAAO,gBAAgB,YAAY,YAAY,MAAM,EAAE;GAC1D,KAAK,MAAM,QAAQ,kBAAkB,YAAY,EAAE;IAClD,MAAM,SAAS,QAAQ;IACvB,IAAI,CAAC,QAAQ;IACb,IAAI,OAAO,SAAS,QACnB,mBAAmB;SAEnB,cAAc,IAAI,KAAK;;GAGzB,MAAM,aAAa,uBAClB,SACA,kBACA,cACA;GACD,mBAAmB,WAAW;GAC9B,gBAAgB,WAAW;GAC3B,WAAW,KAAK,kBAAkB,cAAc;GAChD;;EAGD,MAAM,WAAW,sBAAsB,IAAI,IAC1C,4BAA4B,IAAI,IAAI,IAAI;GACvC,WAAA;GACA,aAAa,EAAE;GACf;EACF,mBAAmB,SAAS,aAAa,KAAA;EACzC,gBAAgB,IAAI,IAAI,SAAS,eAAe,EAAE,CAAC;EACnD,MAAM,aAAa,uBAClB,SACA,kBACA,cACA;EACD,mBAAmB,WAAW;EAC9B,gBAAgB,WAAW;EAC3B,WAAW,KAAK,kBAAkB,cAAc;GAC/C;CAEF,GAAG,GAAG,sBAAsB,OAAO,UAAU;EAC5C,MAAM,SAAmB,EAAE;EAC3B,MAAM,OAAO,SAAS,iBAAiB;EACvC,IAAI,MAAM,aAAa,MAAM,EAC5B,OAAO,KACN,0BAA0B,KAAK,KAAK,IAAI,KAAK,aAAa,MAAM,GAChE;EAGF,MAAM,eAAe,CAAC,GAAG,cAAc,CACrC,MAAM,CACN,KAAK,SAAS,QAAQ,MAAM,CAC5B,QAAQ,WACR,QAAQ,QAAQ,aAAa,MAAM,CAAC,CACpC,CACA,KACC,WACA,OAAO,OAAO,KAAK,IAAI,OAAO,aAAa,MAAM,GAClD;EACF,IAAI,aAAa,SAAS,GACzB,OAAO,KACN,8BAA8B,aAAa,KAAK,OAAO,GACvD;EAGF,IAAI,OAAO,WAAW,GAAG;EACzB,OAAO,EACN,cAAc,GAAG,MAAM,aAAa,MAAM,OAAO,KAAK,OAAO,IAC7D;GACA;CAEF,GAAG,GAAG,oBAAoB,OAAO,QAAQ,QAAQ;EAChD,IAAI,GAAG,UAAU,UAAU,KAAA,EAAU;EACrC,IAAI,GAAG,UAAU,KAAA,EAAU;GAC1B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "my-pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.48",
|
|
4
4
|
"description": "Composable pi coding agent with MCP, LSP, prompt presets, and local eval telemetry",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -49,32 +49,33 @@
|
|
|
49
49
|
"citty": "^0.2.2",
|
|
50
50
|
"typebox": "^1.1.38",
|
|
51
51
|
"@spences10/pi-project-trust": "0.0.6",
|
|
52
|
-
"@spences10/pi-
|
|
53
|
-
"@spences10/pi-
|
|
52
|
+
"@spences10/pi-themes": "0.0.5",
|
|
53
|
+
"@spences10/pi-tui-modal": "0.0.14"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@changesets/cli": "^2.31.0",
|
|
57
57
|
"@types/node": "^25.8.0",
|
|
58
|
+
"@vitest/coverage-v8": "^4.1.6",
|
|
58
59
|
"vite-plus": "^0.1.21",
|
|
59
60
|
"vitest": "^4.1.6"
|
|
60
61
|
},
|
|
61
62
|
"optionalDependencies": {
|
|
62
63
|
"@spences10/pi-child-env": "0.1.4",
|
|
63
64
|
"@spences10/pi-coding-preferences": "0.0.5",
|
|
64
|
-
"@spences10/pi-
|
|
65
|
-
"@spences10/pi-
|
|
66
|
-
"@spences10/pi-
|
|
67
|
-
"@spences10/pi-
|
|
68
|
-
"@spences10/pi-
|
|
65
|
+
"@spences10/pi-confirm-destructive": "0.0.11",
|
|
66
|
+
"@spences10/pi-context": "0.0.16",
|
|
67
|
+
"@spences10/pi-git-ui": "0.0.5",
|
|
68
|
+
"@spences10/pi-lsp": "0.0.23",
|
|
69
|
+
"@spences10/pi-mcp": "0.0.26",
|
|
70
|
+
"@spences10/pi-nopeek": "0.0.9",
|
|
69
71
|
"@spences10/pi-omnisearch": "0.0.9",
|
|
70
|
-
"@spences10/pi-
|
|
72
|
+
"@spences10/pi-recall": "0.0.9",
|
|
73
|
+
"@spences10/pi-skills": "0.0.20",
|
|
71
74
|
"@spences10/pi-redact": "0.0.8",
|
|
72
|
-
"@spences10/pi-recall": "0.0.8",
|
|
73
|
-
"@spences10/pi-skills": "0.0.19",
|
|
74
|
-
"@spences10/pi-svelte-guardrails": "0.0.5",
|
|
75
75
|
"@spences10/pi-sqlite-tools": "0.0.8",
|
|
76
|
-
"@spences10/pi-
|
|
77
|
-
"@spences10/pi-team-mode": "0.0.
|
|
76
|
+
"@spences10/pi-svelte-guardrails": "0.0.6",
|
|
77
|
+
"@spences10/pi-team-mode": "0.0.22",
|
|
78
|
+
"@spences10/pi-telemetry": "0.0.15"
|
|
78
79
|
},
|
|
79
80
|
"engines": {
|
|
80
81
|
"node": ">=24.15.0"
|
|
@@ -92,6 +93,7 @@
|
|
|
92
93
|
"eval:suite": "node scripts/run-eval-suite.ts",
|
|
93
94
|
"changeset": "changeset",
|
|
94
95
|
"version": "changeset version",
|
|
95
|
-
"release": "git diff --quiet && git diff --cached --quiet && pnpm run build && changeset publish"
|
|
96
|
+
"release": "git diff --quiet && git diff --cached --quiet && pnpm run build && changeset publish",
|
|
97
|
+
"coverage": "pnpm --filter \"./packages/*\" run build:self && vp pack && sh -c 'vp test --coverage && pnpm --filter \"./packages/*\" --if-present run coverage:self' --"
|
|
96
98
|
}
|
|
97
99
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hooks-resolution-D89Ewkyw.js","names":["create_child_process_env","create_shared_child_process_env","HOOKS_CONFIG_ENV","create_child_process_env"],"sources":["../src/extensions/hooks-resolution/env.ts","../src/extensions/hooks-resolution/trust.ts","../src/extensions/hooks-resolution/index.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 { getAgentDir } from '@earendil-works/pi-coding-agent';\nimport {\n\tis_project_subject_trusted,\n\tread_project_trust_store,\n\ttrust_project_subject,\n\ttype ProjectTrustSubject,\n} from '@spences10/pi-project-trust';\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(getAgentDir(), '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\tToolCallEvent,\n\tToolCallEventResult,\n\tToolResultEvent,\n} from '@earendil-works/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 =\n\t| 'PreToolUse'\n\t| 'PostToolUse'\n\t| '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 === 'PreToolUse'\n\t\t\t? ['PreToolUse', 'preToolUse']\n\t\t\t: event_name === 'PostToolUse'\n\t\t\t\t? ['PostToolUse', 'postToolUse']\n\t\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'PreToolUse',\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'PreToolUse',\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: ToolCallEvent | 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\tconst payload: Record<string, unknown> = {\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};\n\n\tif ('content' in event) {\n\t\tpayload.tool_response = build_tool_response(\n\t\t\tevent,\n\t\t\tnormalized_input,\n\t\t);\n\t}\n\n\treturn payload;\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 hook_block_reason(\n\tresult: CommandRunResult,\n): string | undefined {\n\tconst parse_json = (\n\t\ttext: string,\n\t): Record<string, unknown> | undefined => {\n\t\tconst trimmed = text.trim();\n\t\tif (!trimmed) return undefined;\n\t\ttry {\n\t\t\treturn as_record(JSON.parse(trimmed));\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t};\n\n\tconst json = parse_json(result.stdout) ?? parse_json(result.stderr);\n\tif (json?.decision === 'block') {\n\t\treturn typeof json.reason === 'string'\n\t\t\t? json.reason\n\t\t\t: 'Blocked by hook';\n\t}\n\tif (result.code === 2) {\n\t\treturn (\n\t\t\tresult.stderr.trim() ||\n\t\t\tresult.stdout.trim() ||\n\t\t\t'Blocked by hook'\n\t\t);\n\t}\n\treturn undefined;\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(\n\t\t\t'tool_call',\n\t\t\tasync (\n\t\t\t\tevent,\n\t\t\t\tctx,\n\t\t\t): Promise<ToolCallEventResult | undefined> => {\n\t\t\t\tif (state.hooks.length === 0) return;\n\n\t\t\t\tconst matching_hooks = state.hooks.filter(\n\t\t\t\t\t(hook) =>\n\t\t\t\t\t\thook.event_name === 'PreToolUse' &&\n\t\t\t\t\t\tmatches_hook(hook, event.toolName),\n\t\t\t\t);\n\t\t\t\tif (matching_hooks.length === 0) return;\n\n\t\t\t\tconst payload = build_hook_payload(\n\t\t\t\t\tevent,\n\t\t\t\t\t'PreToolUse',\n\t\t\t\t\tctx,\n\t\t\t\t\tstate.project_dir,\n\t\t\t\t);\n\t\t\t\tconst executed_commands = new Set<string>();\n\n\t\t\t\tfor (const hook of matching_hooks) {\n\t\t\t\t\tif (executed_commands.has(hook.command)) continue;\n\t\t\t\t\texecuted_commands.add(hook.command);\n\n\t\t\t\t\tconst result = await run_command_hook_impl(\n\t\t\t\t\t\thook.command,\n\t\t\t\t\t\tstate.project_dir,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t);\n\t\t\t\t\tconst reason = hook_block_reason(result);\n\t\t\t\t\tif (reason) return { block: true, reason };\n\t\t\t\t}\n\t\t\t},\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"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-presets-Cl3vBbc-.js","names":[],"sources":["../src/extensions/prompt-presets/catalog.ts","../src/extensions/prompt-presets/defaults.ts","../src/extensions/prompt-presets/footer.ts","../src/extensions/prompt-presets/storage.ts","../src/extensions/prompt-presets/index.ts"],"sourcesContent":["import type {\n\tLoadedPromptPreset,\n\tPromptPresetSource,\n} from './types.js';\n\nexport function get_prompt_source_label(\n\tsource: PromptPresetSource,\n): 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\nexport function 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\nexport function 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\nexport function 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\nexport function 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","import type { PromptPresetMap } from './types.js';\n\nexport const DEFAULT_BASE_PROMPT_PRESET_NAME = 'terse';\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","import {\n\tclampThinkingLevel,\n\tgetSupportedThinkingLevels,\n\ttype ModelThinkingLevel,\n} from '@earendil-works/pi-ai';\nimport type {\n\tExtensionContext,\n\tReadonlyFooterDataProvider,\n} from '@earendil-works/pi-coding-agent';\nimport {\n\ttruncateToWidth,\n\tvisibleWidth,\n} from '@earendil-works/pi-tui';\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\nconst VALID_THINKING_LEVELS = new Set<ModelThinkingLevel>([\n\t'off',\n\t'minimal',\n\t'low',\n\t'medium',\n\t'high',\n\t'xhigh',\n]);\n\nfunction is_model_thinking_level(\n\tlevel: string,\n): level is ModelThinkingLevel {\n\treturn VALID_THINKING_LEVELS.has(level as ModelThinkingLevel);\n}\n\nexport function get_default_footer_thinking_level(\n\tmodel: ExtensionContext['model'],\n): ModelThinkingLevel {\n\tif (!model?.reasoning) return 'off';\n\treturn clampThinkingLevel(model, 'medium');\n}\n\nexport function get_current_thinking_level(\n\tctx: Pick<ExtensionContext, 'model' | 'sessionManager'>,\n): ModelThinkingLevel {\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\tis_model_thinking_level(entry.thinkingLevel)\n\t\t) {\n\t\t\tif (!ctx.model?.reasoning) return 'off';\n\t\t\treturn getSupportedThinkingLevels(ctx.model).includes(\n\t\t\t\tentry.thinkingLevel,\n\t\t\t)\n\t\t\t\t? entry.thinkingLevel\n\t\t\t\t: clampThinkingLevel(ctx.model, entry.thinkingLevel);\n\t\t}\n\t}\n\treturn get_default_footer_thinking_level(ctx.model);\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\nexport function 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","import { getAgentDir } from '@earendil-works/pi-coding-agent';\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';\nimport { DEFAULT_PROMPT_PRESETS } from './defaults.js';\nimport type {\n\tLoadedPromptPreset,\n\tPromptPreset,\n\tPromptPresetMap,\n\tPromptPresetSource,\n\tPromptPresetState,\n} from './types.js';\n\nconst PROJECT_PROMPT_PRESETS_ENV = 'MY_PI_PROMPT_PRESETS_PROJECT';\n\ninterface PersistedPromptPresetStates {\n\tversion: number;\n\tprojects: Record<string, PromptPresetState>;\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\nexport function get_global_presets_dir(): string {\n\treturn join(getAgentDir(), 'presets');\n}\n\nexport function 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\nexport function 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\nexport function 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\nexport function 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","import {\n\ttype ExtensionAPI,\n\ttype ExtensionCommandContext,\n\ttype ExtensionContext,\n} from '@earendil-works/pi-coding-agent';\nimport type { SettingItem } from '@earendil-works/pi-tui';\nimport { show_settings_modal } from '@spences10/pi-tui-modal';\nimport { existsSync } from 'node:fs';\nimport {\n\tformat_active_details,\n\tformat_summary,\n\tget_prompt_source_label,\n\tlist_base_presets,\n\tlist_layer_presets,\n} from './catalog.js';\nimport {\n\tDEFAULT_BASE_PROMPT_PRESET_NAME,\n\tDEFAULT_PROMPT_PRESETS,\n} from './defaults.js';\nimport { set_status } from './footer.js';\nimport {\n\tget_global_presets_dir,\n\tget_project_presets_dir,\n\tget_prompt_preset_file_path,\n\tload_persisted_prompt_state,\n\tload_prompt_presets,\n\tremove_project_prompt_preset,\n\tsave_global_prompt_preset_file,\n\tsave_persisted_prompt_state,\n\tsave_project_prompt_preset_file,\n\tsave_prompt_preset_file,\n} from './storage.js';\nimport type {\n\tLoadedPromptPreset,\n\tPromptPresetKind,\n\tPromptPresetState,\n} from './types.js';\n\nexport {\n\tDEFAULT_BASE_PROMPT_PRESET_NAME,\n\tDEFAULT_PROMPT_PRESETS,\n} from './defaults.js';\nexport {\n\tget_current_thinking_level,\n\tget_default_footer_thinking_level,\n\trender_footer_status_line,\n} from './footer.js';\nexport {\n\tload_persisted_prompt_state,\n\tload_prompt_presets,\n\tmerge_prompt_presets,\n\tnormalize_prompt_presets,\n\tread_prompt_presets_dir,\n\tremove_project_prompt_preset,\n\tsave_persisted_prompt_state,\n\tsave_project_prompt_presets,\n\tsave_prompt_preset_file,\n} from './storage.js';\nexport type {\n\tLoadedPromptPreset,\n\tPromptPreset,\n\tPromptPresetKind,\n\tPromptPresetMap,\n\tPromptPresetSource,\n\tPromptPresetState,\n} from './types.js';\n\nconst PRESET_STATE_TYPE = 'prompt-preset-state';\nconst ENABLED = '● enabled';\nconst DISABLED = '○ disabled';\nconst SELECTED = '● selected';\nconst UNSELECTED = '○';\nconst NONE_BASE_ID = '__base_none__';\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 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 ['prompt-preset', 'preset']) {\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"],"mappings":"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"}
|