my-pi 0.3.5 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -252
- package/dist/extensions.d.ts +11 -0
- package/dist/extensions.js +148 -0
- package/dist/extensions.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +40 -523
- package/dist/index.js.map +1 -1
- package/dist/manager.d.ts +3 -0
- package/dist/manager.js +71 -0
- package/dist/manager.js.map +1 -0
- package/dist/settings.d.ts +3 -0
- package/dist/settings.js +16 -0
- package/dist/settings.js.map +1 -0
- package/package.json +33 -78
- package/dist/api.d.ts +0 -494
- package/dist/api.js +0 -532
- package/dist/api.js.map +0 -1
- package/dist/builtin-registry-wSfsQBi4.js +0 -563
- package/dist/builtin-registry-wSfsQBi4.js.map +0 -1
- package/dist/footer-BAZIMVSb.js +0 -1
- package/dist/handoff-C6wR2mSG.js +0 -28
- package/dist/handoff-C6wR2mSG.js.map +0 -1
- package/dist/hooks-resolution-qlhPfMFJ.js +0 -485
- package/dist/hooks-resolution-qlhPfMFJ.js.map +0 -1
- package/dist/openrouter-fusion-config-BWsHBPQv.js +0 -65
- package/dist/openrouter-fusion-config-BWsHBPQv.js.map +0 -1
- package/dist/prompt-presets-XraV03Ed.js +0 -1402
- package/dist/prompt-presets-XraV03Ed.js.map +0 -1
- package/dist/session-name-CD6TVRnh.js +0 -158
- package/dist/session-name-CD6TVRnh.js.map +0 -1
- package/dist/settings-BCn3P9qH.js +0 -177
- package/dist/settings-BCn3P9qH.js.map +0 -1
- package/dist/startup-screen-DUeBWuAc.js +0 -218
- package/dist/startup-screen-DUeBWuAc.js.map +0 -1
- package/dist/turn-timer-CoyDI4gQ.js +0 -64
- package/dist/turn-timer-CoyDI4gQ.js.map +0 -1
- package/dist/umans-provider-C2UJ4qkO.js +0 -307
- package/dist/umans-provider-C2UJ4qkO.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-presets-XraV03Ed.js","names":["no_purple_prose","asd_ste100","clarify_first","include_risks"],"sources":["../src/extensions/prompt-presets/catalog.ts","../src/extensions/prompt-presets/completions.ts","../src/extensions/prompt-presets/defaults/asd-ste100.md","../src/extensions/prompt-presets/defaults/bullets.md","../src/extensions/prompt-presets/defaults/clarify-first.md","../src/extensions/prompt-presets/defaults/detailed.md","../src/extensions/prompt-presets/defaults/include-risks.md","../src/extensions/prompt-presets/defaults/karpathy.md","../src/extensions/prompt-presets/defaults/no-purple-prose.md","../src/extensions/prompt-presets/defaults/spence.md","../src/extensions/prompt-presets/defaults/standard.md","../src/extensions/prompt-presets/defaults/terse.md","../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/library.ts","../src/extensions/prompt-presets/prompt-blocks.ts","../src/extensions/prompt-presets/state.ts","../src/extensions/prompt-presets/manager.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 { list_base_presets, list_layer_presets } from './catalog.js';\nimport type { LoadedPromptPreset } from './types.js';\n\nconst SUBCOMMANDS = [\n\t'help',\n\t'list',\n\t'show',\n\t'clear',\n\t'edit',\n\t'edit-global',\n\t'export-defaults',\n\t'delete',\n\t'reset',\n\t'reload',\n\t'base',\n\t'enable',\n\t'disable',\n\t'toggle',\n];\n\nexport function get_prompt_preset_completions(\n\tpresets: Record<string, LoadedPromptPreset>,\n\tprefix: string,\n): Array<{ value: string; label: string }> | null {\n\tconst trimmed = prefix.trim();\n\tconst parts = trimmed ? trimmed.split(/\\s+/) : [];\n\tconst base_names = list_base_presets(presets).map(\n\t\t(preset) => preset.name,\n\t);\n\tconst layer_names = list_layer_presets(presets).map(\n\t\t(preset) => preset.name,\n\t);\n\tconst all_names = [...base_names, ...layer_names];\n\n\tif (parts.length <= 1) {\n\t\tconst query = parts[0] ?? '';\n\t\treturn [\n\t\t\t...SUBCOMMANDS.filter((item) => item.startsWith(query)).map(\n\t\t\t\t(item) => ({ value: item, label: item }),\n\t\t\t),\n\t\t\t...all_names\n\t\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t\t.map((item) => ({ value: item, label: item })),\n\t\t];\n\t}\n\n\tconst command = parts[0];\n\tconst query = parts.slice(1).join(' ');\n\tif (command === 'base') {\n\t\treturn base_names\n\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t.map((item) => ({ value: `base ${item}`, label: item }));\n\t}\n\tif (['enable', 'disable', 'toggle'].includes(command)) {\n\t\treturn layer_names\n\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t.map((item) => ({\n\t\t\t\tvalue: `${command} ${item}`,\n\t\t\t\tlabel: item,\n\t\t\t}));\n\t}\n\tif (command === 'edit' || command === 'edit-global') {\n\t\treturn all_names\n\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t.map((item) => ({\n\t\t\t\tvalue: `${command} ${item}`,\n\t\t\t\tlabel: item,\n\t\t\t}));\n\t}\n\tif (['delete', 'reset'].includes(command)) {\n\t\treturn all_names\n\t\t\t.filter((item) => item.startsWith(query))\n\t\t\t.map((item) => ({\n\t\t\t\tvalue: `${command} ${item}`,\n\t\t\t\tlabel: item,\n\t\t\t}));\n\t}\n\treturn null;\n}\n","\"---\\nkind: layer\\ndescription: Use ASD-STE100 Simplified Technical English\\n---\\n\\nUse ASD-STE100 Simplified Technical English in all replies. Use short,\\ndirect sentences. Use simple and consistent words. Avoid jargon,\\nidioms, vague language, and unnecessary explanation.\\n\"","\"---\\nkind: layer\\ndescription: Prefer short bullets when useful\\n---\\n\\nWhen presenting options, findings, or steps, prefer short bullet lists\\nover long paragraphs.\\n\"","\"---\\nkind: layer\\ndescription:\\n Ask brief clarifying questions when requirements are ambiguous\\n---\\n\\nIf the request is materially ambiguous, ask the minimum clarifying\\nquestion(s) needed before proceeding. Do not ask unnecessary\\nquestions.\\n\"","\"---\\nkind: base\\ndescription: More explanation when nuance matters\\n---\\n\\nBe thorough when the task is complex or tradeoffs matter, but stay\\npractical. Explain only the details that help the user decide, verify,\\nor implement. Avoid purple prose and unnecessary scene-setting.\\n\"","\"---\\nkind: layer\\ndescription: Call out notable risks or tradeoffs\\n---\\n\\nWhen making a recommendation or implementation plan, briefly mention\\nthe key risk, tradeoff, or caveat if one materially matters.\\n\"","\"---\\nkind: layer\\ndescription: Bias toward simple, surgical, verified code changes\\n---\\n\\nBefore coding, state assumptions when unclear and surface meaningful\\ntradeoffs. Prefer the minimum code that solves the request; avoid\\nspeculative abstractions, flexibility, and unrelated cleanup. Make\\nsurgical changes: touch only lines directly tied to the task, match\\nexisting style, and mention unrelated issues instead of fixing them.\\nFor multi-step work, use brief success criteria and verify with\\nfocused checks before reporting.\\n\"","\"---\\nkind: layer\\ndescription: Strip out ornamental language\\n---\\n\\nDo not use purple prose, flourish, motivational filler, or theatrical\\ntransitions. Prefer plain language and concrete statements.\\n\"","\"---\\nkind: layer\\ndescription:\\n Discuss critically, then execute the agreed outcome autonomously\\n---\\n\\nMatch the user's working mode. When they are exploring, asking what\\nyou think, or requesting discussion or research, investigate and\\nrespond critically before making changes. Challenge weak assumptions,\\nconsider the wider outcome, and do not agree merely to be agreeable.\\n\\nOnce the user authorises implementation, treat the agreed requirements\\nand decisions as the work contract. Complete that outcome and validate\\nit without stopping at a plan, an arbitrary partial slice, or repeated\\npermission checks. Keep the implementation focused, but never shrink\\nthe requested outcome merely to keep the change small.\\n\\nRespect explicit review and approval boundaries.\\n\"","\"---\\nkind: base\\ndescription: Clear and concise with key context\\n---\\n\\nBe clear, direct, and concise. Include only the reasoning and\\nimplementation details that matter. Avoid filler, grandstanding, and\\nornamental language. Use bullets when they improve scanability.\\n\"","\"---\\nkind: base\\ndescription: Short, direct, no fluff\\n---\\n\\nBe concise and direct. Default to the shortest response that fully\\nsolves the user's request. Use at most one short paragraph or 3\\nbullets unless the user explicitly asks for detail. For implementation\\nreports, include only what changed, validation, and the next step if\\nrelevant. No purple prose, no filler, no repetitive caveats.\\n\"","import { parseFrontmatter } from '@earendil-works/pi-coding-agent';\nimport type { PromptPreset, PromptPresetMap } from './types.js';\n\nimport asd_ste100 from './defaults/asd-ste100.md';\nimport bullets from './defaults/bullets.md';\nimport clarify_first from './defaults/clarify-first.md';\nimport detailed from './defaults/detailed.md';\nimport include_risks from './defaults/include-risks.md';\nimport karpathy from './defaults/karpathy.md';\nimport no_purple_prose from './defaults/no-purple-prose.md';\nimport spence from './defaults/spence.md';\nimport standard from './defaults/standard.md';\nimport terse from './defaults/terse.md';\n\nexport const DEFAULT_BASE_PROMPT_PRESET_NAME = 'terse';\n\nconst DEFAULT_PROMPT_PRESET_FILES = {\n\tterse,\n\tstandard,\n\tdetailed,\n\t'no-purple-prose': no_purple_prose,\n\t'asd-ste100': asd_ste100,\n\tbullets,\n\t'clarify-first': clarify_first,\n\t'include-risks': include_risks,\n\tkarpathy,\n\tspence,\n} satisfies Record<string, string>;\n\nfunction parse_default_prompt_preset(content: string): PromptPreset {\n\tconst { frontmatter, body } = parseFrontmatter(content);\n\treturn {\n\t\tkind: frontmatter.kind === 'layer' ? 'layer' : 'base',\n\t\tinstructions: body.trim(),\n\t\t...(typeof frontmatter.description === 'string' &&\n\t\tfrontmatter.description.trim()\n\t\t\t? { description: frontmatter.description.trim() }\n\t\t\t: {}),\n\t};\n}\n\nexport const DEFAULT_PROMPT_PRESETS: PromptPresetMap =\n\tObject.fromEntries(\n\t\tObject.entries(DEFAULT_PROMPT_PRESET_FILES).map(\n\t\t\t([name, content]) => [\n\t\t\t\tname,\n\t\t\t\tparse_default_prompt_preset(content),\n\t\t\t],\n\t\t),\n\t);\n","import type { ExtensionContext } from '@earendil-works/pi-coding-agent';\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\nexport function set_status(\n\tctx: ExtensionContext,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): void {\n\tctx.ui.setStatus(\n\t\t'preset',\n\t\tget_footer_prompt_status(active_base_name, active_layers),\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 {\n\tgetAgentDir,\n\tparseFrontmatter,\n} from '@earendil-works/pi-coding-agent';\nimport {\n\tget_settings_path,\n\tread_settings,\n\twrite_settings,\n} from '@spences10/pi-settings';\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\tPromptPresetCatalog,\n\tPromptPresetDefinition,\n\tPromptPresetDiagnostic,\n\tPromptPresetMap,\n\tPromptPresetMigrationResult,\n\tPromptPresetOrigin,\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_prompt_preset_definitions(\n\tpresets: PromptPresetMap,\n\tsource: PromptPresetSource,\n\torigin: PromptPresetOrigin,\n\tpath: string | null,\n\teditable: boolean,\n): Record<string, PromptPresetDefinition> {\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\torigin,\n\t\t\t\tpath,\n\t\t\t\teditable,\n\t\t\t\t...preset,\n\t\t\t},\n\t\t]),\n\t);\n}\n\nfunction read_prompt_preset_markdown_definitions(\n\tdir: string,\n\tsource: PromptPresetSource,\n\torigin: 'global-markdown' | 'project-markdown',\n): {\n\tdefinitions: Record<string, PromptPresetDefinition>;\n\tdiagnostics: PromptPresetDiagnostic[];\n} {\n\tconst definitions: Record<string, PromptPresetDefinition> = {};\n\tconst diagnostics: PromptPresetDiagnostic[] = [];\n\tif (!existsSync(dir)) return { definitions, diagnostics };\n\tlet entries;\n\ttry {\n\t\tentries = readdirSync(dir, { withFileTypes: true });\n\t} catch (error) {\n\t\tdiagnostics.push({\n\t\t\tcode: 'invalid-source',\n\t\t\tmessage: `Could not read prompt preset directory: ${String(error)}`,\n\t\t\tpath: dir,\n\t\t\torigin,\n\t\t});\n\t\treturn { definitions, diagnostics };\n\t}\n\tfor (const entry of entries\n\t\t.filter((item) => item.isFile() && item.name.endsWith('.md'))\n\t\t.sort((a, b) => a.name.localeCompare(b.name))) {\n\t\tconst name = entry.name.slice(0, -3).trim();\n\t\tconst path = join(dir, entry.name);\n\t\tif (!name) continue;\n\t\ttry {\n\t\t\tconst { metadata, body } = parse_prompt_preset_markdown(\n\t\t\t\treadFileSync(path, 'utf-8'),\n\t\t\t);\n\t\t\tif (\n\t\t\t\tmetadata.kind !== undefined &&\n\t\t\t\tmetadata.kind !== 'base' &&\n\t\t\t\tmetadata.kind !== 'layer'\n\t\t\t) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`kind must be \"base\" or \"layer\", received ${JSON.stringify(metadata.kind)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!body) throw new Error('instructions body is empty');\n\t\t\tdefinitions[name] = {\n\t\t\t\tname,\n\t\t\t\tkind: metadata.kind === 'layer' ? 'layer' : 'base',\n\t\t\t\tinstructions: body,\n\t\t\t\tsource,\n\t\t\t\torigin,\n\t\t\t\tpath,\n\t\t\t\teditable: true,\n\t\t\t\t...(typeof metadata.description === 'string' &&\n\t\t\t\tmetadata.description.trim()\n\t\t\t\t\t? { description: metadata.description }\n\t\t\t\t\t: {}),\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'invalid-source',\n\t\t\t\tname,\n\t\t\t\tmessage: `Could not read prompt preset Markdown: ${String(error)}`,\n\t\t\t\tpath,\n\t\t\t\torigin,\n\t\t\t});\n\t\t}\n\t}\n\treturn { definitions, diagnostics };\n}\n\nexport function get_global_presets_path(): string {\n\treturn join(getAgentDir(), 'presets.json');\n}\n\nexport function 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\ttry {\n\t\tif (path === get_global_presets_path()) {\n\t\t\treturn normalize_prompt_presets(\n\t\t\t\tread_settings().promptPresets?.global ?? {},\n\t\t\t);\n\t\t}\n\t\tif (!existsSync(path)) return {};\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 read_global_prompt_presets_source(): {\n\tpresets: PromptPresetMap;\n\tdiagnostics: PromptPresetDiagnostic[];\n} {\n\tconst path = get_settings_path();\n\ttry {\n\t\treturn {\n\t\t\tpresets: normalize_prompt_presets(\n\t\t\t\tread_settings().promptPresets?.global ?? {},\n\t\t\t),\n\t\t\tdiagnostics: [],\n\t\t};\n\t} catch (error) {\n\t\treturn {\n\t\t\tpresets: {},\n\t\t\tdiagnostics: [\n\t\t\t\t{\n\t\t\t\t\tcode: 'invalid-source',\n\t\t\t\t\tmessage: `Could not read legacy global prompt presets: ${String(error)}`,\n\t\t\t\t\tpath,\n\t\t\t\t\torigin: 'legacy-global-settings',\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n}\n\nfunction read_prompt_presets_json_source(\n\tpath: string,\n\torigin: 'project-json',\n): {\n\tpresets: PromptPresetMap;\n\tdiagnostics: PromptPresetDiagnostic[];\n} {\n\tif (!existsSync(path)) return { presets: {}, diagnostics: [] };\n\ttry {\n\t\treturn {\n\t\t\tpresets: normalize_prompt_presets(\n\t\t\t\tJSON.parse(readFileSync(path, 'utf-8')),\n\t\t\t),\n\t\t\tdiagnostics: [],\n\t\t};\n\t} catch (error) {\n\t\treturn {\n\t\t\tpresets: {},\n\t\t\tdiagnostics: [\n\t\t\t\t{\n\t\t\t\t\tcode: 'invalid-source',\n\t\t\t\t\tmessage: `Could not read prompt preset JSON: ${String(error)}`,\n\t\t\t\t\tpath,\n\t\t\t\t\torigin,\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n}\n\nexport function parse_prompt_preset_markdown(content: string): {\n\tmetadata: Record<string, unknown>;\n\tbody: string;\n} {\n\tconst { frontmatter, body } = parseFrontmatter(content);\n\treturn { metadata: frontmatter, body: body.trim() };\n}\n\nexport function read_prompt_presets_dir(\n\tpath: string,\n): PromptPresetMap {\n\tconst { definitions } = read_prompt_preset_markdown_definitions(\n\t\tpath,\n\t\t'user',\n\t\t'global-markdown',\n\t);\n\treturn Object.fromEntries(\n\t\tObject.entries(definitions).map(([name, definition]) => [\n\t\t\tname,\n\t\t\t{\n\t\t\t\tkind: definition.kind,\n\t\t\t\tinstructions: definition.instructions,\n\t\t\t\t...(definition.description\n\t\t\t\t\t? { description: definition.description }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t]),\n\t);\n}\n\nexport function format_prompt_preset_markdown(\n\tpreset: PromptPreset,\n): 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_preset_catalog(\n\tcwd: string,\n): PromptPresetCatalog {\n\tconst legacy_global = read_global_prompt_presets_source();\n\tconst global_markdown = read_prompt_preset_markdown_definitions(\n\t\tget_global_presets_dir(),\n\t\t'user',\n\t\t'global-markdown',\n\t);\n\tconst project_json = read_prompt_presets_json_source(\n\t\tget_project_presets_path(cwd),\n\t\t'project-json',\n\t);\n\tconst project_markdown = read_prompt_preset_markdown_definitions(\n\t\tget_project_presets_dir(cwd),\n\t\t'project',\n\t\t'project-markdown',\n\t);\n\tconst source_diagnostics: PromptPresetDiagnostic[] = [\n\t\t...legacy_global.diagnostics,\n\t\t...global_markdown.diagnostics,\n\t];\n\tconst sources: Array<Record<string, PromptPresetDefinition>> = [\n\t\tto_prompt_preset_definitions(\n\t\t\tDEFAULT_PROMPT_PRESETS,\n\t\t\t'builtin',\n\t\t\t'builtin',\n\t\t\tnull,\n\t\t\tfalse,\n\t\t),\n\t\tto_prompt_preset_definitions(\n\t\t\tlegacy_global.presets,\n\t\t\t'user',\n\t\t\t'legacy-global-settings',\n\t\t\tget_settings_path(),\n\t\t\tfalse,\n\t\t),\n\t\tglobal_markdown.definitions,\n\t];\n\tif (should_load_project_prompt_presets()) {\n\t\tsource_diagnostics.push(\n\t\t\t...project_json.diagnostics,\n\t\t\t...project_markdown.diagnostics,\n\t\t);\n\t\tsources.push(\n\t\t\tto_prompt_preset_definitions(\n\t\t\t\tproject_json.presets,\n\t\t\t\t'project',\n\t\t\t\t'project-json',\n\t\t\t\tget_project_presets_path(cwd),\n\t\t\t\tfalse,\n\t\t\t),\n\t\t\tproject_markdown.definitions,\n\t\t);\n\t}\n\n\tconst chains = new Map<string, PromptPresetDefinition[]>();\n\tfor (const source of sources) {\n\t\tfor (const definition of Object.values(source)) {\n\t\t\tconst chain = chains.get(definition.name) ?? [];\n\t\t\tchain.push(definition);\n\t\t\tchains.set(definition.name, chain);\n\t\t}\n\t}\n\tconst diagnostics: PromptPresetDiagnostic[] = [\n\t\t...source_diagnostics,\n\t];\n\tconst presets: Record<string, LoadedPromptPreset> = {};\n\tfor (const [name, chain] of chains) {\n\t\tconst winner = chain.at(-1)!;\n\t\tconst fallbacks = chain.slice(0, -1).reverse();\n\t\tpresets[name] = { ...winner, fallbacks };\n\t\tfor (const shadowed of fallbacks) {\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: 'shadowed',\n\t\t\t\tname,\n\t\t\t\tmessage: `${shadowed.origin} definition is shadowed by ${winner.origin}`,\n\t\t\t\tpath: shadowed.path,\n\t\t\t\torigin: shadowed.origin,\n\t\t\t});\n\t\t}\n\t}\n\treturn { presets, diagnostics };\n}\n\nexport function load_prompt_presets(\n\tcwd: string,\n): Record<string, LoadedPromptPreset> {\n\treturn load_prompt_preset_catalog(cwd).presets;\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 migrate_legacy_prompt_presets(\n\tcwd: string,\n\tscope: 'global' | 'project',\n): PromptPresetMigrationResult {\n\treturn migrate_legacy_prompt_presets_with_dependencies(cwd, scope, {\n\t\tglobal_presets_dir: get_global_presets_dir(),\n\t\tsettings_path: get_settings_path(),\n\t\tread_settings,\n\t\twrite_settings,\n\t});\n}\n\nfunction migrate_legacy_prompt_presets_with_dependencies(\n\tcwd: string,\n\tscope: 'global' | 'project',\n\tdependencies: {\n\t\tglobal_presets_dir: string;\n\t\tsettings_path: string;\n\t\tread_settings: typeof read_settings;\n\t\twrite_settings: typeof write_settings;\n\t},\n): PromptPresetMigrationResult {\n\tconst read_global_settings = dependencies.read_settings;\n\tconst write_global_settings = dependencies.write_settings;\n\tconst legacy_path =\n\t\tscope === 'global'\n\t\t\t? dependencies.settings_path\n\t\t\t: get_project_presets_path(cwd);\n\tconst destination =\n\t\tscope === 'global'\n\t\t\t? dependencies.global_presets_dir\n\t\t\t: get_project_presets_dir(cwd);\n\tconst legacy =\n\t\tscope === 'global'\n\t\t\t? normalize_prompt_presets(\n\t\t\t\t\tread_global_settings().promptPresets?.global ?? {},\n\t\t\t\t)\n\t\t\t: read_prompt_presets_file(legacy_path);\n\tconst written: string[] = [];\n\tconst collisions: PromptPresetDiagnostic[] = [];\n\tconst remaining: PromptPresetMap = {};\n\tif (Object.keys(legacy).length === 0) {\n\t\treturn {\n\t\t\tscope,\n\t\t\twritten,\n\t\t\tcollisions,\n\t\t\tlegacy_path,\n\t\t\tremaining_legacy: 0,\n\t\t};\n\t}\n\n\tfor (const [name, preset] of Object.entries(legacy)) {\n\t\tlet path: string;\n\t\ttry {\n\t\t\tpath = get_prompt_preset_file_path(destination, name);\n\t\t} catch {\n\t\t\tremaining[name] = preset;\n\t\t\tcollisions.push({\n\t\t\t\tcode: 'migration-unsafe-name',\n\t\t\t\tname,\n\t\t\t\tmessage: `Kept legacy definition because its name cannot round-trip to a Markdown filename`,\n\t\t\t\tpath: legacy_path,\n\t\t\t\torigin:\n\t\t\t\t\tscope === 'global'\n\t\t\t\t\t\t? 'legacy-global-settings'\n\t\t\t\t\t\t: 'project-json',\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (path !== join(destination, `${name}.md`)) {\n\t\t\tremaining[name] = preset;\n\t\t\tcollisions.push({\n\t\t\t\tcode: 'migration-unsafe-name',\n\t\t\t\tname,\n\t\t\t\tmessage: `Kept legacy definition because its name would change in Markdown`,\n\t\t\t\tpath: legacy_path,\n\t\t\t\torigin:\n\t\t\t\t\tscope === 'global'\n\t\t\t\t\t\t? 'legacy-global-settings'\n\t\t\t\t\t\t: 'project-json',\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (existsSync(path)) {\n\t\t\tremaining[name] = preset;\n\t\t\tcollisions.push({\n\t\t\t\tcode: 'migration-collision',\n\t\t\t\tname,\n\t\t\t\tmessage: `Kept legacy definition because ${path} already exists`,\n\t\t\t\tpath,\n\t\t\t\torigin:\n\t\t\t\t\tscope === 'global'\n\t\t\t\t\t\t? 'legacy-global-settings'\n\t\t\t\t\t\t: 'project-json',\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tsave_prompt_preset_file(destination, name, preset);\n\t\twritten.push(path);\n\t}\n\n\tif (scope === 'global') {\n\t\tconst settings = read_global_settings();\n\t\twrite_global_settings({\n\t\t\t...settings,\n\t\t\tpromptPresets: {\n\t\t\t\t...settings.promptPresets,\n\t\t\t\tglobal:\n\t\t\t\t\tObject.keys(remaining).length > 0\n\t\t\t\t\t\t? sort_prompt_presets(remaining)\n\t\t\t\t\t\t: undefined,\n\t\t\t},\n\t\t});\n\t} else if (Object.keys(remaining).length > 0) {\n\t\tsave_project_prompt_presets(cwd, remaining);\n\t} else if (existsSync(legacy_path)) {\n\t\tunlinkSync(legacy_path);\n\t}\n\n\treturn {\n\t\tscope,\n\t\twritten,\n\t\tcollisions,\n\t\tlegacy_path,\n\t\tremaining_legacy: Object.keys(remaining).length,\n\t};\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\ttry {\n\t\tconst parsed = (\n\t\t\tpath === get_persisted_prompt_state_path()\n\t\t\t\t? (read_settings().promptPresets?.state ?? {})\n\t\t\t\t: existsSync(path)\n\t\t\t\t\t? JSON.parse(readFileSync(path, 'utf-8'))\n\t\t\t\t\t: {}\n\t\t) 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 next = {\n\t\tversion: 1,\n\t\tprojects: Object.fromEntries(\n\t\t\tObject.entries(persisted.projects).sort(([a], [b]) =>\n\t\t\t\ta.localeCompare(b),\n\t\t\t),\n\t\t),\n\t};\n\tif (path === get_persisted_prompt_state_path()) {\n\t\tconst settings = read_settings();\n\t\twrite_settings({\n\t\t\t...settings,\n\t\t\tpromptPresets: { ...settings.promptPresets, state: next },\n\t\t});\n\t\treturn path;\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(tmp, JSON.stringify(next, null, '\\t') + '\\n', {\n\t\tmode: 0o600,\n\t});\n\trenameSync(tmp, path);\n\treturn path;\n}\n","import {\n\texistsSync,\n\treaddirSync,\n\trenameSync,\n\tunlinkSync,\n} from 'node:fs';\nimport { basename, join } from 'node:path';\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_preset_catalog,\n\tsave_persisted_prompt_state,\n\tsave_prompt_preset_file,\n} from './storage.js';\nimport type {\n\tLoadedPromptPreset,\n\tPromptPreset,\n\tPromptPresetCatalog,\n\tPromptPresetKind,\n\tPromptPresetState,\n} from './types.js';\n\nexport type PromptPresetScope = 'global' | 'project';\nexport type PromptPresetLibraryErrorCode =\n\t| 'collision'\n\t| 'confirmation-required'\n\t| 'invalid-instructions'\n\t| 'invalid-kind'\n\t| 'invalid-name'\n\t| 'invalid-scope'\n\t| 'not-found'\n\t| 'project-disabled'\n\t| 'read-only'\n\t| 'source-mismatch';\n\nexport class PromptPresetLibraryError extends Error {\n\tconstructor(\n\t\tpublic readonly code: PromptPresetLibraryErrorCode,\n\t\tmessage: string,\n\t\tpublic readonly details: Record<string, unknown> = {},\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'PromptPresetLibraryError';\n\t}\n}\n\nexport interface PromptPresetDeleteConfirmation {\n\tname: string;\n\tscope: PromptPresetScope;\n\tpath: string;\n\tkind: PromptPresetKind;\n\tfallback: LoadedPromptPreset | undefined;\n\tactive: boolean;\n}\n\nexport interface PromptPresetMutationResult {\n\tpreset: LoadedPromptPreset | undefined;\n\tcatalog: PromptPresetCatalog;\n\tpath: string;\n\tstate?: PromptPresetState;\n}\n\nconst PORTABLE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\nconst WINDOWS_RESERVED_BASENAME =\n\t/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(?:\\.|$)/i;\n\nfunction validate_scope(\n\tscope: string,\n): asserts scope is PromptPresetScope {\n\tif (scope !== 'global' && scope !== 'project') {\n\t\tthrow new PromptPresetLibraryError(\n\t\t\t'invalid-scope',\n\t\t\t`Invalid prompt preset scope: ${scope}`,\n\t\t\t{ scope },\n\t\t);\n\t}\n}\n\nfunction validate_kind(\n\tkind: string,\n): asserts kind is PromptPresetKind {\n\tif (kind !== 'base' && kind !== 'layer') {\n\t\tthrow new PromptPresetLibraryError(\n\t\t\t'invalid-kind',\n\t\t\t`Invalid prompt preset kind: ${kind}`,\n\t\t\t{ kind },\n\t\t);\n\t}\n}\n\nexport function validate_prompt_preset_name(name: string): string {\n\tif (\n\t\tname !== name.trim() ||\n\t\t!PORTABLE_NAME_PATTERN.test(name) ||\n\t\tname.endsWith('.') ||\n\t\tWINDOWS_RESERVED_BASENAME.test(name)\n\t) {\n\t\tthrow new PromptPresetLibraryError(\n\t\t\t'invalid-name',\n\t\t\t`Prompt preset name is not portable: ${JSON.stringify(name)}`,\n\t\t\t{ name },\n\t\t);\n\t}\n\tconst path = get_prompt_preset_file_path('/presets', name);\n\tif (basename(path) !== `${name}.md`) {\n\t\tthrow new PromptPresetLibraryError(\n\t\t\t'invalid-name',\n\t\t\t`Prompt preset name cannot round-trip to Markdown: ${name}`,\n\t\t\t{ name },\n\t\t);\n\t}\n\treturn name;\n}\n\nfunction get_scope_dir(\n\tcwd: string,\n\tscope: PromptPresetScope,\n): string {\n\tvalidate_scope(scope);\n\tif (\n\t\tscope === 'project' &&\n\t\t['0', 'false', 'no', 'skip', 'disable'].includes(\n\t\t\tprocess.env.MY_PI_PROMPT_PRESETS_PROJECT?.trim().toLowerCase() ??\n\t\t\t\t'',\n\t\t)\n\t) {\n\t\tthrow new PromptPresetLibraryError(\n\t\t\t'project-disabled',\n\t\t\t'Project prompt presets are disabled for this repository',\n\t\t\t{ scope },\n\t\t);\n\t}\n\treturn scope === 'global'\n\t\t? get_global_presets_dir()\n\t\t: get_project_presets_dir(cwd);\n}\n\nfunction get_scope_origin(scope: PromptPresetScope) {\n\treturn scope === 'global' ? 'global-markdown' : 'project-markdown';\n}\n\nfunction assert_portable_path_available(\n\tdir: string,\n\tname: string,\n\tignore_path?: string,\n): string {\n\tconst path = get_prompt_preset_file_path(dir, name);\n\tif (existsSync(dir)) {\n\t\tconst collision = readdirSync(dir).find((entry) => {\n\t\t\tconst candidate = join(dir, entry);\n\t\t\treturn (\n\t\t\t\tcandidate !== ignore_path &&\n\t\t\t\tentry.toLocaleLowerCase('en-US') ===\n\t\t\t\t\t`${name}.md`.toLocaleLowerCase('en-US')\n\t\t\t);\n\t\t});\n\t\tif (collision) {\n\t\t\tthrow new PromptPresetLibraryError(\n\t\t\t\t'collision',\n\t\t\t\t`Prompt preset filename collides with ${collision}`,\n\t\t\t\t{ name, path: join(dir, collision) },\n\t\t\t);\n\t\t}\n\t}\n\treturn path;\n}\n\nfunction find_scope_definition(\n\tcwd: string,\n\tscope: PromptPresetScope,\n\tname: string,\n): LoadedPromptPreset | undefined {\n\tconst origin = get_scope_origin(scope);\n\tconst loaded = load_prompt_preset_catalog(cwd).presets[name];\n\tif (loaded?.origin === origin) return loaded;\n\treturn loaded?.fallbacks.find((item) => item.origin === origin) as\n\t\t| LoadedPromptPreset\n\t\t| undefined;\n}\n\nfunction normalize_preset(preset: PromptPreset): PromptPreset {\n\tconst kind = preset.kind ?? 'base';\n\tvalidate_kind(kind);\n\tif (!preset.instructions.trim()) {\n\t\tthrow new PromptPresetLibraryError(\n\t\t\t'invalid-instructions',\n\t\t\t'Prompt preset instructions cannot be empty',\n\t\t);\n\t}\n\treturn {\n\t\tkind,\n\t\tinstructions: preset.instructions,\n\t\t...(preset.description?.trim()\n\t\t\t? { description: preset.description.trim() }\n\t\t\t: {}),\n\t};\n}\n\nexport function reload_prompt_preset_library(\n\tcwd: string,\n): PromptPresetCatalog {\n\treturn load_prompt_preset_catalog(cwd);\n}\n\nexport function create_prompt_preset(\n\tcwd: string,\n\tscope: PromptPresetScope,\n\tname: string,\n\tpreset: PromptPreset,\n): PromptPresetMutationResult {\n\tvalidate_scope(scope);\n\tvalidate_prompt_preset_name(name);\n\tconst dir = get_scope_dir(cwd, scope);\n\tconst path = assert_portable_path_available(dir, name);\n\tif (existsSync(path)) {\n\t\tthrow new PromptPresetLibraryError(\n\t\t\t'collision',\n\t\t\t`Preset already exists: ${name}`,\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tpath,\n\t\t\t},\n\t\t);\n\t}\n\tsave_prompt_preset_file(dir, name, normalize_preset(preset));\n\tconst catalog = reload_prompt_preset_library(cwd);\n\treturn { preset: catalog.presets[name], catalog, path };\n}\n\nexport function copy_prompt_preset(\n\tcwd: string,\n\tname: string,\n\tsource_scope: PromptPresetScope | 'builtin',\n\ttarget_scope: PromptPresetScope,\n\ttarget_name = name,\n): PromptPresetMutationResult {\n\tvalidate_prompt_preset_name(name);\n\tvalidate_prompt_preset_name(target_name);\n\tif (source_scope !== 'builtin') {\n\t\tvalidate_scope(source_scope);\n\t\tget_scope_dir(cwd, source_scope);\n\t}\n\tvalidate_scope(target_scope);\n\tconst loaded = load_prompt_preset_catalog(cwd).presets[name];\n\tconst chain = loaded ? [loaded, ...loaded.fallbacks] : [];\n\tconst source = chain.find((definition) => {\n\t\tif (source_scope === 'builtin') {\n\t\t\treturn definition.origin === 'builtin';\n\t\t}\n\t\treturn source_scope === 'global'\n\t\t\t? ['global-markdown', 'legacy-global-settings'].includes(\n\t\t\t\t\tdefinition.origin,\n\t\t\t\t)\n\t\t\t: ['project-markdown', 'project-json'].includes(\n\t\t\t\t\tdefinition.origin,\n\t\t\t\t);\n\t});\n\tif (!source) {\n\t\tthrow new PromptPresetLibraryError(\n\t\t\tloaded ? 'source-mismatch' : 'not-found',\n\t\t\tloaded\n\t\t\t\t? `Preset ${name} has no ${source_scope} definition`\n\t\t\t\t: `Preset not found: ${name}`,\n\t\t\t{ name, source_scope },\n\t\t);\n\t}\n\treturn create_prompt_preset(cwd, target_scope, target_name, source);\n}\n\nfunction require_custom_scope_definition(\n\tcwd: string,\n\tscope: PromptPresetScope,\n\tname: string,\n): LoadedPromptPreset {\n\tvalidate_prompt_preset_name(name);\n\tget_scope_dir(cwd, scope);\n\tconst definition = find_scope_definition(cwd, scope, name);\n\tif (!definition?.path) {\n\t\tconst winner = load_prompt_preset_catalog(cwd).presets[name];\n\t\tconst code = !winner\n\t\t\t? 'not-found'\n\t\t\t: winner.origin === 'builtin'\n\t\t\t\t? 'read-only'\n\t\t\t\t: 'source-mismatch';\n\t\tthrow new PromptPresetLibraryError(\n\t\t\tcode,\n\t\t\twinner?.origin === 'builtin'\n\t\t\t\t? `Built-in preset is read-only: ${name}`\n\t\t\t\t: winner\n\t\t\t\t\t? `Preset ${name} is owned by ${winner.origin}, not ${scope} Markdown`\n\t\t\t\t\t: `No ${scope} Markdown preset found: ${name}`,\n\t\t\t{ name, scope, origin: winner?.origin },\n\t\t);\n\t}\n\treturn definition;\n}\n\nfunction rename_state(\n\tstate: PromptPresetState | undefined,\n\told_name: string,\n\tnew_name: string,\n\tkind: PromptPresetKind,\n): PromptPresetState | undefined {\n\tif (!state) return undefined;\n\treturn {\n\t\tbase_name:\n\t\t\tkind === 'base' && state.base_name === old_name\n\t\t\t\t? new_name\n\t\t\t\t: state.base_name,\n\t\tlayer_names:\n\t\t\tkind === 'layer'\n\t\t\t\t? [\n\t\t\t\t\t\t...new Set(\n\t\t\t\t\t\t\tstate.layer_names.map((name) =>\n\t\t\t\t\t\t\t\tname === old_name ? new_name : name,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t].sort()\n\t\t\t\t: state.layer_names,\n\t};\n}\n\nexport function rename_prompt_preset(\n\tcwd: string,\n\tscope: PromptPresetScope,\n\told_name: string,\n\tnew_name: string,\n\tactive_state?: PromptPresetState,\n): PromptPresetMutationResult {\n\tconst definition = require_custom_scope_definition(\n\t\tcwd,\n\t\tscope,\n\t\told_name,\n\t);\n\tvalidate_prompt_preset_name(new_name);\n\tconst dir = get_scope_dir(cwd, scope);\n\tconst old_path = definition.path!;\n\tconst new_path = assert_portable_path_available(\n\t\tdir,\n\t\tnew_name,\n\t\told_path,\n\t);\n\tif (existsSync(new_path) && new_path !== old_path) {\n\t\tthrow new PromptPresetLibraryError(\n\t\t\t'collision',\n\t\t\t`Preset already exists: ${new_name}`,\n\t\t);\n\t}\n\tconst persisted = load_persisted_prompt_state(cwd);\n\tconst next_persisted = rename_state(\n\t\tpersisted,\n\t\told_name,\n\t\tnew_name,\n\t\tdefinition.kind,\n\t);\n\tconst next_active = rename_state(\n\t\tactive_state,\n\t\told_name,\n\t\tnew_name,\n\t\tdefinition.kind,\n\t);\n\trenameSync(old_path, new_path);\n\ttry {\n\t\tif (next_persisted)\n\t\t\tsave_persisted_prompt_state(cwd, next_persisted);\n\t} catch (error) {\n\t\trenameSync(new_path, old_path);\n\t\tthrow error;\n\t}\n\tconst catalog = reload_prompt_preset_library(cwd);\n\treturn {\n\t\tpreset: catalog.presets[new_name],\n\t\tcatalog,\n\t\tpath: new_path,\n\t\t...(next_active ? { state: next_active } : {}),\n\t};\n}\n\nexport function get_delete_prompt_preset_confirmation(\n\tcwd: string,\n\tscope: PromptPresetScope,\n\tname: string,\n\tstate = load_persisted_prompt_state(cwd),\n): PromptPresetDeleteConfirmation {\n\tconst definition = require_custom_scope_definition(\n\t\tcwd,\n\t\tscope,\n\t\tname,\n\t);\n\tconst winner = load_prompt_preset_catalog(cwd).presets[name];\n\tconst fallback =\n\t\twinner?.origin === get_scope_origin(scope)\n\t\t\t? (winner.fallbacks[0] as LoadedPromptPreset | undefined)\n\t\t\t: winner;\n\treturn {\n\t\tname,\n\t\tscope,\n\t\tpath: definition.path!,\n\t\tkind: definition.kind,\n\t\tfallback,\n\t\tactive:\n\t\t\tstate?.base_name === name ||\n\t\t\tstate?.layer_names.includes(name) === true,\n\t};\n}\n\nexport function delete_prompt_preset(\n\tcwd: string,\n\tscope: PromptPresetScope,\n\tname: string,\n\tconfirmed = false,\n): PromptPresetMutationResult {\n\tconst confirmation = get_delete_prompt_preset_confirmation(\n\t\tcwd,\n\t\tscope,\n\t\tname,\n\t);\n\tif (!confirmed) {\n\t\tthrow new PromptPresetLibraryError(\n\t\t\t'confirmation-required',\n\t\t\t`Confirmation required to delete ${name}`,\n\t\t\t{ confirmation },\n\t\t);\n\t}\n\tunlinkSync(confirmation.path);\n\tconst catalog = reload_prompt_preset_library(cwd);\n\treturn {\n\t\tpreset: catalog.presets[name],\n\t\tcatalog,\n\t\tpath: confirmation.path,\n\t};\n}\n\nexport function reset_prompt_preset_override(\n\tcwd: string,\n\tscope: PromptPresetScope,\n\tname: string,\n): PromptPresetMutationResult {\n\tconst definition = require_custom_scope_definition(\n\t\tcwd,\n\t\tscope,\n\t\tname,\n\t);\n\tunlinkSync(definition.path!);\n\tconst catalog = reload_prompt_preset_library(cwd);\n\treturn {\n\t\tpreset: catalog.presets[name],\n\t\tcatalog,\n\t\tpath: definition.path!,\n\t};\n}\n","import type { LoadedPromptPreset } from './types.js';\n\nexport function build_active_prompt_blocks(\n\tpresets: Record<string, LoadedPromptPreset>,\n\tactive_base_name: string | undefined,\n\tactive_layers: ReadonlySet<string>,\n): string[] {\n\tconst blocks: string[] = [];\n\tconst base = active_base_name\n\t\t? presets[active_base_name]\n\t\t: undefined;\n\tif (base?.instructions.trim()) {\n\t\tblocks.push(\n\t\t\t`## Active Base Prompt: ${base.name}\\n${base.instructions.trim()}`,\n\t\t);\n\t}\n\n\tconst layer_blocks = [...active_layers]\n\t\t.sort()\n\t\t.map((name) => presets[name])\n\t\t.filter((preset): preset is LoadedPromptPreset =>\n\t\t\tBoolean(preset?.instructions.trim()),\n\t\t)\n\t\t.map(\n\t\t\t(preset) => `### ${preset.name}\\n${preset.instructions.trim()}`,\n\t\t);\n\tif (layer_blocks.length > 0) {\n\t\tblocks.push(\n\t\t\t`## Active Prompt Layers\\n\\n${layer_blocks.join('\\n\\n')}`,\n\t\t);\n\t}\n\n\treturn blocks;\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 type { ExtensionCommandContext } from '@earendil-works/pi-coding-agent';\nimport {\n\tKey,\n\tmatchesKey,\n\ttruncateToWidth,\n\tvisibleWidth,\n\twrapTextWithAnsi,\n\ttype Component,\n} from '@earendil-works/pi-tui';\nimport { show_modal, type ModalTheme } from '@spences10/pi-tui-modal';\nimport {\n\tget_prompt_source_label,\n\tlist_base_presets,\n\tlist_layer_presets,\n} from './catalog.js';\nimport { build_active_prompt_blocks } from './prompt-blocks.js';\nimport { NONE_BASE_ID } from './state.js';\nimport type { LoadedPromptPreset } from './types.js';\n\nexport interface PromptPresetManagerState {\n\tpresets: Record<string, LoadedPromptPreset>;\n\tactive_base_name: string | undefined;\n\tactive_layers: ReadonlySet<string>;\n}\n\nexport type PromptPresetManagementAction =\n\t| 'create'\n\t| 'edit'\n\t| 'copy'\n\t| 'rename'\n\t| 'delete'\n\t| 'reset'\n\t| 'reload';\n\nexport type PromptPresetManagerResult =\n\t| {\n\t\t\taction: 'apply';\n\t\t\tbase_name: string | undefined;\n\t\t\tlayers: ReadonlySet<string>;\n\t }\n\t| { action: 'cancel' }\n\t| {\n\t\t\taction: PromptPresetManagementAction;\n\t\t\tpreset?: LoadedPromptPreset;\n\t };\n\ntype PresetRow =\n\t| { type: 'header'; id: string; label: string }\n\t| { type: 'base-none'; id: typeof NONE_BASE_ID; label: string }\n\t| { type: 'preset'; id: string; preset: LoadedPromptPreset };\n\nexport async function show_prompt_preset_manager(\n\tctx: ExtensionCommandContext,\n\tstate: PromptPresetManagerState,\n): Promise<PromptPresetManagerResult> {\n\tconst base_presets = list_base_presets(state.presets);\n\tconst layer_presets = list_layer_presets(state.presets);\n\tif (base_presets.length === 0 && layer_presets.length === 0) {\n\t\tctx.ui.notify('No prompt presets available', 'warning');\n\t\treturn { action: 'cancel' };\n\t}\n\n\tconst result = await show_modal<\n\t\tPromptPresetManagerResult | undefined\n\t>(\n\t\tctx,\n\t\t{\n\t\t\ttitle: 'Prompt presets',\n\t\t\tsubtitle: 'Choose one base preset, then add optional layers.',\n\t\t\tfooter: '↑↓ move • space select • enter Apply • esc Cancel',\n\t\t\toverlay_options: {\n\t\t\t\twidth: '94%',\n\t\t\t\tminWidth: 44,\n\t\t\t\tmaxHeight: '92%',\n\t\t\t},\n\t\t},\n\t\t({ done }, theme, layout) =>\n\t\t\tnew PromptPresetInspectorBody(\n\t\t\t\tstate,\n\t\t\t\ttheme,\n\t\t\t\t() => layout.get_max_body_lines(),\n\t\t\t\tdone,\n\t\t\t),\n\t);\n\n\treturn result ?? { action: 'cancel' };\n}\n\nexport class PromptPresetInspectorBody implements Component {\n\tprivate readonly rows: PresetRow[];\n\tprivate selected_index: number;\n\tprivate selected_base: string | undefined;\n\tprivate readonly enabled_layers: Set<string>;\n\tprivate preview_mode: 'item' | 'effective' = 'item';\n\tprivate preview_offset = 0;\n\tprivate preview_lines: string[] = [];\n\n\tconstructor(\n\t\tprivate readonly state: PromptPresetManagerState,\n\t\tprivate readonly theme: ModalTheme,\n\t\tprivate readonly get_max_lines: () => number,\n\t\tprivate readonly done: (\n\t\t\tresult: PromptPresetManagerResult | undefined,\n\t\t) => void,\n\t) {\n\t\tconst base_presets = list_base_presets(state.presets);\n\t\tconst layer_presets = list_layer_presets(state.presets);\n\t\tthis.rows = [\n\t\t\t{\n\t\t\t\ttype: 'header',\n\t\t\t\tid: '__base_header__',\n\t\t\t\tlabel: `Base presets (${base_presets.length + 1})`,\n\t\t\t},\n\t\t\t{ type: 'base-none', id: NONE_BASE_ID, label: '(none)' },\n\t\t\t...base_presets.map((preset) => ({\n\t\t\t\ttype: 'preset' as const,\n\t\t\t\tid: preset.name,\n\t\t\t\tpreset,\n\t\t\t})),\n\t\t\t{\n\t\t\t\ttype: 'header',\n\t\t\t\tid: '__layer_header__',\n\t\t\t\tlabel: `Prompt layers (${layer_presets.length})`,\n\t\t\t},\n\t\t\t...layer_presets.map((preset) => ({\n\t\t\t\ttype: 'preset' as const,\n\t\t\t\tid: preset.name,\n\t\t\t\tpreset,\n\t\t\t})),\n\t\t];\n\t\tthis.selected_base = state.active_base_name;\n\t\tthis.enabled_layers = new Set(state.active_layers);\n\t\tthis.selected_index = this.get_initial_selected_index();\n\t}\n\n\trender(width: number): string[] {\n\t\tconst body_lines = Math.max(8, this.get_max_lines());\n\t\tif (width < 80) return this.render_stacked(width, body_lines);\n\n\t\tconst list_width = Math.min(\n\t\t\t38,\n\t\t\tMath.max(28, Math.floor(width * 0.38)),\n\t\t);\n\t\tconst preview_width = width - list_width - 3;\n\t\tconst list = this.render_list(list_width, body_lines);\n\t\tconst preview = this.render_preview(preview_width, body_lines);\n\t\tconst lines: string[] = [];\n\t\tfor (let i = 0; i < body_lines; i++) {\n\t\t\tlines.push(\n\t\t\t\t`${this.pad_line(list[i] ?? '', list_width)} ${this.theme.fg('dim', '│')} ${preview[i] ?? ''}`,\n\t\t\t);\n\t\t}\n\t\treturn lines.map((line) => truncateToWidth(line, width));\n\t}\n\n\tinvalidate(): void {\n\t\t// No cached rendering.\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (matchesKey(data, Key.up) || data === 'k') {\n\t\t\tthis.move(-1);\n\t\t} else if (matchesKey(data, Key.down) || data === 'j') {\n\t\t\tthis.move(1);\n\t\t} else if (data === ' ' || matchesKey(data, Key.enter)) {\n\t\t\tif (matchesKey(data, Key.enter)) {\n\t\t\t\tthis.done({\n\t\t\t\t\taction: 'apply',\n\t\t\t\t\tbase_name: this.selected_base,\n\t\t\t\t\tlayers: new Set(this.enabled_layers),\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.toggle_selected();\n\t\t} else if (data === '\\t') {\n\t\t\tthis.preview_mode =\n\t\t\t\tthis.preview_mode === 'item' ? 'effective' : 'item';\n\t\t\tthis.preview_offset = 0;\n\t\t} else if (data === 'c') {\n\t\t\tthis.selected_base = undefined;\n\t\t\tthis.enabled_layers.clear();\n\t\t\tthis.preview_mode = 'effective';\n\t\t\tthis.preview_offset = 0;\n\t\t} else if (data === 'a') {\n\t\t\tthis.done({\n\t\t\t\taction: 'apply',\n\t\t\t\tbase_name: this.selected_base,\n\t\t\t\tlayers: new Set(this.enabled_layers),\n\t\t\t});\n\t\t} else if ('neyrdxl'.includes(data)) {\n\t\t\tconst actions = {\n\t\t\t\tn: 'create',\n\t\t\t\te: 'edit',\n\t\t\t\ty: 'copy',\n\t\t\t\tr: 'rename',\n\t\t\t\td: 'delete',\n\t\t\t\tx: 'reset',\n\t\t\t\tl: 'reload',\n\t\t\t} as const;\n\t\t\tconst row = this.rows[this.selected_index];\n\t\t\tconst action = actions[data as keyof typeof actions];\n\t\t\tif (action === 'create' || action === 'reload') {\n\t\t\t\tthis.done({ action });\n\t\t\t} else if (row?.type === 'preset') {\n\t\t\t\tthis.done({ action, preset: row.preset });\n\t\t\t}\n\t\t} else if (matchesKey(data, Key.escape) || data === 'q') {\n\t\t\tthis.done({ action: 'cancel' });\n\t\t} else if (data === 'J') {\n\t\t\tthis.scroll_preview(1);\n\t\t} else if (data === 'K') {\n\t\t\tthis.scroll_preview(-1);\n\t\t}\n\t}\n\n\tprivate render_stacked(\n\t\twidth: number,\n\t\tbody_lines: number,\n\t): string[] {\n\t\tconst list_lines = Math.max(5, Math.floor(body_lines / 2));\n\t\treturn [\n\t\t\t...this.render_list(width, list_lines),\n\t\t\tthis.theme.fg('dim', '─'.repeat(Math.min(width, 80))),\n\t\t\t...this.render_preview(width, body_lines - list_lines - 1),\n\t\t];\n\t}\n\n\tprivate render_list(width: number, max_lines: number): string[] {\n\t\tconst action_lines = wrapTextWithAnsi(\n\t\t\t'N Create E Edit Y Copy R Rename D Delete X Reset L Reload',\n\t\t\tMath.max(20, width),\n\t\t).map((line) => this.theme.fg('dim', line));\n\t\tconst lines = [\n\t\t\tthis.theme.fg(\n\t\t\t\t'accent',\n\t\t\t\t`Draft: ${this.selected_base ?? '(none)'} + ${this.enabled_layers.size} layer(s)`,\n\t\t\t),\n\t\t\t...action_lines,\n\t\t\t'',\n\t\t];\n\t\tconst visible_rows = Math.max(1, max_lines - lines.length);\n\t\tconst start = Math.max(\n\t\t\t0,\n\t\t\tMath.min(\n\t\t\t\tthis.selected_index - Math.floor(visible_rows / 2),\n\t\t\t\tthis.rows.length - visible_rows,\n\t\t\t),\n\t\t);\n\t\tconst end = Math.min(start + visible_rows, this.rows.length);\n\t\tfor (let index = start; index < end; index++) {\n\t\t\tlines.push(this.render_row(this.rows[index], index, width));\n\t\t}\n\t\treturn lines.map((line) => truncateToWidth(line, width));\n\t}\n\n\tprivate render_preview(width: number, max_lines: number): string[] {\n\t\tconst heading =\n\t\t\tthis.preview_mode === 'effective'\n\t\t\t\t? 'Full prompt contribution'\n\t\t\t\t: this.get_selected_heading();\n\t\tconst text =\n\t\t\tthis.preview_mode === 'effective'\n\t\t\t\t? this.get_effective_prompt_text()\n\t\t\t\t: this.get_selected_prompt_text();\n\t\tconst content_width = Math.max(10, width);\n\t\tthis.preview_lines = text\n\t\t\t.split('\\n')\n\t\t\t.flatMap((line) =>\n\t\t\t\tline.trim().length === 0\n\t\t\t\t\t? ['']\n\t\t\t\t\t: wrapTextWithAnsi(line, content_width),\n\t\t\t);\n\t\tconst available = Math.max(1, max_lines - 2);\n\t\tconst max_offset = Math.max(\n\t\t\t0,\n\t\t\tthis.preview_lines.length - available,\n\t\t);\n\t\tthis.preview_offset = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.preview_offset, max_offset),\n\t\t);\n\t\tconst end = Math.min(\n\t\t\tthis.preview_offset + available,\n\t\t\tthis.preview_lines.length,\n\t\t);\n\t\tconst range =\n\t\t\tthis.preview_lines.length > available\n\t\t\t\t? ` (${this.preview_offset + 1}-${end}/${this.preview_lines.length})`\n\t\t\t\t: '';\n\t\treturn [\n\t\t\tthis.theme.fg('accent', this.theme.bold(`${heading}${range}`)),\n\t\t\t'',\n\t\t\t...this.preview_lines\n\t\t\t\t.slice(this.preview_offset, end)\n\t\t\t\t.map((line) => truncateToWidth(line, width)),\n\t\t];\n\t}\n\n\tprivate render_row(\n\t\trow: PresetRow,\n\t\tindex: number,\n\t\twidth: number,\n\t): string {\n\t\tif (row.type === 'header') {\n\t\t\treturn this.theme.fg('muted', ` ${row.label}`);\n\t\t}\n\t\tconst selected = index === this.selected_index;\n\t\tconst cursor = selected ? this.theme.fg('accent', '› ') : ' ';\n\t\tconst marker = this.get_marker(row);\n\t\tconst label =\n\t\t\trow.type === 'base-none' ? row.label : row.preset.name;\n\t\tconst suffix =\n\t\t\trow.type === 'preset'\n\t\t\t\t? ` ${this.theme.fg('dim', get_prompt_source_label(row.preset.source))}`\n\t\t\t\t: '';\n\t\treturn truncateToWidth(\n\t\t\t`${cursor}${marker} ${this.pad(label, 18)}${suffix}`,\n\t\t\twidth,\n\t\t);\n\t}\n\n\tprivate get_marker(row: PresetRow): string {\n\t\tif (row.type === 'header') return ' ';\n\t\tif (row.type === 'base-none') {\n\t\t\treturn this.selected_base ? '○' : '●';\n\t\t}\n\t\tif (row.preset.kind === 'base') {\n\t\t\treturn this.selected_base === row.preset.name ? '●' : '○';\n\t\t}\n\t\treturn this.enabled_layers.has(row.preset.name) ? '☑' : '☐';\n\t}\n\n\tprivate get_selected_prompt_text(): string {\n\t\tconst row = this.rows[this.selected_index];\n\t\tif (!row || row.type === 'header') return '';\n\t\tif (row.type === 'base-none') {\n\t\t\treturn 'No active base preset. Only enabled prompt layers will be appended.';\n\t\t}\n\t\tconst preset = row.preset;\n\t\treturn [\n\t\t\tpreset.description || undefined,\n\t\t\tpreset.description ? '' : undefined,\n\t\t\tpreset.instructions.trim() || '(empty preset)',\n\t\t]\n\t\t\t.filter((line): line is string => line !== undefined)\n\t\t\t.join('\\n');\n\t}\n\n\tprivate get_effective_prompt_text(): string {\n\t\tconst blocks = build_active_prompt_blocks(\n\t\t\tthis.state.presets,\n\t\t\tthis.selected_base,\n\t\t\tthis.enabled_layers,\n\t\t);\n\t\treturn blocks.length > 0\n\t\t\t? blocks.join('\\n\\n')\n\t\t\t: '(No prompt preset text will be appended.)';\n\t}\n\n\tprivate get_selected_heading(): string {\n\t\tconst row = this.rows[this.selected_index];\n\t\tif (!row || row.type === 'header') return 'Highlighted preset';\n\t\treturn row.type === 'base-none'\n\t\t\t? 'No base preset'\n\t\t\t: row.preset.name;\n\t}\n\n\tprivate get_initial_selected_index(): number {\n\t\tif (this.selected_base) {\n\t\t\tconst base_index = this.rows.findIndex(\n\t\t\t\t(row) =>\n\t\t\t\t\trow.type === 'preset' && row.id === this.selected_base,\n\t\t\t);\n\t\t\tif (base_index >= 0) return base_index;\n\t\t}\n\t\tconst active_layer_index = this.rows.findIndex(\n\t\t\t(row) =>\n\t\t\t\trow.type === 'preset' && this.enabled_layers.has(row.id),\n\t\t);\n\t\treturn active_layer_index >= 0 ? active_layer_index : 1;\n\t}\n\n\tprivate toggle_selected(): void {\n\t\tconst row = this.rows[this.selected_index];\n\t\tif (!row || row.type === 'header') return;\n\t\tif (row.type === 'base-none') {\n\t\t\tthis.selected_base = undefined;\n\t\t} else if (row.preset.kind === 'base') {\n\t\t\tthis.selected_base = row.preset.name;\n\t\t} else if (this.enabled_layers.has(row.preset.name)) {\n\t\t\tthis.enabled_layers.delete(row.preset.name);\n\t\t} else {\n\t\t\tthis.enabled_layers.add(row.preset.name);\n\t\t}\n\t\tthis.preview_mode = 'effective';\n\t\tthis.preview_offset = 0;\n\t}\n\n\tprivate move(delta: number): void {\n\t\tlet next = this.selected_index;\n\t\tdo {\n\t\t\tnext = (next + delta + this.rows.length) % this.rows.length;\n\t\t} while (this.rows[next]?.type === 'header');\n\t\tthis.selected_index = next;\n\t\tthis.preview_offset = 0;\n\t}\n\n\tprivate scroll_preview(delta: number): void {\n\t\tconst max_offset = Math.max(0, this.preview_lines.length - 1);\n\t\tthis.preview_offset = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.preview_offset + delta, max_offset),\n\t\t);\n\t}\n\n\tprivate pad(text: string, width: number): string {\n\t\tconst visible = visibleWidth(text);\n\t\treturn text + ' '.repeat(Math.max(0, width - visible));\n\t}\n\n\tprivate pad_line(text: string, width: number): string {\n\t\tconst truncated = truncateToWidth(text, width);\n\t\treturn (\n\t\t\ttruncated +\n\t\t\t' '.repeat(Math.max(0, width - visibleWidth(truncated)))\n\t\t);\n\t}\n}\n","import {\n\ttype ExtensionAPI,\n\ttype ExtensionCommandContext,\n\ttype ExtensionContext,\n} from '@earendil-works/pi-coding-agent';\nimport { existsSync, readFileSync } from 'node:fs';\nimport {\n\tformat_active_details,\n\tformat_summary,\n\tget_prompt_source_label,\n} from './catalog.js';\nimport { get_prompt_preset_completions } from './completions.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\tcopy_prompt_preset,\n\tdelete_prompt_preset,\n\treload_prompt_preset_library,\n\trename_prompt_preset,\n\treset_prompt_preset_override,\n\ttype PromptPresetScope,\n} from './library.js';\nimport { show_prompt_preset_manager } from './manager.js';\nimport { build_active_prompt_blocks } from './prompt-blocks.js';\nimport {\n\tget_last_preset_state,\n\tnormalize_active_state,\n\tparse_preset_flag,\n\tpersist_state,\n} from './state.js';\nimport {\n\tformat_prompt_preset_markdown,\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\tparse_prompt_preset_markdown,\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\tget_current_thinking_level,\n\tget_default_footer_thinking_level,\n\trender_footer_status_line,\n} from '@spences10/pi-footer';\nexport {\n\tDEFAULT_BASE_PROMPT_PRESET_NAME,\n\tDEFAULT_PROMPT_PRESETS,\n} from './defaults.js';\nexport {\n\tcopy_prompt_preset,\n\tcreate_prompt_preset,\n\tdelete_prompt_preset,\n\tget_delete_prompt_preset_confirmation,\n\tPromptPresetLibraryError,\n\treload_prompt_preset_library,\n\trename_prompt_preset,\n\treset_prompt_preset_override,\n\tvalidate_prompt_preset_name,\n} from './library.js';\nexport type {\n\tPromptPresetDeleteConfirmation,\n\tPromptPresetLibraryErrorCode,\n\tPromptPresetMutationResult,\n\tPromptPresetScope,\n} from './library.js';\nexport {\n\tload_persisted_prompt_state,\n\tload_prompt_preset_catalog,\n\tload_prompt_presets,\n\tmerge_prompt_presets,\n\tmigrate_legacy_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\tPromptPresetCatalog,\n\tPromptPresetDefinition,\n\tPromptPresetDiagnostic,\n\tPromptPresetKind,\n\tPromptPresetMap,\n\tPromptPresetMigrationResult,\n\tPromptPresetOrigin,\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 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\tconst path = get_prompt_preset_file_path(dir, name);\n\t\tconst initial_markdown = existsSync(path)\n\t\t\t? readFileSync(path, 'utf-8')\n\t\t\t: format_prompt_preset_markdown({\n\t\t\t\t\tkind: existing?.kind ?? 'layer',\n\t\t\t\t\tinstructions: existing?.instructions ?? '',\n\t\t\t\t\t...(existing?.description\n\t\t\t\t\t\t? { description: existing.description }\n\t\t\t\t\t\t: {}),\n\t\t\t\t});\n\n\t\tconst edited = await ctx.ui.editor(\n\t\t\t`Edit ${scope} preset markdown: ${name}`,\n\t\t\tinitial_markdown,\n\t\t);\n\t\tif (edited === undefined) return;\n\n\t\tconst { metadata, body } = parse_prompt_preset_markdown(edited);\n\t\tif (!body.trim()) {\n\t\t\tctx.ui.notify('Preset instructions cannot be empty', 'warning');\n\t\t\treturn;\n\t\t}\n\t\tconst kind: PromptPresetKind =\n\t\t\tmetadata.kind === 'base' ? 'base' : 'layer';\n\t\tconst preset = {\n\t\t\tkind,\n\t\t\tinstructions: body,\n\t\t\t...(typeof metadata.description === 'string' &&\n\t\t\tmetadata.description.trim()\n\t\t\t\t? { description: metadata.description.trim() }\n\t\t\t\t: {}),\n\t\t};\n\n\t\tconst saved_path =\n\t\t\tscope === 'global'\n\t\t\t\t? save_global_prompt_preset_file(name, preset)\n\t\t\t\t: save_project_prompt_preset_file(ctx.cwd, name, preset);\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 choose_scope(\n\t\tctx: ExtensionCommandContext,\n\t\taction: string,\n\t): Promise<PromptPresetScope | undefined> {\n\t\tconst choice = await ctx.ui.select(\n\t\t\t`${action}: choose where to write`,\n\t\t\t['Project (.pi/presets)', 'Global (~/.pi/agent/presets)'],\n\t\t);\n\t\treturn choice?.startsWith('Project')\n\t\t\t? 'project'\n\t\t\t: choice\n\t\t\t\t? 'global'\n\t\t\t\t: undefined;\n\t}\n\n\tfunction refresh_after_management(\n\t\tctx: ExtensionCommandContext,\n\t): void {\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\t}\n\n\tasync function show_manager(\n\t\tctx: ExtensionCommandContext,\n\t): Promise<void> {\n\t\twhile (true) {\n\t\t\tconst result = await show_prompt_preset_manager(ctx, {\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\tif (result.action === 'cancel') return;\n\t\t\tif (result.action === 'apply') {\n\t\t\t\tcommit_state(ctx, result.base_name, result.layers, {\n\t\t\t\t\tnotify: 'Updated prompt preset selection',\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tif (result.action === 'reload') {\n\t\t\t\t\tconst catalog = reload_prompt_preset_library(ctx.cwd);\n\t\t\t\t\tpresets = catalog.presets;\n\t\t\t\t\trefresh_after_management(ctx);\n\t\t\t\t\tconst diagnostics = catalog.diagnostics;\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\tdiagnostics.length\n\t\t\t\t\t\t\t? `Reloaded with ${diagnostics.length} validation issue(s):\\n${diagnostics.map((item) => `${item.path}: ${item.message}`).join('\\n')}`\n\t\t\t\t\t\t\t: 'Reloaded prompt presets',\n\t\t\t\t\t\tdiagnostics.length ? 'warning' : 'info',\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst selected = result.preset;\n\t\t\t\tif (result.action === 'create') {\n\t\t\t\t\tconst name = await ctx.ui.input(\n\t\t\t\t\t\t'Create preset',\n\t\t\t\t\t\t'Preset name',\n\t\t\t\t\t);\n\t\t\t\t\tif (!name) continue;\n\t\t\t\t\tconst scope = await choose_scope(ctx, 'Create preset');\n\t\t\t\t\tif (!scope) continue;\n\t\t\t\t\tawait edit_preset(name.trim(), ctx, scope);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!selected) continue;\n\n\t\t\t\tif (result.action === 'edit' && !selected.editable) {\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t'Built-in presets are read-only. Copy it before editing.',\n\t\t\t\t\t\t'warning',\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst scope = await choose_scope(\n\t\t\t\t\tctx,\n\t\t\t\t\t`${result.action} ${selected.name}`,\n\t\t\t\t);\n\t\t\t\tif (!scope) continue;\n\n\t\t\t\tif (result.action === 'edit') {\n\t\t\t\t\tawait edit_preset(selected.name, ctx, scope);\n\t\t\t\t} else if (result.action === 'copy') {\n\t\t\t\t\tconst target = await ctx.ui.input(\n\t\t\t\t\t\t'Copy preset',\n\t\t\t\t\t\tselected.name,\n\t\t\t\t\t);\n\t\t\t\t\tif (!target) continue;\n\t\t\t\t\tcopy_prompt_preset(\n\t\t\t\t\t\tctx.cwd,\n\t\t\t\t\t\tselected.name,\n\t\t\t\t\t\tselected.origin === 'builtin'\n\t\t\t\t\t\t\t? 'builtin'\n\t\t\t\t\t\t\t: selected.origin.startsWith('project')\n\t\t\t\t\t\t\t\t? 'project'\n\t\t\t\t\t\t\t\t: 'global',\n\t\t\t\t\t\tscope,\n\t\t\t\t\t\ttarget.trim(),\n\t\t\t\t\t);\n\t\t\t\t} else if (result.action === 'rename') {\n\t\t\t\t\tif (!selected.editable) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Built-in presets are read-only. Copy it before renaming.',\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst target = await ctx.ui.input(\n\t\t\t\t\t\t'Rename preset',\n\t\t\t\t\t\tselected.name,\n\t\t\t\t\t);\n\t\t\t\t\tif (!target) continue;\n\t\t\t\t\tconst mutation = rename_prompt_preset(\n\t\t\t\t\t\tctx.cwd,\n\t\t\t\t\t\tscope,\n\t\t\t\t\t\tselected.name,\n\t\t\t\t\t\ttarget.trim(),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbase_name: active_base_name ?? null,\n\t\t\t\t\t\t\tlayer_names: [...active_layers],\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tif (mutation.state) {\n\t\t\t\t\t\tactive_base_name = mutation.state.base_name ?? undefined;\n\t\t\t\t\t\tactive_layers = new Set(mutation.state.layer_names);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (!selected.editable) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t'Built-in presets are read-only.',\n\t\t\t\t\t\t\t'warning',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst confirmed = await ctx.ui.confirm(\n\t\t\t\t\t\tresult.action === 'delete'\n\t\t\t\t\t\t\t? 'Delete preset?'\n\t\t\t\t\t\t\t: 'Reset override?',\n\t\t\t\t\t\t`${selected.name} (${scope})`,\n\t\t\t\t\t);\n\t\t\t\t\tif (!confirmed) continue;\n\t\t\t\t\tif (result.action === 'delete')\n\t\t\t\t\t\tdelete_prompt_preset(ctx.cwd, scope, selected.name, true);\n\t\t\t\t\telse\n\t\t\t\t\t\treset_prompt_preset_override(\n\t\t\t\t\t\t\tctx.cwd,\n\t\t\t\t\t\t\tscope,\n\t\t\t\t\t\t\tselected.name,\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\trefresh_after_management(ctx);\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`${result.action} completed for \"${selected.name}\"`,\n\t\t\t\t\t'info',\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\t\t'error',\n\t\t\t\t);\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\tget_prompt_preset_completions(presets, prefix),\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 && ctx.mode === 'tui') {\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 = build_active_prompt_blocks(\n\t\t\tpresets,\n\t\t\tactive_base_name,\n\t\t\tactive_layers,\n\t\t);\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});\n}\n"],"mappings":"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"}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { BorderedLoader, convertToLlm, serializeConversation } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { complete } from "@earendil-works/pi-ai/compat";
|
|
3
|
-
//#region src/extensions/session-name/index.ts
|
|
4
|
-
const SYSTEM_PROMPT = `You are a session naming assistant. Given a conversation history, generate a short, descriptive session name (2-5 words) that captures the main topic or task.
|
|
5
|
-
|
|
6
|
-
Guidelines:
|
|
7
|
-
- Be concise but specific
|
|
8
|
-
- Use kebab-case only
|
|
9
|
-
- Focus on the core task/question
|
|
10
|
-
- Avoid generic names like "discussion" or "conversation"
|
|
11
|
-
- No quotes, no punctuation at the end
|
|
12
|
-
|
|
13
|
-
Examples:
|
|
14
|
-
- "fix auth bug" -> "fix-auth-bug"
|
|
15
|
-
- "how do I deploy to vercel" -> "vercel-deployment"
|
|
16
|
-
- "explain react hooks" -> "react-hooks-explanation"
|
|
17
|
-
- "optimize database queries" -> "db-query-optimization"
|
|
18
|
-
|
|
19
|
-
Output ONLY the session name, nothing else.`;
|
|
20
|
-
const AUTO_NAME_THRESHOLD = 1;
|
|
21
|
-
const MAX_CHARS = 4e3;
|
|
22
|
-
const MAX_NAME_LEN = 50;
|
|
23
|
-
const MAX_ATTEMPTS = 3;
|
|
24
|
-
const RETRY_DELAYS_MS = [1500, 4e3];
|
|
25
|
-
function clean_name(value) {
|
|
26
|
-
return value.replace(/^["']|["']$/g, "").normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, MAX_NAME_LEN).replace(/-+$/g, "");
|
|
27
|
-
}
|
|
28
|
-
function truncate_conversation(value) {
|
|
29
|
-
return value.length > MAX_CHARS ? value.slice(0, MAX_CHARS) + "\n..." : value;
|
|
30
|
-
}
|
|
31
|
-
function is_transient_error(message) {
|
|
32
|
-
return /\b(429|500|502|503|529)\b/.test(message) || /overload|rate.?limit|temporarily unavailable|try again/i.test(message);
|
|
33
|
-
}
|
|
34
|
-
function sleep(ms, signal) {
|
|
35
|
-
return new Promise((resolve) => {
|
|
36
|
-
const timer = setTimeout(resolve, ms);
|
|
37
|
-
signal?.addEventListener("abort", () => {
|
|
38
|
-
clearTimeout(timer);
|
|
39
|
-
resolve();
|
|
40
|
-
}, { once: true });
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
async function complete_with_retry(model, context, options) {
|
|
44
|
-
let last_error = /* @__PURE__ */ new Error("Unknown provider error");
|
|
45
|
-
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
46
|
-
if (attempt > 0) {
|
|
47
|
-
await sleep(RETRY_DELAYS_MS[attempt - 1], options.signal);
|
|
48
|
-
if (options.signal?.aborted) break;
|
|
49
|
-
}
|
|
50
|
-
try {
|
|
51
|
-
const response = await complete(model, context, options);
|
|
52
|
-
if (response.stopReason !== "error") return response;
|
|
53
|
-
const message = response.errorMessage ?? "Provider error";
|
|
54
|
-
if (!is_transient_error(message)) return response;
|
|
55
|
-
last_error = new Error(message);
|
|
56
|
-
} catch (err) {
|
|
57
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
58
|
-
if (options.signal?.aborted || !is_transient_error(message)) throw err;
|
|
59
|
-
last_error = err;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
throw last_error;
|
|
63
|
-
}
|
|
64
|
-
async function generate_session_name(ctx, model, conversation_text, signal) {
|
|
65
|
-
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
66
|
-
if (!auth.ok || !auth.apiKey && !auth.headers) throw new Error(auth.ok ? `No credentials for ${model.provider} (API key or OAuth login required)` : auth.error);
|
|
67
|
-
const user_message = {
|
|
68
|
-
role: "user",
|
|
69
|
-
content: [{
|
|
70
|
-
type: "text",
|
|
71
|
-
text: `## Conversation History\n\n${truncate_conversation(conversation_text)}\n\nGenerate a concise session name for this conversation.`
|
|
72
|
-
}],
|
|
73
|
-
timestamp: Date.now()
|
|
74
|
-
};
|
|
75
|
-
const response = await complete_with_retry(model, {
|
|
76
|
-
systemPrompt: SYSTEM_PROMPT,
|
|
77
|
-
messages: [user_message]
|
|
78
|
-
}, {
|
|
79
|
-
apiKey: auth.apiKey,
|
|
80
|
-
headers: auth.headers,
|
|
81
|
-
signal
|
|
82
|
-
});
|
|
83
|
-
if (response.stopReason === "aborted") return null;
|
|
84
|
-
if (response.stopReason === "error") throw new Error(response.errorMessage ?? `Provider error from ${model.provider}`);
|
|
85
|
-
return clean_name(response.content.filter((c) => c.type === "text").map((c) => c.text.trim()).join(" "));
|
|
86
|
-
}
|
|
87
|
-
async function session_name(pi) {
|
|
88
|
-
let auto_named_attempted = false;
|
|
89
|
-
pi.on("agent_end", async (_event, ctx) => {
|
|
90
|
-
if (!ctx.hasUI || !ctx.model) return;
|
|
91
|
-
if (pi.getSessionName() || auto_named_attempted) return;
|
|
92
|
-
const branch = ctx.sessionManager.getBranch();
|
|
93
|
-
if (branch.filter((entry) => entry.type === "message" && entry.message.role === "user").length < AUTO_NAME_THRESHOLD) return;
|
|
94
|
-
auto_named_attempted = true;
|
|
95
|
-
const messages = branch.filter((entry) => entry.type === "message").map((entry) => entry.message);
|
|
96
|
-
if (messages.length === 0) return;
|
|
97
|
-
const conversation_text = serializeConversation(convertToLlm(messages));
|
|
98
|
-
generate_session_name(ctx, ctx.model, conversation_text).then((name) => {
|
|
99
|
-
if (!name) return;
|
|
100
|
-
pi.setSessionName(name);
|
|
101
|
-
ctx.ui.notify(`Auto-named: ${name}`, "info");
|
|
102
|
-
}).catch((err) => {
|
|
103
|
-
console.error("Auto-naming failed:", err);
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
pi.on("session_start", async () => {
|
|
107
|
-
auto_named_attempted = false;
|
|
108
|
-
});
|
|
109
|
-
pi.registerCommand("session-name", {
|
|
110
|
-
description: "Set, show, or auto-generate the current session name",
|
|
111
|
-
handler: async (args, ctx) => {
|
|
112
|
-
const trimmed = args.trim();
|
|
113
|
-
if (!trimmed) {
|
|
114
|
-
const current = pi.getSessionName();
|
|
115
|
-
ctx.ui.notify(current ? `Session: ${current}` : "No session name set", "info");
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
if (trimmed === "--auto" || trimmed === "-a") {
|
|
119
|
-
if (!ctx.hasUI || !ctx.model) {
|
|
120
|
-
ctx.ui.notify("Auto-naming requires interactive mode and a selected model", "error");
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
const messages = ctx.sessionManager.getBranch().filter((entry) => entry.type === "message").map((entry) => entry.message);
|
|
124
|
-
if (messages.length === 0) {
|
|
125
|
-
ctx.ui.notify("No conversation to analyze", "error");
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
const conversation_text = serializeConversation(convertToLlm(messages));
|
|
129
|
-
const result = await ctx.ui.custom((tui, theme, _kb, done) => {
|
|
130
|
-
const loader = new BorderedLoader(tui, theme, "Generating session name...");
|
|
131
|
-
loader.onAbort = () => done(null);
|
|
132
|
-
generate_session_name(ctx, ctx.model, conversation_text, loader.signal).then(done).catch((err) => {
|
|
133
|
-
console.error("Auto-naming failed:", err);
|
|
134
|
-
done(null);
|
|
135
|
-
});
|
|
136
|
-
return loader;
|
|
137
|
-
});
|
|
138
|
-
if (result === null) {
|
|
139
|
-
ctx.ui.notify("Auto-naming cancelled", "info");
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
if (!result) {
|
|
143
|
-
ctx.ui.notify("Failed to generate name", "error");
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
pi.setSessionName(result);
|
|
147
|
-
ctx.ui.notify(`Session named: ${result}`, "info");
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
pi.setSessionName(clean_name(trimmed));
|
|
151
|
-
ctx.ui.notify(`Session named: ${clean_name(trimmed)}`, "info");
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
//#endregion
|
|
156
|
-
export { session_name as default };
|
|
157
|
-
|
|
158
|
-
//# sourceMappingURL=session-name-CD6TVRnh.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session-name-CD6TVRnh.js","names":[],"sources":["../src/extensions/session-name/index.ts"],"sourcesContent":["// Session name — AI-powered session naming\n// Adapted from Thomas Lopes' pi dotfiles\n\nimport { complete, type Message } from '@earendil-works/pi-ai/compat';\nimport type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tSessionEntry,\n} from '@earendil-works/pi-coding-agent';\nimport {\n\tBorderedLoader,\n\tconvertToLlm,\n\tserializeConversation,\n} from '@earendil-works/pi-coding-agent';\n\nconst SYSTEM_PROMPT = `You are a session naming assistant. Given a conversation history, generate a short, descriptive session name (2-5 words) that captures the main topic or task.\n\nGuidelines:\n- Be concise but specific\n- Use kebab-case only\n- Focus on the core task/question\n- Avoid generic names like \"discussion\" or \"conversation\"\n- No quotes, no punctuation at the end\n\nExamples:\n- \"fix auth bug\" -> \"fix-auth-bug\"\n- \"how do I deploy to vercel\" -> \"vercel-deployment\"\n- \"explain react hooks\" -> \"react-hooks-explanation\"\n- \"optimize database queries\" -> \"db-query-optimization\"\n\nOutput ONLY the session name, nothing else.`;\n\nconst AUTO_NAME_THRESHOLD = 1;\nconst MAX_CHARS = 4000;\nconst MAX_NAME_LEN = 50;\nconst MAX_ATTEMPTS = 3;\nconst RETRY_DELAYS_MS = [1_500, 4_000];\n\nexport function clean_name(value: string): string {\n\treturn value\n\t\t.replace(/^[\"']|[\"']$/g, '')\n\t\t.normalize('NFKD')\n\t\t.replace(/[\\u0300-\\u036f]/g, '')\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, '-')\n\t\t.replace(/^-+|-+$/g, '')\n\t\t.slice(0, MAX_NAME_LEN)\n\t\t.replace(/-+$/g, '');\n}\n\nfunction truncate_conversation(value: string): string {\n\treturn value.length > MAX_CHARS\n\t\t? value.slice(0, MAX_CHARS) + '\\n...'\n\t\t: value;\n}\n\nexport function is_transient_error(message: string): boolean {\n\treturn (\n\t\t/\\b(429|500|502|503|529)\\b/.test(message) ||\n\t\t/overload|rate.?limit|temporarily unavailable|try again/i.test(\n\t\t\tmessage,\n\t\t)\n\t);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve) => {\n\t\tconst timer = setTimeout(resolve, ms);\n\t\tsignal?.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve();\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t});\n}\n\nasync function complete_with_retry(\n\tmodel: Parameters<typeof complete>[0],\n\tcontext: Parameters<typeof complete>[1],\n\toptions: NonNullable<Parameters<typeof complete>[2]>,\n): Promise<Awaited<ReturnType<typeof complete>>> {\n\tlet last_error: unknown = new Error('Unknown provider error');\n\tfor (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {\n\t\tif (attempt > 0) {\n\t\t\tawait sleep(RETRY_DELAYS_MS[attempt - 1], options.signal);\n\t\t\tif (options.signal?.aborted) break;\n\t\t}\n\t\ttry {\n\t\t\tconst response = await complete(model, context, options);\n\t\t\tif (response.stopReason !== 'error') return response;\n\t\t\tconst message = response.errorMessage ?? 'Provider error';\n\t\t\tif (!is_transient_error(message)) return response;\n\t\t\tlast_error = new Error(message);\n\t\t} catch (err) {\n\t\t\tconst message =\n\t\t\t\terr instanceof Error ? err.message : String(err);\n\t\t\tif (options.signal?.aborted || !is_transient_error(message)) {\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t\tlast_error = err;\n\t\t}\n\t}\n\tthrow last_error;\n}\n\nasync function generate_session_name(\n\tctx: Pick<ExtensionCommandContext, 'modelRegistry'>,\n\tmodel: NonNullable<\n\t\tParameters<\n\t\t\tParameters<ExtensionAPI['registerCommand']>[1]['handler']\n\t\t>[1]['model']\n\t>,\n\tconversation_text: string,\n\tsignal?: AbortSignal,\n): Promise<string | null> {\n\tconst auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);\n\tif (!auth.ok || (!auth.apiKey && !auth.headers)) {\n\t\tthrow new Error(\n\t\t\tauth.ok\n\t\t\t\t? `No credentials for ${model.provider} (API key or OAuth login required)`\n\t\t\t\t: auth.error,\n\t\t);\n\t}\n\n\tconst user_message: Message = {\n\t\trole: 'user',\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: 'text',\n\t\t\t\ttext: `## Conversation History\\n\\n${truncate_conversation(conversation_text)}\\n\\nGenerate a concise session name for this conversation.`,\n\t\t\t},\n\t\t],\n\t\ttimestamp: Date.now(),\n\t};\n\n\tconst response = await complete_with_retry(\n\t\tmodel,\n\t\t{ systemPrompt: SYSTEM_PROMPT, messages: [user_message] },\n\t\t{ apiKey: auth.apiKey, headers: auth.headers, signal },\n\t);\n\n\tif (response.stopReason === 'aborted') {\n\t\treturn null;\n\t}\n\n\tif (response.stopReason === 'error') {\n\t\tthrow new Error(\n\t\t\tresponse.errorMessage ??\n\t\t\t\t`Provider error from ${model.provider}`,\n\t\t);\n\t}\n\n\treturn clean_name(\n\t\tresponse.content\n\t\t\t.filter(\n\t\t\t\t(c): c is { type: 'text'; text: string } => c.type === 'text',\n\t\t\t)\n\t\t\t.map((c) => c.text.trim())\n\t\t\t.join(' '),\n\t);\n}\n\nexport default async function session_name(pi: ExtensionAPI) {\n\tlet auto_named_attempted = false;\n\n\tpi.on('agent_end', async (_event, ctx) => {\n\t\tif (!ctx.hasUI || !ctx.model) return;\n\t\tif (pi.getSessionName() || auto_named_attempted) return;\n\n\t\tconst branch = ctx.sessionManager.getBranch();\n\t\tconst user_messages = branch.filter(\n\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\tentry.type === 'message' && entry.message.role === 'user',\n\t\t);\n\t\tif (user_messages.length < AUTO_NAME_THRESHOLD) return;\n\n\t\tauto_named_attempted = true;\n\t\tconst messages = branch\n\t\t\t.filter(\n\t\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\t\tentry.type === 'message',\n\t\t\t)\n\t\t\t.map((entry) => entry.message);\n\t\tif (messages.length === 0) return;\n\n\t\tconst conversation_text = serializeConversation(\n\t\t\tconvertToLlm(messages),\n\t\t);\n\n\t\tgenerate_session_name(ctx, ctx.model, conversation_text)\n\t\t\t.then((name) => {\n\t\t\t\tif (!name) return;\n\t\t\t\tpi.setSessionName(name);\n\t\t\t\tctx.ui.notify(`Auto-named: ${name}`, 'info');\n\t\t\t})\n\t\t\t.catch((err) => {\n\t\t\t\tconsole.error('Auto-naming failed:', err);\n\t\t\t});\n\t});\n\n\tpi.on('session_start', async () => {\n\t\tauto_named_attempted = false;\n\t});\n\n\tpi.registerCommand('session-name', {\n\t\tdescription:\n\t\t\t'Set, show, or auto-generate the current session name',\n\t\thandler: async (args, ctx) => {\n\t\t\tconst trimmed = args.trim();\n\n\t\t\tif (!trimmed) {\n\t\t\t\tconst current = pi.getSessionName();\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\tcurrent ? `Session: ${current}` : 'No session name set',\n\t\t\t\t\t'info',\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (trimmed === '--auto' || trimmed === '-a') {\n\t\t\t\tif (!ctx.hasUI || !ctx.model) {\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t'Auto-naming requires interactive mode and a selected model',\n\t\t\t\t\t\t'error',\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst branch = ctx.sessionManager.getBranch();\n\t\t\t\tconst messages = branch\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(entry): entry is SessionEntry & { type: 'message' } =>\n\t\t\t\t\t\t\tentry.type === 'message',\n\t\t\t\t\t)\n\t\t\t\t\t.map((entry) => entry.message);\n\t\t\t\tif (messages.length === 0) {\n\t\t\t\t\tctx.ui.notify('No conversation to analyze', 'error');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst conversation_text = serializeConversation(\n\t\t\t\t\tconvertToLlm(messages),\n\t\t\t\t);\n\n\t\t\t\tconst result = await ctx.ui.custom<string | null>(\n\t\t\t\t\t(tui, theme, _kb, done) => {\n\t\t\t\t\t\tconst loader = new BorderedLoader(\n\t\t\t\t\t\t\ttui,\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\t'Generating session name...',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tloader.onAbort = () => done(null);\n\n\t\t\t\t\t\tgenerate_session_name(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\tctx.model!,\n\t\t\t\t\t\t\tconversation_text,\n\t\t\t\t\t\t\tloader.signal,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.then(done)\n\t\t\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\t\t\tconsole.error('Auto-naming failed:', err);\n\t\t\t\t\t\t\t\tdone(null);\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn loader;\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (result === null) {\n\t\t\t\t\tctx.ui.notify('Auto-naming cancelled', 'info');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!result) {\n\t\t\t\t\tctx.ui.notify('Failed to generate name', 'error');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tpi.setSessionName(result);\n\t\t\t\tctx.ui.notify(`Session named: ${result}`, 'info');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tpi.setSessionName(clean_name(trimmed));\n\t\t\tctx.ui.notify(`Session named: ${clean_name(trimmed)}`, 'info');\n\t\t},\n\t});\n}\n"],"mappings":"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"}
|