lsd-pi 1.1.9 → 1.2.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/dist/resources/extensions/slash-commands/context.js +15 -8
- package/dist/resources/extensions/slash-commands/index.js +2 -0
- package/dist/resources/extensions/slash-commands/init.js +47 -0
- package/dist/resources/extensions/slash-commands/plan.js +241 -54
- package/dist/resources/extensions/slash-commands/tools.js +47 -21
- package/dist/resources/extensions/subagent/index.js +5 -10
- package/dist/startup-model-validation.d.ts +1 -1
- package/package.json +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +2 -1
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/src/types.ts +2 -1
- package/packages/pi-ai/dist/providers/amazon-bedrock.js +10 -3
- package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +4 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts +2 -2
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +2 -2
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.js +2 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.js +2 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-vertex.js +2 -0
- package/packages/pi-ai/dist/providers/google-vertex.js.map +1 -1
- package/packages/pi-ai/dist/providers/google.js +2 -0
- package/packages/pi-ai/dist/providers/google.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +2 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +2 -1
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js +2 -1
- package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.d.ts +1 -1
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +6 -2
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +1 -1
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/src/providers/amazon-bedrock.ts +11 -4
- package/packages/pi-ai/src/providers/anthropic-shared.ts +5 -2
- package/packages/pi-ai/src/providers/anthropic.ts +2 -2
- package/packages/pi-ai/src/providers/azure-openai-responses.ts +2 -1
- package/packages/pi-ai/src/providers/google-gemini-cli.ts +3 -1
- package/packages/pi-ai/src/providers/google-vertex.ts +3 -1
- package/packages/pi-ai/src/providers/google.ts +3 -1
- package/packages/pi-ai/src/providers/openai-codex-responses.ts +2 -1
- package/packages/pi-ai/src/providers/openai-completions.ts +2 -1
- package/packages/pi-ai/src/providers/openai-responses.ts +2 -1
- package/packages/pi-ai/src/providers/simple-options.ts +5 -3
- package/packages/pi-ai/src/types.ts +1 -1
- package/packages/pi-coding-agent/dist/cli/args.js +1 -1
- package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +57 -20
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/classifier-service.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/classifier-service.js +34 -61
- package/packages/pi-coding-agent/dist/core/classifier-service.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/utils.js +3 -1
- package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader-lsd-md.test.js +59 -7
- package/packages/pi-coding-agent/dist/core/resource-loader-lsd-md.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +4 -4
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +19 -20
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.js +80 -0
- package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +15 -5
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +31 -5
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +28 -68
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash-interceptor.js +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash-interceptor.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash-interceptor.test.js +5 -0
- package/packages/pi-coding-agent/dist/core/tools/bash-interceptor.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +28 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +8 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +44 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/thinking-selector.js +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +36 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +41 -5
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/cli/args.ts +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +62 -19
- package/packages/pi-coding-agent/src/core/classifier-service.ts +35 -63
- package/packages/pi-coding-agent/src/core/compaction/utils.ts +3 -1
- package/packages/pi-coding-agent/src/core/resource-loader-lsd-md.test.ts +67 -7
- package/packages/pi-coding-agent/src/core/resource-loader.ts +4 -4
- package/packages/pi-coding-agent/src/core/sdk.test.ts +100 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +24 -21
- package/packages/pi-coding-agent/src/core/settings-manager.ts +42 -8
- package/packages/pi-coding-agent/src/core/system-prompt.ts +39 -82
- package/packages/pi-coding-agent/src/core/tools/bash-interceptor.test.ts +6 -0
- package/packages/pi-coding-agent/src/core/tools/bash-interceptor.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +26 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +53 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/thinking-selector.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +41 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +50 -7
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +3 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.js +2 -0
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/slash-commands/context.ts +15 -8
- package/src/resources/extensions/slash-commands/index.ts +2 -0
- package/src/resources/extensions/slash-commands/init.ts +55 -0
- package/src/resources/extensions/slash-commands/plan.ts +277 -55
- package/src/resources/extensions/slash-commands/tools.ts +47 -21
- package/src/resources/extensions/subagent/index.ts +5 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.js\";\nimport { toPosixPath } from \"../utils/path-display.js\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.js\";\n\n/** Tool descriptions for system prompt */\nconst toolDescriptions: Record<string, string> = {\n\tread: \"Read file contents\",\n\tbash: \"Execute bash commands (ls, grep, find, etc.)\",\n\tedit: \"Make surgical edits to files (find exact text and replace)\",\n\twrite: \"Create or overwrite files\",\n\tgrep: \"Search file contents for patterns (respects .gitignore). For symbol definitions, references, type info, or callers in code, use lsp instead\",\n\tfind: \"Find files by glob pattern (respects .gitignore)\",\n\tls: \"List directory contents\",\n\tlsp: \"Code intelligence via Language Server Protocol (go-to-definition, references, diagnostics, hover, rename, symbols)\",\n};\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. Default: process.cwd() */\n\tcwd?: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions = {}): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t} = options;\n\tconst resolvedCwd = toPosixPath(cwd ?? process.cwd());\n\n\tconst now = new Date();\n\tconst dateTime = now.toLocaleString(\"en-US\", {\n\t\tweekday: \"long\",\n\t\tyear: \"numeric\",\n\t\tmonth: \"long\",\n\t\tday: \"numeric\",\n\t\thour: \"2-digit\",\n\t\tminute: \"2-digit\",\n\t\tsecond: \"2-digit\",\n\t\ttimeZoneName: \"short\",\n\t});\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Append skills section (if read or Skill tool is available)\n\t\tconst customPromptHasSkillAccess = !selectedTools || selectedTools.includes(\"read\") || selectedTools.includes(\"Skill\");\n\t\tif (customPromptHasSkillAccess && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\n\t\t// Add date/time and working directory last\n\t\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\t\tprompt += `\\nCurrent working directory: ${resolvedCwd}`;\n\n\t\t// Append promptGuidelines from extension-registered tools.\n\t\t// Without this, tools registered via pi.registerTool() with promptGuidelines\n\t\t// have their definitions reach the API but the model has no guidance on when\n\t\t// to use them (#1184).\n\t\tif (promptGuidelines && promptGuidelines.length > 0) {\n\t\t\tprompt += \"\\n\\n\";\n\t\t\tfor (const guideline of promptGuidelines) {\n\t\t\t\tprompt += guideline + \"\\n\";\n\t\t\t}\n\t\t}\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\n\t// Build tools list based on selected tools.\n\t// Built-ins use toolDescriptions. Custom tools can provide one-line snippets.\n\tconst tools = selectedTools || [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst toolsList =\n\t\ttools.length > 0\n\t\t\t? tools\n\t\t\t\t\t.map((name) => {\n\t\t\t\t\t\tconst snippet = toolSnippets?.[name] ?? toolDescriptions[name] ?? name;\n\t\t\t\t\t\treturn `- ${name}: ${snippet}`;\n\t\t\t\t\t})\n\t\t\t\t\t.join(\"\\n\")\n\t\t\t: \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasEdit = tools.includes(\"edit\");\n\tconst hasWrite = tools.includes(\"write\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\tconst hasLsp = tools.includes(\"lsp\");\n\n\t// LSP guideline — must come FIRST so it outranks grep/bash in the model's priority\n\tif (hasLsp) {\n\t\taddGuideline(\n\t\t\t`Use lsp as the primary tool for code navigation in typed codebases:\n- Navigation: definition, type_definition, implementation, references, incoming_calls, outgoing_calls\n- Understanding: hover (types + docs), signature (parameter info), symbols (file/workspace search)\n- Refactoring: rename (project-wide), code_actions (quick-fixes, imports, refactors), format (formatter)\n- Verification: diagnostics after edits to catch type errors immediately\n- Before choosing a code-navigation tool, classify your intent: symbol lookup (definition, references, type info, callers, rename, formatting, diagnostics) or text search. Symbols → lsp. Text patterns / non-code files → grep/find/ls\n- Tool selection — code navigation:\n • Find where a symbol is defined → lsp definition (not grep)\n • Find all usages of a symbol → lsp references (not grep)\n • Find implementations of an interface or method → lsp implementation (not grep)\n • Get type info or docs for a symbol → lsp hover/signature (not reading source first)\n • Find all callers of a function → lsp incoming_calls (not grep)\n • Search for a text pattern, TODO, log message, or non-code content → grep\n • Search for filenames or directory structure → find/ls\n • Rename a symbol across the codebase → lsp rename (not find-and-replace)\n • Check typed errors after edits → lsp diagnostics (not manual scans)\n • Format a file → lsp format when available (not shelling out)\n- When lsp is available, ALWAYS prefer it over grep/bash/find for: finding definitions, finding references, getting type info, renaming symbols, listing symbols in a file or workspace, checking diagnostics/errors, and formatting\n- Never grep for a symbol definition when lsp can resolve it semantically\n- Never shell out to a formatter when lsp format is available`,\n\t\t);\n\t}\n\n\t// If the request is primarily conceptual or product/design oriented, answer the design or strategy question first and inspect the codebase only after confirming implementation detail is needed.\n\taddGuideline(\n\t\t\"If the request is primarily conceptual, product, or UX/design oriented, answer the question first with concise recommendations and inspect the codebase only after confirming implementation detail is needed\",\n\t);\n\n\t// Use subagents for broad reconnaissance before spending expensive-model tokens on discovery\n\tif (tools.includes(\"subagent\")) {\n\t\taddGuideline(\n\t\t\t\"Use a scout subagent for broad repo reconnaissance when file ownership or architecture is unclear; keep the scout read-only, use a cheaper model when available, and ask it to return a high-signal handoff with exact files/symbols to inspect next\",\n\t\t);\n\t}\n\n\taddGuideline(\n\t\t\"Do not deep-dive backend schemas, migrations, or infrastructure for a conceptual/product request until you confirm that implementation constraints actually matter\",\n\t);\n\n\t// File exploration guidelines (only for tasks lsp cannot do: raw text search, non-code files, etc.)\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use bash for file operations like ls, rg, find\");\n\t} else if (hasBash && (hasGrep || hasFind || hasLs)) {\n\t\tif (hasLsp) {\n\t\t\taddGuideline(\"Prefer grep/find/ls tools over bash for file exploration (faster, respects .gitignore) — but prefer lsp over grep/find when navigating typed code\");\n\t\t} else {\n\t\t\taddGuideline(\"Prefer grep/find/ls tools over bash for file exploration (faster, respects .gitignore)\");\n\t\t}\n\t}\n\n\t// Read before edit guideline\n\tif (hasRead && hasEdit) {\n\t\taddGuideline(\"Use read to examine files before editing. You must use this tool instead of cat or sed.\");\n\t}\n\n\t// Edit guideline\n\tif (hasEdit) {\n\t\taddGuideline(\"Use edit for precise changes (old text must match exactly)\");\n\t}\n\n\t// Write guideline\n\tif (hasWrite) {\n\t\taddGuideline(\"Use write only for new files or complete rewrites\");\n\t}\n\n\t// Output guideline (only when actually writing or executing)\n\tif (hasEdit || hasWrite) {\n\t\taddGuideline(\n\t\t\t\"When summarizing your actions, output plain text directly - do NOT use cat or bash to display what you did\",\n\t\t);\n\t}\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\t// Always include these\n\taddGuideline(\"Be concise in your responses\");\n\taddGuideline(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant operating inside pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n\nGuidelines:\n${guidelines}\n\nPi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md)\n- When working on pi topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Append skills section (if read or Skill tool is available)\n\tconst hasSkill = tools.includes(\"Skill\");\n\tif ((hasRead || hasSkill) && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\n\t// Add date/time and working directory last\n\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\tprompt += `\\nCurrent working directory: ${resolvedCwd}`;\n\n\treturn prompt;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { existsSync } from \"node:fs\";\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.js\";\nimport { toPosixPath } from \"../utils/path-display.js\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.js\";\n\n/** Tool descriptions for system prompt */\nconst toolDescriptions: Record<string, string> = {\n\tread: \"Read file contents\",\n\tbash: \"Execute bash commands (ls, grep, find, etc.)\",\n\tedit: \"Make surgical edits to files (find exact text and replace)\",\n\twrite: \"Create or overwrite files\",\n\tgrep: \"Search file contents for patterns (respects .gitignore). For symbol definitions, references, type info, or callers in code, use lsp instead\",\n\tfind: \"Find files by glob pattern (respects .gitignore)\",\n\tls: \"List directory contents\",\n\tlsp: \"Code intelligence via Language Server Protocol (go-to-definition, references, diagnostics, hover, rename, symbols)\",\n};\n\nexport interface BuildSystemPromptOptions {\n\t/**\n\t * Custom system prompt that replaces the default role header, tool list,\n\t * and guidelines entirely. You are responsible for providing your own\n\t * tool-usage guidance. Project context, skills, extension promptGuidelines,\n\t * date/cwd, and appendSystemPrompt are still applied on top.\n\t */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. Default: process.cwd() */\n\tcwd?: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions = {}): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t} = options;\n\tconst resolvedCwd = toPosixPath(cwd ?? process.cwd());\n\n\tconst now = new Date();\n\tconst dateTime = now.toLocaleString(\"en-US\", {\n\t\tweekday: \"long\",\n\t\tyear: \"numeric\",\n\t\tmonth: \"long\",\n\t\tday: \"numeric\",\n\t\thour: \"2-digit\",\n\t\tminute: \"2-digit\",\n\t\tsecond: \"2-digit\",\n\t\ttimeZoneName: \"short\",\n\t});\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Append skills section (if read or Skill tool is available)\n\t\tconst customPromptHasSkillAccess = !selectedTools || selectedTools.includes(\"read\") || selectedTools.includes(\"Skill\");\n\t\tif (customPromptHasSkillAccess && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\n\t\t// Append promptGuidelines from extension-registered tools.\n\t\t// Without this, tools registered via pi.registerTool() with promptGuidelines\n\t\t// have their definitions reach the API but the model has no guidance on when\n\t\t// to use them (#1184).\n\t\tif (promptGuidelines && promptGuidelines.length > 0) {\n\t\t\tprompt += \"\\n\\n\";\n\t\t\tfor (const guideline of promptGuidelines) {\n\t\t\t\tprompt += guideline + \"\\n\";\n\t\t\t}\n\t\t}\n\n\t\t// Add date/time and working directory last\n\t\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\t\tprompt += `\\nCurrent working directory: ${resolvedCwd}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\n\t// Build tools list based on selected tools.\n\t// Built-ins use toolDescriptions. Custom tools can provide one-line snippets.\n\tconst tools = selectedTools || [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst toolsList =\n\t\ttools.length > 0\n\t\t\t? tools\n\t\t\t\t\t.map((name) => {\n\t\t\t\t\t\tconst snippet = toolSnippets?.[name] ?? toolDescriptions[name] ?? name;\n\t\t\t\t\t\treturn `- ${name}: ${snippet}`;\n\t\t\t\t\t})\n\t\t\t\t\t.join(\"\\n\")\n\t\t\t: \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasEdit = tools.includes(\"edit\");\n\tconst hasWrite = tools.includes(\"write\");\n\tconst hasRead = tools.includes(\"read\");\n\tconst hasLsp = tools.includes(\"lsp\");\n\n\t// Priority-ordered compact guidelines\n\taddGuideline(\"Be concise. Prefer short, direct answers over preamble.\");\n\taddGuideline(\"For conceptual, product, or UX questions, answer first; inspect code only if implementation detail is needed.\");\n\n\tif (hasLsp) {\n\t\taddGuideline(\n\t\t\t\"Code navigation in typed codebases: use lsp for symbols (definition, references, implementation, hover, diagnostics, rename, format). Use grep/find/ls for text patterns, filenames, and non-code files.\",\n\t\t);\n\t} else {\n\t\taddGuideline(\"Use grep/find/ls for code search and file exploration (faster than bash, respects .gitignore)\");\n\t}\n\n\tif (hasRead && hasEdit) {\n\t\taddGuideline(\"Read files before editing them. Never use cat or sed to inspect or modify files.\");\n\t}\n\n\tif (hasEdit) {\n\t\taddGuideline(\"edit requires exact text match; write is for new files or full rewrites.\");\n\t}\n\n\tif (hasWrite && !hasEdit) {\n\t\taddGuideline(\"write is for new files or full rewrites.\");\n\t}\n\n\tif (hasLsp && hasEdit) {\n\t\taddGuideline(\"Run lsp diagnostics after edits to catch type errors.\");\n\t}\n\n\tif (hasEdit || hasWrite) {\n\t\taddGuideline(\"Output plain text directly when summarizing your work — do not cat or echo to display what you did.\");\n\t}\n\n\taddGuideline(\"Show file paths clearly when referencing files.\");\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tconst piDocsBlock = existsSync(readmePath)\n\t\t? `\\n\\nPi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- When working on pi topics, read the docs and follow .md cross-references before implementing`\n\t\t: \"\";\n\n\tlet prompt = `You are an expert coding assistant operating inside pi, a coding agent harness.\n\nAvailable tools:\n${toolsList}\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n\nGuidelines:\n${guidelines}${piDocsBlock}`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Append skills section (if read or Skill tool is available)\n\tconst hasSkill = tools.includes(\"Skill\");\n\tif ((hasRead || hasSkill) && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\n\t// Add date/time and working directory last\n\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\tprompt += `\\nCurrent working directory: ${resolvedCwd}`;\n\n\treturn prompt;\n}\n"]}
|
|
@@ -67,7 +67,7 @@ export function compileInterceptor(rules) {
|
|
|
67
67
|
if (regex.test(trimmed) && availableTools.includes(rule.tool)) {
|
|
68
68
|
return {
|
|
69
69
|
block: true,
|
|
70
|
-
message: `
|
|
70
|
+
message: `Tool routing: ${rule.message}\n\nThis is a routing suggestion, not a permission block. Use the suggested tool to perform this action.\n\nOriginal command: ${command}`,
|
|
71
71
|
suggestedTool: rule.tool,
|
|
72
72
|
};
|
|
73
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash-interceptor.js","sourceRoot":"","sources":["../../../src/core/tools/bash-interceptor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,CAAC,MAAM,8BAA8B,GAA0B;IACpE;QACC,oEAAoE;QACpE,OAAO,EAAE,8CAA8C;QACvD,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,oEAAoE;KAC7E;IACD;QACC,OAAO,EAAE,mCAAmC;QAC5C,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,0EAA0E;KACnF;IACD;QACC,OAAO,EAAE,8DAA8D;QACvE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,8EAA8E;KACvF;IACD;QACC,OAAO,EAAE,6BAA6B;QACtC,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,mEAAmE;KAC5E;IACD;QACC,OAAO,EAAE,wBAAwB;QACjC,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,oEAAoE;KAC7E;IACD;QACC,OAAO,EAAE,6BAA6B;QACtC,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,mEAAmE;KAC5E;IACD;QACC,sFAAsF;QACtF,4EAA4E;QAC5E,OAAO,EAAE,6DAA6D;QACtE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,0EAA0E;KACnF;CACD,CAAC;AAYF;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA4B;IAC9D,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACvC,IAAI,CAAC;YACJ,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,EAAE,CAAC,CAAC,qBAAqB;QACjC,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,OAAO;QACN,KAAK,CAAC,OAAe,EAAE,cAAwB;YAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/B,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,QAAQ,EAAE,CAAC;gBACxC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/D,OAAO;wBACN,KAAK,EAAE,IAAI;wBACX,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"bash-interceptor.js","sourceRoot":"","sources":["../../../src/core/tools/bash-interceptor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,CAAC,MAAM,8BAA8B,GAA0B;IACpE;QACC,oEAAoE;QACpE,OAAO,EAAE,8CAA8C;QACvD,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,oEAAoE;KAC7E;IACD;QACC,OAAO,EAAE,mCAAmC;QAC5C,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,0EAA0E;KACnF;IACD;QACC,OAAO,EAAE,8DAA8D;QACvE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,8EAA8E;KACvF;IACD;QACC,OAAO,EAAE,6BAA6B;QACtC,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,mEAAmE;KAC5E;IACD;QACC,OAAO,EAAE,wBAAwB;QACjC,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,oEAAoE;KAC7E;IACD;QACC,OAAO,EAAE,6BAA6B;QACtC,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,mEAAmE;KAC5E;IACD;QACC,sFAAsF;QACtF,4EAA4E;QAC5E,OAAO,EAAE,6DAA6D;QACtE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,0EAA0E;KACnF;CACD,CAAC;AAYF;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA4B;IAC9D,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACvC,IAAI,CAAC;YACJ,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,EAAE,CAAC,CAAC,qBAAqB;QACjC,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,OAAO;QACN,KAAK,CAAC,OAAe,EAAE,cAAwB;YAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/B,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,QAAQ,EAAE,CAAC;gBACxC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/D,OAAO;wBACN,KAAK,EAAE,IAAI;wBACX,OAAO,EAAE,iBAAiB,IAAI,CAAC,OAAO,iIAAiI,OAAO,EAAE;wBAChL,aAAa,EAAE,IAAI,CAAC,IAAI;qBACxB,CAAC;gBACH,CAAC;YACF,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACzB,CAAC;KACD,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACpC,OAAe,EACf,cAAwB,EACxB,KAA6B;IAE7B,MAAM,cAAc,GAAG,KAAK,IAAI,8BAA8B,CAAC;IAC/D,OAAO,kBAAkB,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;AAC1E,CAAC","sourcesContent":["/**\n * Bash command interceptor — blocks shell commands that duplicate dedicated tools.\n *\n * Each rule defines a regex pattern, a suggested replacement tool, and a message.\n * A command is only blocked when the suggested tool exists in the session's active tool list.\n */\n\nexport interface BashInterceptorRule {\n\tpattern: string;\n\tflags?: string;\n\ttool: string;\n\tmessage: string;\n}\n\nexport const DEFAULT_BASH_INTERCEPTOR_RULES: BashInterceptorRule[] = [\n\t{\n\t\t// cat/head/tail for file viewing — excludes heredoc syntax (cat <<)\n\t\tpattern: \"^\\\\s*(cat(?!\\\\s*<<)|head|tail|less|more)\\\\s+\",\n\t\ttool: \"read\",\n\t\tmessage: \"Use the read tool to view file contents instead of shell commands.\",\n\t},\n\t{\n\t\tpattern: \"^\\\\s*(grep|rg|ripgrep|ag|ack)\\\\s+\",\n\t\ttool: \"grep\",\n\t\tmessage: \"Use the grep tool for searching file contents instead of shell commands.\",\n\t},\n\t{\n\t\tpattern: \"^\\\\s*(find|fd|locate)\\\\s+.*(-name|-iname|-type|--type|-glob)\",\n\t\ttool: \"find\",\n\t\tmessage: \"Use the find tool for locating files by name/type instead of shell commands.\",\n\t},\n\t{\n\t\tpattern: \"^\\\\s*sed\\\\s+(-i|--in-place)\",\n\t\ttool: \"edit\",\n\t\tmessage: \"Use the edit tool for in-place file modifications instead of sed.\",\n\t},\n\t{\n\t\tpattern: \"^\\\\s*perl\\\\s+.*-[pn]?i\",\n\t\ttool: \"edit\",\n\t\tmessage: \"Use the edit tool for in-place file modifications instead of perl.\",\n\t},\n\t{\n\t\tpattern: \"^\\\\s*awk\\\\s+.*-i\\\\s+inplace\",\n\t\ttool: \"edit\",\n\t\tmessage: \"Use the edit tool for in-place file modifications instead of awk.\",\n\t},\n\t{\n\t\t// echo/printf/heredoc writing to a file via > (not >> append, not 2> stderr redirect)\n\t\t// Matches a single > not preceded by |, >, or a digit (fd redirect like 2>)\n\t\tpattern: \"^\\\\s*(echo|printf|cat\\\\s*<<)\\\\s+.*(?<![|>\\\\d])>(?!>)\\\\s*\\\\S\",\n\t\ttool: \"write\",\n\t\tmessage: \"Use the write tool to create/overwrite files instead of shell redirects.\",\n\t},\n];\n\nexport interface InterceptionResult {\n\tblock: boolean;\n\tmessage?: string;\n\tsuggestedTool?: string;\n}\n\nexport interface CompiledInterceptor {\n\tcheck: (command: string, availableTools: string[]) => InterceptionResult;\n}\n\n/**\n * Compile rules into an interceptor with pre-built regex objects.\n * Silently skips rules with invalid patterns.\n *\n * Pre-compiling at construction time avoids repeated `new RegExp()` calls\n * on every bash command invocation.\n */\nexport function compileInterceptor(rules: BashInterceptorRule[]): CompiledInterceptor {\n\tconst compiled = rules.flatMap((rule) => {\n\t\ttry {\n\t\t\treturn [{ regex: new RegExp(rule.pattern, rule.flags), rule }];\n\t\t} catch {\n\t\t\treturn []; // skip invalid regex\n\t\t}\n\t});\n\n\treturn {\n\t\tcheck(command: string, availableTools: string[]): InterceptionResult {\n\t\t\tconst trimmed = command.trim();\n\t\t\tfor (const { regex, rule } of compiled) {\n\t\t\t\tif (regex.test(trimmed) && availableTools.includes(rule.tool)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tblock: true,\n\t\t\t\t\t\tmessage: `Tool routing: ${rule.message}\\n\\nThis is a routing suggestion, not a permission block. Use the suggested tool to perform this action.\\n\\nOriginal command: ${command}`,\n\t\t\t\t\t\tsuggestedTool: rule.tool,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { block: false };\n\t\t},\n\t};\n}\n\n/**\n * Check whether a bash command should be intercepted.\n *\n * Compiles rules on each call — prefer `compileInterceptor()` for repeated use.\n *\n * @param command - The shell command to check\n * @param availableTools - Tool names present in the current session\n * @param rules - Override the default rule set (optional)\n */\nexport function checkBashInterception(\n\tcommand: string,\n\tavailableTools: string[],\n\trules?: BashInterceptorRule[],\n): InterceptionResult {\n\tconst effectiveRules = rules ?? DEFAULT_BASH_INTERCEPTOR_RULES;\n\treturn compileInterceptor(effectiveRules).check(command, availableTools);\n}\n"]}
|
|
@@ -110,6 +110,11 @@ describe("checkBashInterception", () => {
|
|
|
110
110
|
const r = checkBashInterception("cat README.md", ALL_TOOLS);
|
|
111
111
|
assert.ok(r.message?.includes("cat README.md"), "message should contain original command");
|
|
112
112
|
});
|
|
113
|
+
it("uses 'Tool routing:' prefix to distinguish from permission blocks", () => {
|
|
114
|
+
const r = checkBashInterception("cat README.md", ALL_TOOLS);
|
|
115
|
+
assert.ok(r.message?.startsWith("Tool routing:"), "message should start with 'Tool routing:'");
|
|
116
|
+
assert.ok(r.message?.includes("not a permission block"), "message should clarify it's not a permission block");
|
|
117
|
+
});
|
|
113
118
|
it("returns block:false with no message when not blocked", () => {
|
|
114
119
|
const r = checkBashInterception("npm install", ALL_TOOLS);
|
|
115
120
|
assert.equal(r.block, false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash-interceptor.test.js","sourceRoot":"","sources":["../../../src/core/tools/bash-interceptor.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport {\n\tcheckBashInterception,\n\tcompileInterceptor,\n\tDEFAULT_BASH_INTERCEPTOR_RULES,\n\ttype BashInterceptorRule,\n} from \"./bash-interceptor.js\";\n\nconst ALL_TOOLS = [\"read\", \"grep\", \"find\", \"edit\", \"write\"];\nconst NO_TOOLS: string[] = [];\n\ndescribe(\"checkBashInterception\", () => {\n\tdescribe(\"read rule (cat/head/tail/less/more)\", () => {\n\t\tit(\"blocks cat with a file argument\", () => {\n\t\t\tconst r = checkBashInterception(\"cat README.md\", ALL_TOOLS);\n\t\t\tassert.equal(r.block, true);\n\t\t\tassert.equal(r.suggestedTool, \"read\");\n\t\t});\n\n\t\tit(\"blocks head and tail\", () => {\n\t\t\tassert.equal(checkBashInterception(\"head -n 20 file.ts\", ALL_TOOLS).block, true);\n\t\t\tassert.equal(checkBashInterception(\"tail -f app.log\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"does NOT block cat used as heredoc (cat <<EOF)\", () => {\n\t\t\tconst r = checkBashInterception(\"cat <<EOF > file.txt\", ALL_TOOLS);\n\t\t\tassert.notEqual(r.suggestedTool, \"read\");\n\t\t});\n\n\t\tit(\"does NOT block when read tool is absent\", () => {\n\t\t\tassert.equal(checkBashInterception(\"cat README.md\", NO_TOOLS).block, false);\n\t\t\tassert.equal(checkBashInterception(\"cat README.md\", [\"grep\"]).block, false);\n\t\t});\n\t});\n\n\tdescribe(\"grep rule\", () => {\n\t\tit(\"blocks grep and rg\", () => {\n\t\t\tassert.equal(checkBashInterception(\"grep foo bar.ts\", ALL_TOOLS).block, true);\n\t\t\tassert.equal(checkBashInterception(\"rg -r pattern .\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"blocks grep with leading whitespace\", () => {\n\t\t\tassert.equal(checkBashInterception(\" grep -r foo .\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"does NOT block when grep tool is absent\", () => {\n\t\t\tassert.equal(checkBashInterception(\"grep foo bar\", [\"read\", \"edit\"]).block, false);\n\t\t});\n\t});\n\n\tdescribe(\"find rule\", () => {\n\t\tit(\"blocks find with -name flag\", () => {\n\t\t\tassert.equal(checkBashInterception('find . -name \"*.ts\"', ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"blocks find with -type flag\", () => {\n\t\t\tassert.equal(checkBashInterception(\"find /tmp -maxdepth 1 -type f\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"does NOT block find without name/type flags\", () => {\n\t\t\tassert.equal(checkBashInterception(\"find /tmp -maxdepth 1\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"does NOT block when find tool is absent\", () => {\n\t\t\tassert.equal(checkBashInterception('find . -name \"*.ts\"', [\"read\", \"grep\"]).block, false);\n\t\t});\n\t});\n\n\tdescribe(\"edit rule (sed/perl/awk)\", () => {\n\t\tit(\"blocks sed -i\", () => {\n\t\t\tassert.equal(checkBashInterception(\"sed -i 's/foo/bar/' file.ts\", ALL_TOOLS).block, true);\n\t\t\tassert.equal(checkBashInterception(\"sed --in-place 's/x/y/' f\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"does NOT block sed without -i (read-only)\", () => {\n\t\t\tassert.equal(checkBashInterception(\"sed 's/foo/bar/' file.ts\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"blocks perl -pi and perl -p -i\", () => {\n\t\t\tassert.equal(checkBashInterception(\"perl -pi -e 's/foo/bar/' file\", ALL_TOOLS).block, true);\n\t\t\tassert.equal(checkBashInterception(\"perl -p -i -e 's/x/y/' f\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"blocks awk -i inplace\", () => {\n\t\t\tassert.equal(checkBashInterception(\"awk -i inplace '{print}' file\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"does NOT block when edit tool is absent\", () => {\n\t\t\tassert.equal(checkBashInterception(\"sed -i 's/a/b/' f\", [\"read\", \"grep\"]).block, false);\n\t\t});\n\t});\n\n\tdescribe(\"write rule (echo/printf/heredoc redirect)\", () => {\n\t\tit(\"blocks echo with > redirect\", () => {\n\t\t\tassert.equal(checkBashInterception(\"echo hello > file.txt\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"blocks printf with > redirect\", () => {\n\t\t\tassert.equal(checkBashInterception('printf \"%s\" content > out.txt', ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"does NOT block echo without redirect\", () => {\n\t\t\tassert.equal(checkBashInterception(\"echo hello\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"does NOT block >> append redirect (write tool does not support appending)\", () => {\n\t\t\tassert.equal(checkBashInterception(\"echo hello >> file.txt\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"does NOT block stderr redirect (2>)\", () => {\n\t\t\tassert.equal(checkBashInterception(\"echo test 2> /dev/null\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"does NOT block pipe (echo foo | grep bar)\", () => {\n\t\t\tassert.equal(checkBashInterception(\"echo foo | grep bar\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"does NOT block when write tool is absent\", () => {\n\t\t\tassert.equal(checkBashInterception(\"echo hello > file.txt\", [\"read\", \"grep\"]).block, false);\n\t\t});\n\t});\n\n\tdescribe(\"pass-through commands\", () => {\n\t\tit(\"passes npm install\", () => {\n\t\t\tassert.equal(checkBashInterception(\"npm install\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"passes ls > output.txt (not an echo/printf/cat)\", () => {\n\t\t\tassert.equal(checkBashInterception(\"ls > output.txt\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"passes tee file.txt\", () => {\n\t\t\tassert.equal(checkBashInterception(\"tee file.txt\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"passes git log\", () => {\n\t\t\tassert.equal(checkBashInterception(\"git log --oneline\", ALL_TOOLS).block, false);\n\t\t});\n\t});\n\n\tdescribe(\"block message content\", () => {\n\t\tit(\"includes the original command in the block message\", () => {\n\t\t\tconst r = checkBashInterception(\"cat README.md\", ALL_TOOLS);\n\t\t\tassert.ok(r.message?.includes(\"cat README.md\"), \"message should contain original command\");\n\t\t});\n\n\t\tit(\"returns block:false with no message when not blocked\", () => {\n\t\t\tconst r = checkBashInterception(\"npm install\", ALL_TOOLS);\n\t\t\tassert.equal(r.block, false);\n\t\t\tassert.equal(r.message, undefined);\n\t\t});\n\t});\n});\n\ndescribe(\"compileInterceptor\", () => {\n\tit(\"produces same results as checkBashInterception\", () => {\n\t\tconst interceptor = compileInterceptor(DEFAULT_BASH_INTERCEPTOR_RULES);\n\t\tconst cases: [string, string[], boolean][] = [\n\t\t\t[\"cat README.md\", ALL_TOOLS, true],\n\t\t\t[\"npm install\", ALL_TOOLS, false],\n\t\t\t[\"grep foo bar\", ALL_TOOLS, true],\n\t\t\t[\"echo hello >> file\", ALL_TOOLS, false],\n\t\t\t[\"echo test 2> /dev/null\", ALL_TOOLS, false],\n\t\t];\n\t\tfor (const [cmd, tools, expected] of cases) {\n\t\t\tassert.equal(\n\t\t\t\tinterceptor.check(cmd, tools).block,\n\t\t\t\texpected,\n\t\t\t\t`pre-compiled: \"${cmd}\" expected block=${expected}`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"silently skips rules with invalid regex patterns\", () => {\n\t\tconst rules: BashInterceptorRule[] = [\n\t\t\t{ pattern: \"[invalid(\", tool: \"read\", message: \"broken\" },\n\t\t\t{ pattern: \"^\\\\s*cat\\\\s+\", tool: \"read\", message: \"valid\" },\n\t\t];\n\t\tconst interceptor = compileInterceptor(rules);\n\t\tassert.equal(interceptor.check(\"cat file.txt\", [\"read\"]).block, true);\n\t});\n\n\tit(\"returns block:false when available tools list is empty\", () => {\n\t\tconst interceptor = compileInterceptor(DEFAULT_BASH_INTERCEPTOR_RULES);\n\t\tassert.equal(interceptor.check(\"cat README.md\", []).block, false);\n\t});\n\n\tit(\"allows custom rule override\", () => {\n\t\tconst customRules: BashInterceptorRule[] = [\n\t\t\t{ pattern: \"^\\\\s*curl\\\\s+\", tool: \"fetch\", message: \"Use fetch tool instead.\" },\n\t\t];\n\t\tconst interceptor = compileInterceptor(customRules);\n\t\tassert.equal(interceptor.check(\"curl https://example.com\", [\"fetch\"]).block, true);\n\t\t// default rules not active\n\t\tassert.equal(interceptor.check(\"cat file.txt\", [\"read\"]).block, false);\n\t});\n});\n"]}
|
|
1
|
+
{"version":3,"file":"bash-interceptor.test.js","sourceRoot":"","sources":["../../../src/core/tools/bash-interceptor.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport {\n\tcheckBashInterception,\n\tcompileInterceptor,\n\tDEFAULT_BASH_INTERCEPTOR_RULES,\n\ttype BashInterceptorRule,\n} from \"./bash-interceptor.js\";\n\nconst ALL_TOOLS = [\"read\", \"grep\", \"find\", \"edit\", \"write\"];\nconst NO_TOOLS: string[] = [];\n\ndescribe(\"checkBashInterception\", () => {\n\tdescribe(\"read rule (cat/head/tail/less/more)\", () => {\n\t\tit(\"blocks cat with a file argument\", () => {\n\t\t\tconst r = checkBashInterception(\"cat README.md\", ALL_TOOLS);\n\t\t\tassert.equal(r.block, true);\n\t\t\tassert.equal(r.suggestedTool, \"read\");\n\t\t});\n\n\t\tit(\"blocks head and tail\", () => {\n\t\t\tassert.equal(checkBashInterception(\"head -n 20 file.ts\", ALL_TOOLS).block, true);\n\t\t\tassert.equal(checkBashInterception(\"tail -f app.log\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"does NOT block cat used as heredoc (cat <<EOF)\", () => {\n\t\t\tconst r = checkBashInterception(\"cat <<EOF > file.txt\", ALL_TOOLS);\n\t\t\tassert.notEqual(r.suggestedTool, \"read\");\n\t\t});\n\n\t\tit(\"does NOT block when read tool is absent\", () => {\n\t\t\tassert.equal(checkBashInterception(\"cat README.md\", NO_TOOLS).block, false);\n\t\t\tassert.equal(checkBashInterception(\"cat README.md\", [\"grep\"]).block, false);\n\t\t});\n\t});\n\n\tdescribe(\"grep rule\", () => {\n\t\tit(\"blocks grep and rg\", () => {\n\t\t\tassert.equal(checkBashInterception(\"grep foo bar.ts\", ALL_TOOLS).block, true);\n\t\t\tassert.equal(checkBashInterception(\"rg -r pattern .\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"blocks grep with leading whitespace\", () => {\n\t\t\tassert.equal(checkBashInterception(\" grep -r foo .\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"does NOT block when grep tool is absent\", () => {\n\t\t\tassert.equal(checkBashInterception(\"grep foo bar\", [\"read\", \"edit\"]).block, false);\n\t\t});\n\t});\n\n\tdescribe(\"find rule\", () => {\n\t\tit(\"blocks find with -name flag\", () => {\n\t\t\tassert.equal(checkBashInterception('find . -name \"*.ts\"', ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"blocks find with -type flag\", () => {\n\t\t\tassert.equal(checkBashInterception(\"find /tmp -maxdepth 1 -type f\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"does NOT block find without name/type flags\", () => {\n\t\t\tassert.equal(checkBashInterception(\"find /tmp -maxdepth 1\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"does NOT block when find tool is absent\", () => {\n\t\t\tassert.equal(checkBashInterception('find . -name \"*.ts\"', [\"read\", \"grep\"]).block, false);\n\t\t});\n\t});\n\n\tdescribe(\"edit rule (sed/perl/awk)\", () => {\n\t\tit(\"blocks sed -i\", () => {\n\t\t\tassert.equal(checkBashInterception(\"sed -i 's/foo/bar/' file.ts\", ALL_TOOLS).block, true);\n\t\t\tassert.equal(checkBashInterception(\"sed --in-place 's/x/y/' f\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"does NOT block sed without -i (read-only)\", () => {\n\t\t\tassert.equal(checkBashInterception(\"sed 's/foo/bar/' file.ts\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"blocks perl -pi and perl -p -i\", () => {\n\t\t\tassert.equal(checkBashInterception(\"perl -pi -e 's/foo/bar/' file\", ALL_TOOLS).block, true);\n\t\t\tassert.equal(checkBashInterception(\"perl -p -i -e 's/x/y/' f\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"blocks awk -i inplace\", () => {\n\t\t\tassert.equal(checkBashInterception(\"awk -i inplace '{print}' file\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"does NOT block when edit tool is absent\", () => {\n\t\t\tassert.equal(checkBashInterception(\"sed -i 's/a/b/' f\", [\"read\", \"grep\"]).block, false);\n\t\t});\n\t});\n\n\tdescribe(\"write rule (echo/printf/heredoc redirect)\", () => {\n\t\tit(\"blocks echo with > redirect\", () => {\n\t\t\tassert.equal(checkBashInterception(\"echo hello > file.txt\", ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"blocks printf with > redirect\", () => {\n\t\t\tassert.equal(checkBashInterception('printf \"%s\" content > out.txt', ALL_TOOLS).block, true);\n\t\t});\n\n\t\tit(\"does NOT block echo without redirect\", () => {\n\t\t\tassert.equal(checkBashInterception(\"echo hello\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"does NOT block >> append redirect (write tool does not support appending)\", () => {\n\t\t\tassert.equal(checkBashInterception(\"echo hello >> file.txt\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"does NOT block stderr redirect (2>)\", () => {\n\t\t\tassert.equal(checkBashInterception(\"echo test 2> /dev/null\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"does NOT block pipe (echo foo | grep bar)\", () => {\n\t\t\tassert.equal(checkBashInterception(\"echo foo | grep bar\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"does NOT block when write tool is absent\", () => {\n\t\t\tassert.equal(checkBashInterception(\"echo hello > file.txt\", [\"read\", \"grep\"]).block, false);\n\t\t});\n\t});\n\n\tdescribe(\"pass-through commands\", () => {\n\t\tit(\"passes npm install\", () => {\n\t\t\tassert.equal(checkBashInterception(\"npm install\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"passes ls > output.txt (not an echo/printf/cat)\", () => {\n\t\t\tassert.equal(checkBashInterception(\"ls > output.txt\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"passes tee file.txt\", () => {\n\t\t\tassert.equal(checkBashInterception(\"tee file.txt\", ALL_TOOLS).block, false);\n\t\t});\n\n\t\tit(\"passes git log\", () => {\n\t\t\tassert.equal(checkBashInterception(\"git log --oneline\", ALL_TOOLS).block, false);\n\t\t});\n\t});\n\n\tdescribe(\"block message content\", () => {\n\t\tit(\"includes the original command in the block message\", () => {\n\t\t\tconst r = checkBashInterception(\"cat README.md\", ALL_TOOLS);\n\t\t\tassert.ok(r.message?.includes(\"cat README.md\"), \"message should contain original command\");\n\t\t});\n\n\t\tit(\"uses 'Tool routing:' prefix to distinguish from permission blocks\", () => {\n\t\t\tconst r = checkBashInterception(\"cat README.md\", ALL_TOOLS);\n\t\t\tassert.ok(r.message?.startsWith(\"Tool routing:\"), \"message should start with 'Tool routing:'\");\n\t\t\tassert.ok(r.message?.includes(\"not a permission block\"), \"message should clarify it's not a permission block\");\n\t\t});\n\n\t\tit(\"returns block:false with no message when not blocked\", () => {\n\t\t\tconst r = checkBashInterception(\"npm install\", ALL_TOOLS);\n\t\t\tassert.equal(r.block, false);\n\t\t\tassert.equal(r.message, undefined);\n\t\t});\n\t});\n});\n\ndescribe(\"compileInterceptor\", () => {\n\tit(\"produces same results as checkBashInterception\", () => {\n\t\tconst interceptor = compileInterceptor(DEFAULT_BASH_INTERCEPTOR_RULES);\n\t\tconst cases: [string, string[], boolean][] = [\n\t\t\t[\"cat README.md\", ALL_TOOLS, true],\n\t\t\t[\"npm install\", ALL_TOOLS, false],\n\t\t\t[\"grep foo bar\", ALL_TOOLS, true],\n\t\t\t[\"echo hello >> file\", ALL_TOOLS, false],\n\t\t\t[\"echo test 2> /dev/null\", ALL_TOOLS, false],\n\t\t];\n\t\tfor (const [cmd, tools, expected] of cases) {\n\t\t\tassert.equal(\n\t\t\t\tinterceptor.check(cmd, tools).block,\n\t\t\t\texpected,\n\t\t\t\t`pre-compiled: \"${cmd}\" expected block=${expected}`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"silently skips rules with invalid regex patterns\", () => {\n\t\tconst rules: BashInterceptorRule[] = [\n\t\t\t{ pattern: \"[invalid(\", tool: \"read\", message: \"broken\" },\n\t\t\t{ pattern: \"^\\\\s*cat\\\\s+\", tool: \"read\", message: \"valid\" },\n\t\t];\n\t\tconst interceptor = compileInterceptor(rules);\n\t\tassert.equal(interceptor.check(\"cat file.txt\", [\"read\"]).block, true);\n\t});\n\n\tit(\"returns block:false when available tools list is empty\", () => {\n\t\tconst interceptor = compileInterceptor(DEFAULT_BASH_INTERCEPTOR_RULES);\n\t\tassert.equal(interceptor.check(\"cat README.md\", []).block, false);\n\t});\n\n\tit(\"allows custom rule override\", () => {\n\t\tconst customRules: BashInterceptorRule[] = [\n\t\t\t{ pattern: \"^\\\\s*curl\\\\s+\", tool: \"fetch\", message: \"Use fetch tool instead.\" },\n\t\t];\n\t\tconst interceptor = compileInterceptor(customRules);\n\t\tassert.equal(interceptor.check(\"curl https://example.com\", [\"fetch\"]).block, true);\n\t\t// default rules not active\n\t\tassert.equal(interceptor.check(\"cat file.txt\", [\"read\"]).block, false);\n\t});\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/bash-execution.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAgB,KAAK,GAAG,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAGN,KAAK,gBAAgB,EAErB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"bash-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/bash-execution.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAgB,KAAK,GAAG,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAGN,KAAK,gBAAgB,EAErB,MAAM,iCAAiC,CAAC;AA4BzC,KAAK,cAAc,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE3C,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,MAAM,CAA6D;IAC3E,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAAC,CAAmB;IAC5C,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,SAAS,CAAU;IAE3B,OAAO,CAAC,UAAU,CAAO;gBAGxB,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,GAAG,EACP,kBAAkB,UAAQ,EAC1B,UAAU,GAAE,cAAyB,EACrC,UAAU,UAAQ,EAClB,SAAS,UAAQ;IA6BlB,kCAAkC;IAClC,OAAO,CAAC,eAAe;IAQvB;;;OAGG;IACH,OAAO,IAAI,IAAI;IAIf;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAKpC,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAOhC,UAAU,IAAI,IAAI;IAK3B,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOjC,WAAW,CACV,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,SAAS,EAAE,OAAO,EAClB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,cAAc,CAAC,EAAE,MAAM,EACvB,SAAS,CAAC,EAAE,OAAO,GACjB,IAAI;IAmBP,OAAO,CAAC,aAAa;IAkGrB;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,UAAU,IAAI,MAAM;CAGpB"}
|
|
@@ -9,6 +9,30 @@ import { editorKey, keyHint } from "./keybinding-hints.js";
|
|
|
9
9
|
import { truncateToVisualLines } from "./visual-truncate.js";
|
|
10
10
|
// Preview line limit when not expanded (matches tool execution behavior)
|
|
11
11
|
const PREVIEW_LINES = 20;
|
|
12
|
+
/**
|
|
13
|
+
* Returns true if the command failure looks like a privilege/sudo escalation
|
|
14
|
+
* error that the agent cannot resolve — distinct from an OS sandbox policy block.
|
|
15
|
+
*/
|
|
16
|
+
function isPrivilegeError(output, command) {
|
|
17
|
+
// Already handled by sandbox-policy path
|
|
18
|
+
if (/sandbox blocked this operation/i.test(output))
|
|
19
|
+
return false;
|
|
20
|
+
// sudo explicitly rejected
|
|
21
|
+
if (/sudo.*operation not permitted/i.test(output))
|
|
22
|
+
return true;
|
|
23
|
+
if (/command exited with code 126/i.test(output) && /sudo/i.test(output))
|
|
24
|
+
return true;
|
|
25
|
+
// Agent process itself hit EPERM (e.g. npm cache owned by root)
|
|
26
|
+
if (/EPERM|operation not permitted/i.test(output) && /sudo/i.test(command))
|
|
27
|
+
return true;
|
|
28
|
+
// npm cache root-owned files pattern
|
|
29
|
+
if (/cache folder contains root-owned files/i.test(output))
|
|
30
|
+
return true;
|
|
31
|
+
// Generic privilege denial patterns
|
|
32
|
+
if (/permission denied/i.test(output) && /sudo/i.test(command))
|
|
33
|
+
return true;
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
12
36
|
export class BashExecutionComponent extends Container {
|
|
13
37
|
constructor(command, ui, excludeFromContext = false, renderMode = "normal", _rtkActive = false, sandboxed = false) {
|
|
14
38
|
super();
|
|
@@ -151,6 +175,10 @@ export class BashExecutionComponent extends Container {
|
|
|
151
175
|
if (this.sandboxed && /operation not permitted/i.test(fullOutput)) {
|
|
152
176
|
statusParts.push(theme.fg("warning", "Sandbox blocked this operation. Run /sandbox to inspect the active policy and allowed paths."));
|
|
153
177
|
}
|
|
178
|
+
else if (!this.sandboxed && isPrivilegeError(fullOutput, this.command)) {
|
|
179
|
+
statusParts.push(theme.fg("warning", "⚠ This command requires elevated privileges the agent cannot use."));
|
|
180
|
+
statusParts.push(theme.fg("muted", `Run it manually in your terminal:\n ${this.command}`));
|
|
181
|
+
}
|
|
154
182
|
}
|
|
155
183
|
// Add truncation warning (context truncation, not preview truncation)
|
|
156
184
|
const wasTruncated = this.truncationResult?.truncated || contextTruncation.truncated;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash-execution.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/bash-execution.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Component for displaying bash command execution with streaming output.\n */\n\nimport { Container, Loader, Text, type TUI } from \"@gsd/pi-tui\";\nimport {\n\tDEFAULT_MAX_BYTES,\n\tDEFAULT_MAX_LINES,\n\ttype TruncationResult,\n\ttruncateTail,\n} from \"../../../core/tools/truncate.js\";\nimport { renderTerminalLines } from \"../../../utils/terminal-serializer.js\";\nimport { theme, type ThemeColor } from \"../theme/theme.js\";\nimport { editorKey, keyHint } from \"./keybinding-hints.js\";\nimport { truncateToVisualLines } from \"./visual-truncate.js\";\n\n// Preview line limit when not expanded (matches tool execution behavior)\nconst PREVIEW_LINES = 20;\n\ntype ToolOutputMode = \"minimal\" | \"normal\";\n\nexport class BashExecutionComponent extends Container {\n\tprivate command: string;\n\tprivate outputLines: string[] = [];\n\tprivate rawOutput = \"\";\n\tprivate status: \"running\" | \"complete\" | \"cancelled\" | \"error\" = \"running\";\n\tprivate exitCode: number | undefined = undefined;\n\tprivate loader: Loader;\n\tprivate truncationResult?: TruncationResult;\n\tprivate fullOutputPath?: string;\n\tprivate expanded = false;\n\tprivate renderMode: ToolOutputMode;\n\tprivate contentContainer: Container;\n\tprivate ui: TUI;\n\tprivate colorKey: ThemeColor;\n\tprivate sandboxed: boolean;\n\t// Dedicated header node\n\tprivate headerText: Text;\n\n\tconstructor(\n\t\tcommand: string,\n\t\tui: TUI,\n\t\texcludeFromContext = false,\n\t\trenderMode: ToolOutputMode = \"normal\",\n\t\t_rtkActive = false,\n\t\tsandboxed = false,\n\t) {\n\t\tsuper();\n\t\tthis.command = command;\n\t\tthis.ui = ui;\n\t\tthis.renderMode = renderMode;\n\t\tthis.sandboxed = sandboxed;\n\n\t\t// Use dim tone for excluded-from-context commands (!! prefix)\n\t\tthis.colorKey = (excludeFromContext ? \"dim\" : \"bashMode\") as ThemeColor;\n\n\t\t// Content container\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\t// Header Text node\n\t\tthis.headerText = new Text(this.buildHeaderText(), 1, 0);\n\t\tthis.contentContainer.addChild(this.headerText);\n\n\t\t// Loader\n\t\tthis.loader = new Loader(\n\t\t\tui,\n\t\t\t(spinner) => theme.fg(this.colorKey, spinner),\n\t\t\t(text) => theme.fg(\"muted\", text),\n\t\t\t`Running... (${editorKey(\"selectCancel\")} to cancel)`, // Plain text for loader\n\t\t);\n\t\tthis.contentContainer.addChild(this.loader);\n\t}\n\n\t/** Build the header line text. */\n\tprivate buildHeaderText(): string {\n\t\tlet text = `${theme.fg(\"toolTitle\", theme.bold(\"bash\"))} ${theme.fg(this.colorKey, theme.bold(`$ ${this.command}`))}`;\n\t\tif (this.sandboxed) {\n\t\t\ttext += ` ${theme.fg(\"success\", \"[sandboxed]\")}`;\n\t\t}\n\t\treturn text;\n\t}\n\n\t/**\n\t * Stop all timers and release resources. Call when removing the component\n\t * from the tree before setComplete() has been called (e.g. on clear/cancel).\n\t */\n\tdispose(): void {\n\t\tthis.loader.dispose();\n\t}\n\n\t/**\n\t * Set whether the output is expanded (shows full output) or collapsed (preview only).\n\t */\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetRenderMode(mode: ToolOutputMode): void {\n\t\tif (this.renderMode !== mode) {\n\t\t\tthis.renderMode = mode;\n\t\t\tthis.updateDisplay();\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\tappendOutput(chunk: string): void {\n\t\t// Strip ANSI codes and preserve carriage-return semantics for display.\n\t\tthis.rawOutput += chunk;\n\t\tthis.outputLines = renderTerminalLines(this.rawOutput);\n\t\tthis.updateDisplay();\n\t}\n\n\tsetComplete(\n\t\texitCode: number | undefined,\n\t\tcancelled: boolean,\n\t\ttruncationResult?: TruncationResult,\n\t\tfullOutputPath?: string,\n\t\tsandboxed?: boolean,\n\t): void {\n\t\tthis.exitCode = exitCode;\n\t\tthis.status = cancelled\n\t\t\t? \"cancelled\"\n\t\t\t: exitCode !== 0 && exitCode !== undefined && exitCode !== null\n\t\t\t\t? \"error\"\n\t\t\t\t: \"complete\";\n\t\tthis.truncationResult = truncationResult;\n\t\tthis.fullOutputPath = fullOutputPath;\n\t\tif (sandboxed !== undefined) {\n\t\t\tthis.sandboxed = sandboxed;\n\t\t}\n\n\t\t// Stop loader\n\t\tthis.loader.stop();\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate updateDisplay(): void {\n\t\t// Apply truncation for LLM context limits (same limits as bash tool)\n\t\tconst fullOutput = this.outputLines.join(\"\\n\");\n\t\tconst contextTruncation = truncateTail(fullOutput, {\n\t\t\tmaxLines: DEFAULT_MAX_LINES,\n\t\t\tmaxBytes: DEFAULT_MAX_BYTES,\n\t\t});\n\n\t\t// Get the lines to potentially display (after context truncation)\n\t\tconst availableLines = contextTruncation.content ? contextTruncation.content.split(\"\\n\") : [];\n\n\t\t// Apply preview truncation based on expanded state\n\t\tconst previewLogicalLines = availableLines.slice(-PREVIEW_LINES);\n\t\tconst hiddenLineCount = availableLines.length - previewLogicalLines.length;\n\n\t\t// Rebuild content container\n\t\tthis.contentContainer.clear();\n\n\t\t// Header — re-add the dedicated node (clear() removed it, setText keeps its current value)\n\t\tthis.contentContainer.addChild(this.headerText);\n\n\t\t// Output\n\t\tif (availableLines.length > 0) {\n\t\t\tif (this.expanded) {\n\t\t\t\t// Show all lines\n\t\t\t\tconst displayText = availableLines.map((line) => theme.fg(\"muted\", line)).join(\"\\n\");\n\t\t\t\tthis.contentContainer.addChild(new Text(`\\n${displayText}`, 1, 0));\n\t\t\t} else if (this.renderMode === \"minimal\") {\n\t\t\t\t// collapsed — no inline hint needed (shown in editor bottom border)\n\t\t\t} else {\n\t\t\t\t// Use shared visual truncation utility\n\t\t\t\tconst styledOutput = previewLogicalLines.map((line) => theme.fg(\"muted\", line)).join(\"\\n\");\n\t\t\t\tconst { visualLines } = truncateToVisualLines(\n\t\t\t\t\t`\\n${styledOutput}`,\n\t\t\t\t\tPREVIEW_LINES,\n\t\t\t\t\tthis.ui.terminal.columns,\n\t\t\t\t\t1, // padding\n\t\t\t\t);\n\t\t\t\tthis.contentContainer.addChild({ render: () => visualLines, invalidate: () => {} });\n\t\t\t}\n\t\t}\n\n\t\t// Loader or status\n\t\tif (this.status === \"running\") {\n\t\t\tthis.contentContainer.addChild(this.loader);\n\t\t} else {\n\t\t\tconst statusParts: string[] = [];\n\n\t\t\t// Show expand/collapse hint whenever there is output\n\t\t\tif (availableLines.length > 0) {\n\t\t\t\tif (this.expanded) {\n\t\t\t\t\tstatusParts.push(`(${keyHint(\"expandTools\", \"to collapse\")})`);\n\t\t\t\t} else if (this.renderMode === \"minimal\") {\n\t\t\t\t\tstatusParts.push(`(${keyHint(\"expandTools\", \"to expand\")})`);\n\t\t\t\t} else if (hiddenLineCount > 0) {\n\t\t\t\t\t// Normal mode: show line count + hint\n\t\t\t\t\tstatusParts.push(\n\t\t\t\t\t\t`${theme.fg(\"muted\", `... ${hiddenLineCount} more lines`)} (${keyHint(\"expandTools\", \"to expand\")})`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Normal mode: all preview lines visible, still offer expand\n\t\t\t\t\tstatusParts.push(`(${keyHint(\"expandTools\", \"to expand\")})`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.status === \"cancelled\") {\n\t\t\t\tstatusParts.push(theme.fg(\"warning\", \"(cancelled)\"));\n\t\t\t} else if (this.status === \"error\") {\n\t\t\t\tstatusParts.push(theme.fg(\"error\", `(exit ${this.exitCode})`));\n\t\t\t\tif (this.sandboxed && /operation not permitted/i.test(fullOutput)) {\n\t\t\t\t\tstatusParts.push(\n\t\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\t\"warning\",\n\t\t\t\t\t\t\t\"Sandbox blocked this operation. Run /sandbox to inspect the active policy and allowed paths.\",\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add truncation warning (context truncation, not preview truncation)\n\t\t\tconst wasTruncated = this.truncationResult?.truncated || contextTruncation.truncated;\n\t\t\tif (wasTruncated && this.fullOutputPath) {\n\t\t\t\tstatusParts.push(theme.fg(\"warning\", `Output truncated. Full output: ${this.fullOutputPath}`));\n\t\t\t}\n\n\t\t\tif (statusParts.length > 0) {\n\t\t\t\tthis.contentContainer.addChild(new Text(`\\n${statusParts.join(\"\\n\")}`, 1, 0));\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get the raw output for creating BashExecutionMessage.\n\t */\n\tgetOutput(): string {\n\t\treturn this.outputLines.join(\"\\n\");\n\t}\n\n\t/**\n\t * Get the command that was executed.\n\t */\n\tgetCommand(): string {\n\t\treturn this.command;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bash-execution.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/bash-execution.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Component for displaying bash command execution with streaming output.\n */\n\nimport { Container, Loader, Text, type TUI } from \"@gsd/pi-tui\";\nimport {\n\tDEFAULT_MAX_BYTES,\n\tDEFAULT_MAX_LINES,\n\ttype TruncationResult,\n\ttruncateTail,\n} from \"../../../core/tools/truncate.js\";\nimport { renderTerminalLines } from \"../../../utils/terminal-serializer.js\";\nimport { theme, type ThemeColor } from \"../theme/theme.js\";\nimport { editorKey, keyHint } from \"./keybinding-hints.js\";\nimport { truncateToVisualLines } from \"./visual-truncate.js\";\n\n// Preview line limit when not expanded (matches tool execution behavior)\nconst PREVIEW_LINES = 20;\n\n/**\n * Returns true if the command failure looks like a privilege/sudo escalation\n * error that the agent cannot resolve — distinct from an OS sandbox policy block.\n */\nfunction isPrivilegeError(output: string, command: string): boolean {\n\t// Already handled by sandbox-policy path\n\tif (/sandbox blocked this operation/i.test(output)) return false;\n\t// sudo explicitly rejected\n\tif (/sudo.*operation not permitted/i.test(output)) return true;\n\tif (/command exited with code 126/i.test(output) && /sudo/i.test(output)) return true;\n\t// Agent process itself hit EPERM (e.g. npm cache owned by root)\n\tif (/EPERM|operation not permitted/i.test(output) && /sudo/i.test(command)) return true;\n\t// npm cache root-owned files pattern\n\tif (/cache folder contains root-owned files/i.test(output)) return true;\n\t// Generic privilege denial patterns\n\tif (/permission denied/i.test(output) && /sudo/i.test(command)) return true;\n\treturn false;\n}\n\ntype ToolOutputMode = \"minimal\" | \"normal\";\n\nexport class BashExecutionComponent extends Container {\n\tprivate command: string;\n\tprivate outputLines: string[] = [];\n\tprivate rawOutput = \"\";\n\tprivate status: \"running\" | \"complete\" | \"cancelled\" | \"error\" = \"running\";\n\tprivate exitCode: number | undefined = undefined;\n\tprivate loader: Loader;\n\tprivate truncationResult?: TruncationResult;\n\tprivate fullOutputPath?: string;\n\tprivate expanded = false;\n\tprivate renderMode: ToolOutputMode;\n\tprivate contentContainer: Container;\n\tprivate ui: TUI;\n\tprivate colorKey: ThemeColor;\n\tprivate sandboxed: boolean;\n\t// Dedicated header node\n\tprivate headerText: Text;\n\n\tconstructor(\n\t\tcommand: string,\n\t\tui: TUI,\n\t\texcludeFromContext = false,\n\t\trenderMode: ToolOutputMode = \"normal\",\n\t\t_rtkActive = false,\n\t\tsandboxed = false,\n\t) {\n\t\tsuper();\n\t\tthis.command = command;\n\t\tthis.ui = ui;\n\t\tthis.renderMode = renderMode;\n\t\tthis.sandboxed = sandboxed;\n\n\t\t// Use dim tone for excluded-from-context commands (!! prefix)\n\t\tthis.colorKey = (excludeFromContext ? \"dim\" : \"bashMode\") as ThemeColor;\n\n\t\t// Content container\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\t// Header Text node\n\t\tthis.headerText = new Text(this.buildHeaderText(), 1, 0);\n\t\tthis.contentContainer.addChild(this.headerText);\n\n\t\t// Loader\n\t\tthis.loader = new Loader(\n\t\t\tui,\n\t\t\t(spinner) => theme.fg(this.colorKey, spinner),\n\t\t\t(text) => theme.fg(\"muted\", text),\n\t\t\t`Running... (${editorKey(\"selectCancel\")} to cancel)`, // Plain text for loader\n\t\t);\n\t\tthis.contentContainer.addChild(this.loader);\n\t}\n\n\t/** Build the header line text. */\n\tprivate buildHeaderText(): string {\n\t\tlet text = `${theme.fg(\"toolTitle\", theme.bold(\"bash\"))} ${theme.fg(this.colorKey, theme.bold(`$ ${this.command}`))}`;\n\t\tif (this.sandboxed) {\n\t\t\ttext += ` ${theme.fg(\"success\", \"[sandboxed]\")}`;\n\t\t}\n\t\treturn text;\n\t}\n\n\t/**\n\t * Stop all timers and release resources. Call when removing the component\n\t * from the tree before setComplete() has been called (e.g. on clear/cancel).\n\t */\n\tdispose(): void {\n\t\tthis.loader.dispose();\n\t}\n\n\t/**\n\t * Set whether the output is expanded (shows full output) or collapsed (preview only).\n\t */\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetRenderMode(mode: ToolOutputMode): void {\n\t\tif (this.renderMode !== mode) {\n\t\t\tthis.renderMode = mode;\n\t\t\tthis.updateDisplay();\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\tappendOutput(chunk: string): void {\n\t\t// Strip ANSI codes and preserve carriage-return semantics for display.\n\t\tthis.rawOutput += chunk;\n\t\tthis.outputLines = renderTerminalLines(this.rawOutput);\n\t\tthis.updateDisplay();\n\t}\n\n\tsetComplete(\n\t\texitCode: number | undefined,\n\t\tcancelled: boolean,\n\t\ttruncationResult?: TruncationResult,\n\t\tfullOutputPath?: string,\n\t\tsandboxed?: boolean,\n\t): void {\n\t\tthis.exitCode = exitCode;\n\t\tthis.status = cancelled\n\t\t\t? \"cancelled\"\n\t\t\t: exitCode !== 0 && exitCode !== undefined && exitCode !== null\n\t\t\t\t? \"error\"\n\t\t\t\t: \"complete\";\n\t\tthis.truncationResult = truncationResult;\n\t\tthis.fullOutputPath = fullOutputPath;\n\t\tif (sandboxed !== undefined) {\n\t\t\tthis.sandboxed = sandboxed;\n\t\t}\n\n\t\t// Stop loader\n\t\tthis.loader.stop();\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate updateDisplay(): void {\n\t\t// Apply truncation for LLM context limits (same limits as bash tool)\n\t\tconst fullOutput = this.outputLines.join(\"\\n\");\n\t\tconst contextTruncation = truncateTail(fullOutput, {\n\t\t\tmaxLines: DEFAULT_MAX_LINES,\n\t\t\tmaxBytes: DEFAULT_MAX_BYTES,\n\t\t});\n\n\t\t// Get the lines to potentially display (after context truncation)\n\t\tconst availableLines = contextTruncation.content ? contextTruncation.content.split(\"\\n\") : [];\n\n\t\t// Apply preview truncation based on expanded state\n\t\tconst previewLogicalLines = availableLines.slice(-PREVIEW_LINES);\n\t\tconst hiddenLineCount = availableLines.length - previewLogicalLines.length;\n\n\t\t// Rebuild content container\n\t\tthis.contentContainer.clear();\n\n\t\t// Header — re-add the dedicated node (clear() removed it, setText keeps its current value)\n\t\tthis.contentContainer.addChild(this.headerText);\n\n\t\t// Output\n\t\tif (availableLines.length > 0) {\n\t\t\tif (this.expanded) {\n\t\t\t\t// Show all lines\n\t\t\t\tconst displayText = availableLines.map((line) => theme.fg(\"muted\", line)).join(\"\\n\");\n\t\t\t\tthis.contentContainer.addChild(new Text(`\\n${displayText}`, 1, 0));\n\t\t\t} else if (this.renderMode === \"minimal\") {\n\t\t\t\t// collapsed — no inline hint needed (shown in editor bottom border)\n\t\t\t} else {\n\t\t\t\t// Use shared visual truncation utility\n\t\t\t\tconst styledOutput = previewLogicalLines.map((line) => theme.fg(\"muted\", line)).join(\"\\n\");\n\t\t\t\tconst { visualLines } = truncateToVisualLines(\n\t\t\t\t\t`\\n${styledOutput}`,\n\t\t\t\t\tPREVIEW_LINES,\n\t\t\t\t\tthis.ui.terminal.columns,\n\t\t\t\t\t1, // padding\n\t\t\t\t);\n\t\t\t\tthis.contentContainer.addChild({ render: () => visualLines, invalidate: () => {} });\n\t\t\t}\n\t\t}\n\n\t\t// Loader or status\n\t\tif (this.status === \"running\") {\n\t\t\tthis.contentContainer.addChild(this.loader);\n\t\t} else {\n\t\t\tconst statusParts: string[] = [];\n\n\t\t\t// Show expand/collapse hint whenever there is output\n\t\t\tif (availableLines.length > 0) {\n\t\t\t\tif (this.expanded) {\n\t\t\t\t\tstatusParts.push(`(${keyHint(\"expandTools\", \"to collapse\")})`);\n\t\t\t\t} else if (this.renderMode === \"minimal\") {\n\t\t\t\t\tstatusParts.push(`(${keyHint(\"expandTools\", \"to expand\")})`);\n\t\t\t\t} else if (hiddenLineCount > 0) {\n\t\t\t\t\t// Normal mode: show line count + hint\n\t\t\t\t\tstatusParts.push(\n\t\t\t\t\t\t`${theme.fg(\"muted\", `... ${hiddenLineCount} more lines`)} (${keyHint(\"expandTools\", \"to expand\")})`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Normal mode: all preview lines visible, still offer expand\n\t\t\t\t\tstatusParts.push(`(${keyHint(\"expandTools\", \"to expand\")})`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.status === \"cancelled\") {\n\t\t\t\tstatusParts.push(theme.fg(\"warning\", \"(cancelled)\"));\n\t\t\t} else if (this.status === \"error\") {\n\t\t\t\tstatusParts.push(theme.fg(\"error\", `(exit ${this.exitCode})`));\n\t\t\t\tif (this.sandboxed && /operation not permitted/i.test(fullOutput)) {\n\t\t\t\t\tstatusParts.push(\n\t\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\t\"warning\",\n\t\t\t\t\t\t\t\"Sandbox blocked this operation. Run /sandbox to inspect the active policy and allowed paths.\",\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} else if (!this.sandboxed && isPrivilegeError(fullOutput, this.command)) {\n\t\t\t\t\tstatusParts.push(\n\t\t\t\t\t\ttheme.fg(\"warning\", \"⚠ This command requires elevated privileges the agent cannot use.\"),\n\t\t\t\t\t);\n\t\t\t\t\tstatusParts.push(\n\t\t\t\t\t\ttheme.fg(\"muted\", `Run it manually in your terminal:\\n ${this.command}`),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add truncation warning (context truncation, not preview truncation)\n\t\t\tconst wasTruncated = this.truncationResult?.truncated || contextTruncation.truncated;\n\t\t\tif (wasTruncated && this.fullOutputPath) {\n\t\t\t\tstatusParts.push(theme.fg(\"warning\", `Output truncated. Full output: ${this.fullOutputPath}`));\n\t\t\t}\n\n\t\t\tif (statusParts.length > 0) {\n\t\t\t\tthis.contentContainer.addChild(new Text(`\\n${statusParts.join(\"\\n\")}`, 1, 0));\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get the raw output for creating BashExecutionMessage.\n\t */\n\tgetOutput(): string {\n\t\treturn this.outputLines.join(\"\\n\");\n\t}\n\n\t/**\n\t * Get the command that was executed.\n\t */\n\tgetCommand(): string {\n\t\treturn this.command;\n\t}\n}\n"]}
|
|
@@ -11,10 +11,13 @@ export interface SettingsConfig {
|
|
|
11
11
|
planModeReasoningModel: string;
|
|
12
12
|
planModeReviewModel: string;
|
|
13
13
|
planModeCodingModel: string;
|
|
14
|
+
autoSuggestPlanMode: boolean;
|
|
15
|
+
autoSwitchPlanModel: boolean;
|
|
14
16
|
showImages: boolean;
|
|
15
17
|
autoResizeImages: boolean;
|
|
16
18
|
blockImages: boolean;
|
|
17
19
|
enableSkillCommands: boolean;
|
|
20
|
+
toolProfile: "balanced" | "full";
|
|
18
21
|
codexRotate: boolean;
|
|
19
22
|
cacheTimer: boolean;
|
|
20
23
|
pinLastPrompt: boolean;
|
|
@@ -22,6 +25,7 @@ export interface SettingsConfig {
|
|
|
22
25
|
followUpMode: "all" | "one-at-a-time";
|
|
23
26
|
transport: Transport;
|
|
24
27
|
thinkingLevel: ThinkingLevel;
|
|
28
|
+
anthropicAdaptiveByDefault: boolean;
|
|
25
29
|
availableThinkingLevels: ThinkingLevel[];
|
|
26
30
|
currentTheme: string;
|
|
27
31
|
availableThemes: string[];
|
|
@@ -62,6 +66,8 @@ export interface SettingsCallbacks {
|
|
|
62
66
|
onPlanModeReasoningModelChange: (modelRef: string) => void;
|
|
63
67
|
onPlanModeReviewModelChange: (modelRef: string) => void;
|
|
64
68
|
onPlanModeCodingModelChange: (modelRef: string) => void;
|
|
69
|
+
onAutoSuggestPlanModeChange: (enabled: boolean) => void;
|
|
70
|
+
onAutoSwitchPlanModelChange: (enabled: boolean) => void;
|
|
65
71
|
onAutoDreamChange: (enabled: boolean) => void;
|
|
66
72
|
onAutoMemoryChange: (enabled: boolean) => void;
|
|
67
73
|
onTelegramLiveRelayAutoConnectChange: (enabled: boolean) => void;
|
|
@@ -71,6 +77,7 @@ export interface SettingsCallbacks {
|
|
|
71
77
|
onAutoResizeImagesChange: (enabled: boolean) => void;
|
|
72
78
|
onBlockImagesChange: (blocked: boolean) => void;
|
|
73
79
|
onEnableSkillCommandsChange: (enabled: boolean) => void;
|
|
80
|
+
onToolProfileChange: (profile: "balanced" | "full") => void;
|
|
74
81
|
onCodexRotateChange: (enabled: boolean) => void;
|
|
75
82
|
onCacheTimerChange: (enabled: boolean) => void;
|
|
76
83
|
onPinLastPromptChange: (enabled: boolean) => void;
|
|
@@ -78,6 +85,7 @@ export interface SettingsCallbacks {
|
|
|
78
85
|
onFollowUpModeChange: (mode: "all" | "one-at-a-time") => void;
|
|
79
86
|
onTransportChange: (transport: Transport) => void;
|
|
80
87
|
onThinkingLevelChange: (level: ThinkingLevel) => void;
|
|
88
|
+
onAnthropicAdaptiveByDefaultChange: (enabled: boolean) => void;
|
|
81
89
|
onThemeChange: (theme: string) => void;
|
|
82
90
|
onThemePreview?: (theme: string) => void;
|
|
83
91
|
onThemeAccentChange: (accent: string) => void;
|
package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/settings-selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACN,KAAK,SAAS,EACd,SAAS,EAET,KAAK,UAAU,EAGf,YAAY,EAGZ,MAAM,aAAa,CAAC;AAIrB,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"settings-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/settings-selector.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { getSelectListTheme, getSettingsListTheme, getThemeAccentInfo, getThemeA
|
|
|
3
3
|
import { DynamicBorder } from "./dynamic-border.js";
|
|
4
4
|
export const THINKING_DESCRIPTIONS = {
|
|
5
5
|
off: "No reasoning",
|
|
6
|
+
adaptive: "Claude decides when and how much to think (Claude 4.6+ only)",
|
|
6
7
|
minimal: "Very brief reasoning (~1k tokens)",
|
|
7
8
|
low: "Light reasoning (~2k tokens)",
|
|
8
9
|
medium: "Moderate reasoning (~8k tokens)",
|
|
@@ -113,6 +114,20 @@ export class SettingsSelectorComponent extends Container {
|
|
|
113
114
|
currentValue: config.planModeCodingModel,
|
|
114
115
|
submenu: config.planModeCodingModelSubmenu,
|
|
115
116
|
},
|
|
117
|
+
{
|
|
118
|
+
id: "auto-suggest-plan-mode",
|
|
119
|
+
label: "Auto-suggest plan mode",
|
|
120
|
+
description: "Ask the LLM to suggest plan mode for large/complex tasks",
|
|
121
|
+
currentValue: config.autoSuggestPlanMode ? "true" : "false",
|
|
122
|
+
values: ["true", "false"],
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: "auto-switch-plan-model",
|
|
126
|
+
label: "OpusPlan mode",
|
|
127
|
+
description: "On plan entry: auto-switch to Plan reasoning model (must be set). On approval: offer new session with Plan coding model + worker agent",
|
|
128
|
+
currentValue: config.autoSwitchPlanModel ? "true" : "false",
|
|
129
|
+
values: ["true", "false"],
|
|
130
|
+
},
|
|
116
131
|
{
|
|
117
132
|
id: "steering-mode",
|
|
118
133
|
label: "Steering mode",
|
|
@@ -204,6 +219,13 @@ export class SettingsSelectorComponent extends Container {
|
|
|
204
219
|
done(value);
|
|
205
220
|
}, () => done()),
|
|
206
221
|
},
|
|
222
|
+
{
|
|
223
|
+
id: "anthropic-adaptive-default",
|
|
224
|
+
label: "Anthropic adaptive",
|
|
225
|
+
description: "Default to adaptive thinking for supported Anthropic models",
|
|
226
|
+
currentValue: config.anthropicAdaptiveByDefault ? "true" : "false",
|
|
227
|
+
values: ["true", "false"],
|
|
228
|
+
},
|
|
207
229
|
{
|
|
208
230
|
id: "theme",
|
|
209
231
|
label: "Theme",
|
|
@@ -276,9 +298,18 @@ export class SettingsSelectorComponent extends Container {
|
|
|
276
298
|
currentValue: config.enableSkillCommands ? "true" : "false",
|
|
277
299
|
values: ["true", "false"],
|
|
278
300
|
});
|
|
279
|
-
//
|
|
301
|
+
// Tool profile selector (insert after skill-commands)
|
|
280
302
|
const skillCommandsIndex = items.findIndex((item) => item.id === "skill-commands");
|
|
281
303
|
items.splice(skillCommandsIndex + 1, 0, {
|
|
304
|
+
id: "tool-profile",
|
|
305
|
+
label: "Tool profile",
|
|
306
|
+
description: "Choose the default active tool set: balanced for day-to-day coding, full to enable all available tools",
|
|
307
|
+
currentValue: config.toolProfile,
|
|
308
|
+
values: ["balanced", "full"],
|
|
309
|
+
});
|
|
310
|
+
// Codex rotate toggle (insert after tool-profile)
|
|
311
|
+
const toolProfileIndex = items.findIndex((item) => item.id === "tool-profile");
|
|
312
|
+
items.splice(toolProfileIndex + 1, 0, {
|
|
282
313
|
id: "codex-rotate",
|
|
283
314
|
label: "Codex rotate",
|
|
284
315
|
description: "Enable automatic Codex account rotation extension",
|
|
@@ -430,6 +461,12 @@ export class SettingsSelectorComponent extends Container {
|
|
|
430
461
|
case "plan-mode-coding-model":
|
|
431
462
|
callbacks.onPlanModeCodingModelChange(newValue);
|
|
432
463
|
break;
|
|
464
|
+
case "auto-suggest-plan-mode":
|
|
465
|
+
callbacks.onAutoSuggestPlanModeChange(newValue === "true");
|
|
466
|
+
break;
|
|
467
|
+
case "auto-switch-plan-model":
|
|
468
|
+
callbacks.onAutoSwitchPlanModelChange(newValue === "true");
|
|
469
|
+
break;
|
|
433
470
|
case "show-images":
|
|
434
471
|
callbacks.onShowImagesChange(newValue === "true");
|
|
435
472
|
break;
|
|
@@ -442,6 +479,9 @@ export class SettingsSelectorComponent extends Container {
|
|
|
442
479
|
case "skill-commands":
|
|
443
480
|
callbacks.onEnableSkillCommandsChange(newValue === "true");
|
|
444
481
|
break;
|
|
482
|
+
case "tool-profile":
|
|
483
|
+
callbacks.onToolProfileChange(newValue);
|
|
484
|
+
break;
|
|
445
485
|
case "codex-rotate":
|
|
446
486
|
callbacks.onCodexRotateChange(newValue === "true");
|
|
447
487
|
break;
|
|
@@ -472,6 +512,9 @@ export class SettingsSelectorComponent extends Container {
|
|
|
472
512
|
case "transport":
|
|
473
513
|
callbacks.onTransportChange(newValue);
|
|
474
514
|
break;
|
|
515
|
+
case "anthropic-adaptive-default":
|
|
516
|
+
callbacks.onAnthropicAdaptiveByDefaultChange(newValue === "true");
|
|
517
|
+
break;
|
|
475
518
|
case "hide-thinking":
|
|
476
519
|
callbacks.onHideThinkingBlockChange(newValue === "true");
|
|
477
520
|
break;
|