@hyperspaceng/neural-coding-agent 0.62.1 → 0.63.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 +143 -0
- package/README.md +10 -0
- package/dist/bun/register-bedrock.d.ts.map +1 -1
- package/dist/bun/register-bedrock.js +2 -2
- package/dist/bun/register-bedrock.js.map +1 -1
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +1 -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 +4 -0
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/initial-message.d.ts +1 -1
- package/dist/cli/initial-message.d.ts.map +1 -1
- package/dist/cli/initial-message.js.map +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js +1 -1
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/core/agent-session.d.ts +21 -11
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +159 -101
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +5 -3
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +7 -4
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +4 -2
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +3 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +5 -5
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +28 -27
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +2 -2
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/defaults.d.ts +1 -1
- package/dist/core/defaults.d.ts.map +1 -1
- package/dist/core/defaults.js.map +1 -1
- package/dist/core/export-html/index.d.ts +3 -3
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +7 -6
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts +2 -2
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +41 -16
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +3 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +27 -17
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +7 -10
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +27 -38
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +56 -15
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts +1 -1
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +2 -8
- package/dist/core/extensions/wrapper.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 +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +2 -2
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +1 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts +3 -3
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts +19 -3
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +85 -71
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +2 -2
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +5 -5
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/output-guard.d.ts +6 -0
- package/dist/core/output-guard.d.ts.map +1 -0
- package/dist/core/output-guard.js +59 -0
- package/dist/core/output-guard.js.map +1 -0
- package/dist/core/package-manager.d.ts +3 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +153 -29
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +2 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +30 -32
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts +6 -0
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +37 -5
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts +6 -5
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +136 -108
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +4 -4
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +15 -24
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +2 -2
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +3 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +2 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +25 -1
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts +2 -3
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/source-info.d.ts +18 -0
- package/dist/core/source-info.d.ts.map +1 -0
- package/dist/core/source-info.js +19 -0
- package/dist/core/source-info.js.map +1 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +3 -38
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/timings.d.ts +1 -0
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js +6 -0
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/bash.d.ts +20 -10
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +151 -59
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +23 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +150 -57
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +31 -7
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +179 -59
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js +4 -4
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.d.ts +12 -5
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +76 -27
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +16 -5
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +83 -29
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +68 -22
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +50 -26
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +10 -4
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +67 -13
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts +11 -4
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +110 -51
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +21 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -0
- package/dist/core/tools/render-utils.js +49 -0
- package/dist/core/tools/render-utils.js.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.js +30 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
- package/dist/core/tools/write.d.ts +10 -4
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +162 -27
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +57 -19
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/armin.d.ts +1 -1
- package/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +2 -2
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +1 -1
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +1 -2
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +19 -6
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +1 -1
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +1 -1
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +1 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +1 -1
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/daxnuts.d.ts +1 -1
- package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
- package/dist/modes/interactive/components/daxnuts.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +1 -1
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +1 -1
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +1 -1
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +2 -2
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +2 -2
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +2 -2
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +2 -2
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +2 -2
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +1 -1
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -3
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +1 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +1 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +1 -1
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts +2 -2
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +1 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +15 -41
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +121 -679
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +1 -1
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +1 -1
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +1 -1
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.js +1 -1
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +5 -13
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +175 -160
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts +5 -2
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +15 -1
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts +2 -2
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +84 -78
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +2 -2
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +27 -20
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +5 -6
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/image-resize.d.ts +6 -6
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +45 -94
- package/dist/utils/image-resize.js.map +1 -1
- package/docs/development.md +3 -1
- package/docs/extensions.md +85 -34
- package/docs/models.md +6 -0
- package/docs/rpc.md +11 -2
- package/docs/settings.md +12 -0
- package/docs/skills.md +3 -2
- package/docs/tui.md +2 -2
- package/examples/extensions/built-in-tool-renderer.ts +8 -8
- package/examples/extensions/commands.ts +3 -3
- package/examples/extensions/custom-compaction.ts +17 -4
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +17 -17
- package/examples/extensions/custom-provider-gitlab-duo/package.json +14 -14
- package/examples/extensions/custom-provider-qwen-cli/package.json +14 -14
- package/examples/extensions/handoff.ts +5 -2
- package/examples/extensions/minimal-mode.ts +14 -14
- package/examples/extensions/qna.ts +5 -2
- package/examples/extensions/question.ts +2 -2
- package/examples/extensions/questionnaire.ts +2 -2
- package/examples/extensions/subagent/index.ts +23 -3
- package/examples/extensions/summarize.ts +15 -4
- package/examples/extensions/todo.ts +2 -2
- package/examples/extensions/trigger-compact.ts +11 -1
- package/examples/extensions/truncated-tool.ts +2 -2
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +20 -20
- package/examples/sdk/04-skills.ts +8 -2
- package/examples/sdk/08-prompt-templates.ts +2 -1
- package/examples/sdk/12-full-control.ts +0 -1
- package/package.json +5 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/core/tools/read.ts"],"names":[],"mappings":"AAEA,OAAO,EAAe,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,QAAQ,IAAI,UAAU,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/E,OAAO,EAAE,oCAAoC,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,UAAU,EAAyB,YAAY,EAAE,MAAM,eAAe,CAAC;AAEtH,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,iDAAiD,EAAE,CAAC;IACrF,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,+CAA+C,EAAE,CAAC,CAAC;IACpG,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,iCAAiC,EAAE,CAAC,CAAC;CACrF,CAAC,CAAC;AAqBH,MAAM,qBAAqB,GAAmB;IAC7C,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;IACpC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC;IAChD,mBAAmB,EAAE,oCAAoC;CACzD,CAAC;AASF,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,OAAyB,EAAgC;IACpG,MAAM,gBAAgB,GAAG,OAAO,EAAE,gBAAgB,IAAI,IAAI,CAAC;IAC3D,MAAM,GAAG,GAAG,OAAO,EAAE,UAAU,IAAI,qBAAqB,CAAC;IAEzD,OAAO;QACN,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;QACb,WAAW,EAAE,6JAA6J,iBAAiB,aAAa,iBAAiB,GAAG,IAAI,kIAAkI;QAClW,UAAU,EAAE,UAAU;QACtB,OAAO,EAAE,KAAK,EACb,WAAmB,EACnB,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAqD,EAC1E,MAAoB,EACnB,EAAE,CAAC;YACJ,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAEhD,OAAO,IAAI,OAAO,CACjB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;gBACpB,2BAA2B;gBAC3B,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;oBACrB,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;oBACvC,OAAO;gBACR,CAAC;gBAED,IAAI,OAAO,GAAG,KAAK,CAAC;gBAEpB,uBAAuB;gBACvB,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;oBACrB,OAAO,GAAG,IAAI,CAAC;oBACf,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;gBAAA,CACvC,CAAC;gBAEF,IAAI,MAAM,EAAE,CAAC;oBACZ,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC3D,CAAC;gBAED,6BAA6B;gBAC7B,CAAC,KAAK,IAAI,EAAE,CAAC;oBACZ,IAAI,CAAC;wBACJ,uBAAuB;wBACvB,MAAM,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;wBAE/B,kCAAkC;wBAClC,IAAI,OAAO,EAAE,CAAC;4BACb,OAAO;wBACR,CAAC;wBAED,MAAM,QAAQ,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;wBAEnG,8BAA8B;wBAC9B,IAAI,OAAuC,CAAC;wBAC5C,IAAI,OAAoC,CAAC;wBAEzC,IAAI,QAAQ,EAAE,CAAC;4BACd,yBAAyB;4BACzB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;4BAChD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;4BAEzC,IAAI,gBAAgB,EAAE,CAAC;gCACtB,yBAAyB;gCACzB,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;gCAC7E,MAAM,aAAa,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;gCAEnD,IAAI,QAAQ,GAAG,oBAAoB,OAAO,CAAC,QAAQ,GAAG,CAAC;gCACvD,IAAI,aAAa,EAAE,CAAC;oCACnB,QAAQ,IAAI,KAAK,aAAa,EAAE,CAAC;gCAClC,CAAC;gCAED,OAAO,GAAG;oCACT,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;oCAChC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE;iCACjE,CAAC;4BACH,CAAC;iCAAM,CAAC;gCACP,MAAM,QAAQ,GAAG,oBAAoB,QAAQ,GAAG,CAAC;gCACjD,OAAO,GAAG;oCACT,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;oCAChC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE;iCACzC,CAAC;4BACH,CAAC;wBACF,CAAC;6BAAM,CAAC;4BACP,eAAe;4BACf,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;4BAChD,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;4BAC7C,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;4BACzC,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC;4BAEvC,qDAAqD;4BACrD,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;4BACvD,MAAM,gBAAgB,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,0BAA0B;4BAElE,mCAAmC;4BACnC,IAAI,SAAS,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gCAClC,MAAM,IAAI,KAAK,CAAC,UAAU,MAAM,2BAA2B,QAAQ,CAAC,MAAM,eAAe,CAAC,CAAC;4BAC5F,CAAC;4BAED,iFAAiF;4BACjF,IAAI,eAAuB,CAAC;4BAC5B,IAAI,gBAAoC,CAAC;4BACzC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gCACzB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;gCAC7D,eAAe,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gCAChE,gBAAgB,GAAG,OAAO,GAAG,SAAS,CAAC;4BACxC,CAAC;iCAAM,CAAC;gCACP,eAAe,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;4BACxD,CAAC;4BAED,wDAAwD;4BACxD,MAAM,UAAU,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;4BAEjD,IAAI,UAAkB,CAAC;4BAEvB,IAAI,UAAU,CAAC,qBAAqB,EAAE,CAAC;gCACtC,6DAA6D;gCAC7D,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;gCAClF,UAAU,GAAG,SAAS,gBAAgB,OAAO,aAAa,aAAa,UAAU,CAAC,iBAAiB,CAAC,6BAA6B,gBAAgB,MAAM,IAAI,cAAc,iBAAiB,GAAG,CAAC;gCAC9L,OAAO,GAAG,EAAE,UAAU,EAAE,CAAC;4BAC1B,CAAC;iCAAM,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;gCACjC,gDAAgD;gCAChD,MAAM,cAAc,GAAG,gBAAgB,GAAG,UAAU,CAAC,WAAW,GAAG,CAAC,CAAC;gCACrE,MAAM,UAAU,GAAG,cAAc,GAAG,CAAC,CAAC;gCAEtC,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC;gCAEhC,IAAI,UAAU,CAAC,WAAW,KAAK,OAAO,EAAE,CAAC;oCACxC,UAAU,IAAI,sBAAsB,gBAAgB,IAAI,cAAc,OAAO,cAAc,gBAAgB,UAAU,gBAAgB,CAAC;gCACvI,CAAC;qCAAM,CAAC;oCACP,UAAU,IAAI,sBAAsB,gBAAgB,IAAI,cAAc,OAAO,cAAc,KAAK,UAAU,CAAC,iBAAiB,CAAC,uBAAuB,UAAU,gBAAgB,CAAC;gCAChL,CAAC;gCACD,OAAO,GAAG,EAAE,UAAU,EAAE,CAAC;4BAC1B,CAAC;iCAAM,IAAI,gBAAgB,KAAK,SAAS,IAAI,SAAS,GAAG,gBAAgB,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;gCAC7F,gEAAgE;gCAChE,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,SAAS,GAAG,gBAAgB,CAAC,CAAC;gCACnE,MAAM,UAAU,GAAG,SAAS,GAAG,gBAAgB,GAAG,CAAC,CAAC;gCAEpD,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC;gCAChC,UAAU,IAAI,QAAQ,SAAS,mCAAmC,UAAU,gBAAgB,CAAC;4BAC9F,CAAC;iCAAM,CAAC;gCACP,wCAAwC;gCACxC,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC;4BACjC,CAAC;4BAED,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;wBAChD,CAAC;wBAED,iCAAiC;wBACjC,IAAI,OAAO,EAAE,CAAC;4BACb,OAAO;wBACR,CAAC;wBAED,yBAAyB;wBACzB,IAAI,MAAM,EAAE,CAAC;4BACZ,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;wBAC9C,CAAC;wBAED,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;oBAC/B,CAAC;oBAAC,OAAO,KAAU,EAAE,CAAC;wBACrB,yBAAyB;wBACzB,IAAI,MAAM,EAAE,CAAC;4BACZ,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;wBAC9C,CAAC;wBAED,IAAI,CAAC,OAAO,EAAE,CAAC;4BACd,MAAM,CAAC,KAAK,CAAC,CAAC;wBACf,CAAC;oBACF,CAAC;gBAAA,CACD,CAAC,EAAE,CAAC;YAAA,CACL,CACD,CAAC;QAAA,CACF;KACD,CAAC;AAAA,CACF;AAED,0EAA0E;AAC1E,MAAM,CAAC,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC","sourcesContent":["import type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport type { ImageContent, TextContent } from \"@mariozechner/pi-ai\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile } from \"fs/promises\";\nimport { formatDimensionNote, resizeImage } from \"../../utils/image-resize.js\";\nimport { detectSupportedImageMimeTypeFromFile } from \"../../utils/mime.js\";\nimport { resolveReadPath } from \"./path-utils.js\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult, truncateHead } from \"./truncate.js\";\n\nconst readSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to read (relative or absolute)\" }),\n\toffset: Type.Optional(Type.Number({ description: \"Line number to start reading from (1-indexed)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of lines to read\" })),\n});\n\nexport type ReadToolInput = Static<typeof readSchema>;\n\nexport interface ReadToolDetails {\n\ttruncation?: TruncationResult;\n}\n\n/**\n * Pluggable operations for the read tool.\n * Override these to delegate file reading to remote systems (e.g., SSH).\n */\nexport interface ReadOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Check if file is readable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n\t/** Detect image MIME type, return null/undefined for non-images */\n\tdetectImageMimeType?: (absolutePath: string) => Promise<string | null | undefined>;\n}\n\nconst defaultReadOperations: ReadOperations = {\n\treadFile: (path) => fsReadFile(path),\n\taccess: (path) => fsAccess(path, constants.R_OK),\n\tdetectImageMimeType: detectSupportedImageMimeTypeFromFile,\n};\n\nexport interface ReadToolOptions {\n\t/** Whether to auto-resize images to 2000x2000 max. Default: true */\n\tautoResizeImages?: boolean;\n\t/** Custom operations for file reading. Default: local filesystem */\n\toperations?: ReadOperations;\n}\n\nexport function createReadTool(cwd: string, options?: ReadToolOptions): AgentTool<typeof readSchema> {\n\tconst autoResizeImages = options?.autoResizeImages ?? true;\n\tconst ops = options?.operations ?? defaultReadOperations;\n\n\treturn {\n\t\tname: \"read\",\n\t\tlabel: \"read\",\n\t\tdescription: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.`,\n\t\tparameters: readSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ path, offset, limit }: { path: string; offset?: number; limit?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t) => {\n\t\t\tconst absolutePath = resolveReadPath(path, cwd);\n\n\t\t\treturn new Promise<{ content: (TextContent | ImageContent)[]; details: ReadToolDetails | undefined }>(\n\t\t\t\t(resolve, reject) => {\n\t\t\t\t\t// Check if already aborted\n\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet aborted = false;\n\n\t\t\t\t\t// Set up abort handler\n\t\t\t\t\tconst onAbort = () => {\n\t\t\t\t\t\taborted = true;\n\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t};\n\n\t\t\t\t\tif (signal) {\n\t\t\t\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t\t}\n\n\t\t\t\t\t// Perform the read operation\n\t\t\t\t\t(async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Check if file exists\n\t\t\t\t\t\t\tawait ops.access(absolutePath);\n\n\t\t\t\t\t\t\t// Check if aborted before reading\n\t\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst mimeType = ops.detectImageMimeType ? await ops.detectImageMimeType(absolutePath) : undefined;\n\n\t\t\t\t\t\t\t// Read the file based on type\n\t\t\t\t\t\t\tlet content: (TextContent | ImageContent)[];\n\t\t\t\t\t\t\tlet details: ReadToolDetails | undefined;\n\n\t\t\t\t\t\t\tif (mimeType) {\n\t\t\t\t\t\t\t\t// Read as image (binary)\n\t\t\t\t\t\t\t\tconst buffer = await ops.readFile(absolutePath);\n\t\t\t\t\t\t\t\tconst base64 = buffer.toString(\"base64\");\n\n\t\t\t\t\t\t\t\tif (autoResizeImages) {\n\t\t\t\t\t\t\t\t\t// Resize image if needed\n\t\t\t\t\t\t\t\t\tconst resized = await resizeImage({ type: \"image\", data: base64, mimeType });\n\t\t\t\t\t\t\t\t\tconst dimensionNote = formatDimensionNote(resized);\n\n\t\t\t\t\t\t\t\t\tlet textNote = `Read image file [${resized.mimeType}]`;\n\t\t\t\t\t\t\t\t\tif (dimensionNote) {\n\t\t\t\t\t\t\t\t\t\ttextNote += `\\n${dimensionNote}`;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tcontent = [\n\t\t\t\t\t\t\t\t\t\t{ type: \"text\", text: textNote },\n\t\t\t\t\t\t\t\t\t\t{ type: \"image\", data: resized.data, mimeType: resized.mimeType },\n\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tconst textNote = `Read image file [${mimeType}]`;\n\t\t\t\t\t\t\t\t\tcontent = [\n\t\t\t\t\t\t\t\t\t\t{ type: \"text\", text: textNote },\n\t\t\t\t\t\t\t\t\t\t{ type: \"image\", data: base64, mimeType },\n\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Read as text\n\t\t\t\t\t\t\t\tconst buffer = await ops.readFile(absolutePath);\n\t\t\t\t\t\t\t\tconst textContent = buffer.toString(\"utf-8\");\n\t\t\t\t\t\t\t\tconst allLines = textContent.split(\"\\n\");\n\t\t\t\t\t\t\t\tconst totalFileLines = allLines.length;\n\n\t\t\t\t\t\t\t\t// Apply offset if specified (1-indexed to 0-indexed)\n\t\t\t\t\t\t\t\tconst startLine = offset ? Math.max(0, offset - 1) : 0;\n\t\t\t\t\t\t\t\tconst startLineDisplay = startLine + 1; // For display (1-indexed)\n\n\t\t\t\t\t\t\t\t// Check if offset is out of bounds\n\t\t\t\t\t\t\t\tif (startLine >= allLines.length) {\n\t\t\t\t\t\t\t\t\tthrow new Error(`Offset ${offset} is beyond end of file (${allLines.length} lines total)`);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If limit is specified by user, use it; otherwise we'll let truncateHead decide\n\t\t\t\t\t\t\t\tlet selectedContent: string;\n\t\t\t\t\t\t\t\tlet userLimitedLines: number | undefined;\n\t\t\t\t\t\t\t\tif (limit !== undefined) {\n\t\t\t\t\t\t\t\t\tconst endLine = Math.min(startLine + limit, allLines.length);\n\t\t\t\t\t\t\t\t\tselectedContent = allLines.slice(startLine, endLine).join(\"\\n\");\n\t\t\t\t\t\t\t\t\tuserLimitedLines = endLine - startLine;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tselectedContent = allLines.slice(startLine).join(\"\\n\");\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Apply truncation (respects both line and byte limits)\n\t\t\t\t\t\t\t\tconst truncation = truncateHead(selectedContent);\n\n\t\t\t\t\t\t\t\tlet outputText: string;\n\n\t\t\t\t\t\t\t\tif (truncation.firstLineExceedsLimit) {\n\t\t\t\t\t\t\t\t\t// First line at offset exceeds 30KB - tell model to use bash\n\t\t\t\t\t\t\t\t\tconst firstLineSize = formatSize(Buffer.byteLength(allLines[startLine], \"utf-8\"));\n\t\t\t\t\t\t\t\t\toutputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(DEFAULT_MAX_BYTES)} limit. Use bash: sed -n '${startLineDisplay}p' ${path} | head -c ${DEFAULT_MAX_BYTES}]`;\n\t\t\t\t\t\t\t\t\tdetails = { truncation };\n\t\t\t\t\t\t\t\t} else if (truncation.truncated) {\n\t\t\t\t\t\t\t\t\t// Truncation occurred - build actionable notice\n\t\t\t\t\t\t\t\t\tconst endLineDisplay = startLineDisplay + truncation.outputLines - 1;\n\t\t\t\t\t\t\t\t\tconst nextOffset = endLineDisplay + 1;\n\n\t\t\t\t\t\t\t\t\toutputText = truncation.content;\n\n\t\t\t\t\t\t\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tdetails = { truncation };\n\t\t\t\t\t\t\t\t} else if (userLimitedLines !== undefined && startLine + userLimitedLines < allLines.length) {\n\t\t\t\t\t\t\t\t\t// User specified limit, there's more content, but no truncation\n\t\t\t\t\t\t\t\t\tconst remaining = allLines.length - (startLine + userLimitedLines);\n\t\t\t\t\t\t\t\t\tconst nextOffset = startLine + userLimitedLines + 1;\n\n\t\t\t\t\t\t\t\t\toutputText = truncation.content;\n\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[${remaining} more lines in file. Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// No truncation, no user limit exceeded\n\t\t\t\t\t\t\t\t\toutputText = truncation.content;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcontent = [{ type: \"text\", text: outputText }];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Check if aborted after reading\n\t\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Clean up abort handler\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tresolve({ content, details });\n\t\t\t\t\t\t} catch (error: any) {\n\t\t\t\t\t\t\t// Clean up abort handler\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!aborted) {\n\t\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t})();\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t};\n}\n\n/** Default read tool using process.cwd() - for backwards compatibility */\nexport const readTool = createReadTool(process.cwd());\n"]}
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/core/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@hyperspaceng/neural-agent-core\";\nimport type { ImageContent, TextContent } from \"@hyperspaceng/neural-ai\";\nimport { Text } from \"@hyperspaceng/neural-tui\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile } from \"fs/promises\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.js\";\nimport { getLanguageFromPath, highlightCode } from \"../../modes/interactive/theme/theme.js\";\nimport { formatDimensionNote, resizeImage } from \"../../utils/image-resize.js\";\nimport { detectSupportedImageMimeTypeFromFile } from \"../../utils/mime.js\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.js\";\nimport { resolveReadPath } from \"./path-utils.js\";\nimport { getTextOutput, invalidArgText, replaceTabs, shortenPath, str } from \"./render-utils.js\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.js\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult, truncateHead } from \"./truncate.js\";\n\nconst readSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to read (relative or absolute)\" }),\n\toffset: Type.Optional(Type.Number({ description: \"Line number to start reading from (1-indexed)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of lines to read\" })),\n});\n\nexport type ReadToolInput = Static<typeof readSchema>;\n\nexport interface ReadToolDetails {\n\ttruncation?: TruncationResult;\n}\n\n/**\n * Pluggable operations for the read tool.\n * Override these to delegate file reading to remote systems (for example SSH).\n */\nexport interface ReadOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Check if file is readable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n\t/** Detect image MIME type, return null or undefined for non-images */\n\tdetectImageMimeType?: (absolutePath: string) => Promise<string | null | undefined>;\n}\n\nconst defaultReadOperations: ReadOperations = {\n\treadFile: (path) => fsReadFile(path),\n\taccess: (path) => fsAccess(path, constants.R_OK),\n\tdetectImageMimeType: detectSupportedImageMimeTypeFromFile,\n};\n\nexport interface ReadToolOptions {\n\t/** Whether to auto-resize images to 2000x2000 max. Default: true */\n\tautoResizeImages?: boolean;\n\t/** Custom operations for file reading. Default: local filesystem */\n\toperations?: ReadOperations;\n}\n\nfunction formatReadCall(\n\targs: { path?: string; file_path?: string; offset?: number; limit?: number } | undefined,\n\ttheme: typeof import(\"../../modes/interactive/theme/theme.js\").theme,\n): string {\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tconst path = rawPath !== null ? shortenPath(rawPath) : null;\n\tconst offset = args?.offset;\n\tconst limit = args?.limit;\n\tconst invalidArg = invalidArgText(theme);\n\tlet pathDisplay = path === null ? invalidArg : path ? theme.fg(\"accent\", path) : theme.fg(\"toolOutput\", \"...\");\n\tif (offset !== undefined || limit !== undefined) {\n\t\tconst startLine = offset ?? 1;\n\t\tconst endLine = limit !== undefined ? startLine + limit - 1 : \"\";\n\t\tpathDisplay += theme.fg(\"warning\", `:${startLine}${endLine ? `-${endLine}` : \"\"}`);\n\t}\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"read\"))} ${pathDisplay}`;\n}\n\nfunction trimTrailingEmptyLines(lines: string[]): string[] {\n\tlet end = lines.length;\n\twhile (end > 0 && lines[end - 1] === \"\") {\n\t\tend--;\n\t}\n\treturn lines.slice(0, end);\n}\n\nfunction formatReadResult(\n\targs: { path?: string; file_path?: string; offset?: number; limit?: number } | undefined,\n\tresult: { content: (TextContent | ImageContent)[]; details?: ReadToolDetails },\n\toptions: ToolRenderResultOptions,\n\ttheme: typeof import(\"../../modes/interactive/theme/theme.js\").theme,\n\tshowImages: boolean,\n): string {\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tconst output = getTextOutput(result as any, showImages);\n\tconst lang = rawPath ? getLanguageFromPath(rawPath) : undefined;\n\tconst renderedLines = lang ? highlightCode(replaceTabs(output), lang) : output.split(\"\\n\");\n\tconst lines = trimTrailingEmptyLines(renderedLines);\n\tconst maxLines = options.expanded ? lines.length : 10;\n\tconst displayLines = lines.slice(0, maxLines);\n\tconst remaining = lines.length - maxLines;\n\tlet text = `\\n${displayLines.map((line) => (lang ? replaceTabs(line) : theme.fg(\"toolOutput\", replaceTabs(line)))).join(\"\\n\")}`;\n\tif (remaining > 0) {\n\t\ttext += `${theme.fg(\"muted\", `\\n... (${remaining} more lines,`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t}\n\n\tconst truncation = result.details?.truncation;\n\tif (truncation?.truncated) {\n\t\tif (truncation.firstLineExceedsLimit) {\n\t\t\ttext += `\\n${theme.fg(\"warning\", `[First line exceeds ${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit]`)}`;\n\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\ttext += `\\n${theme.fg(\"warning\", `[Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines (${truncation.maxLines ?? DEFAULT_MAX_LINES} line limit)]`)}`;\n\t\t} else {\n\t\t\ttext += `\\n${theme.fg(\"warning\", `[Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)]`)}`;\n\t\t}\n\t}\n\treturn text;\n}\n\nexport function createReadToolDefinition(\n\tcwd: string,\n\toptions?: ReadToolOptions,\n): ToolDefinition<typeof readSchema, ReadToolDetails | undefined> {\n\tconst autoResizeImages = options?.autoResizeImages ?? true;\n\tconst ops = options?.operations ?? defaultReadOperations;\n\treturn {\n\t\tname: \"read\",\n\t\tlabel: \"read\",\n\t\tdescription: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.`,\n\t\tpromptSnippet: \"Read file contents\",\n\t\tpromptGuidelines: [\"Use read to examine files instead of cat or sed.\"],\n\t\tparameters: readSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ path, offset, limit }: { path: string; offset?: number; limit?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\t_ctx?,\n\t\t) {\n\t\t\tconst absolutePath = resolveReadPath(path, cwd);\n\t\t\treturn new Promise<{ content: (TextContent | ImageContent)[]; details: ReadToolDetails | undefined }>(\n\t\t\t\t(resolve, reject) => {\n\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tlet aborted = false;\n\t\t\t\t\tconst onAbort = () => {\n\t\t\t\t\t\taborted = true;\n\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t};\n\t\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\t\t\t(async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Check if file exists and is readable.\n\t\t\t\t\t\t\tawait ops.access(absolutePath);\n\t\t\t\t\t\t\tif (aborted) return;\n\t\t\t\t\t\t\tconst mimeType = ops.detectImageMimeType ? await ops.detectImageMimeType(absolutePath) : undefined;\n\t\t\t\t\t\t\tlet content: (TextContent | ImageContent)[];\n\t\t\t\t\t\t\tlet details: ReadToolDetails | undefined;\n\t\t\t\t\t\t\tif (mimeType) {\n\t\t\t\t\t\t\t\t// Read image as binary.\n\t\t\t\t\t\t\t\tconst buffer = await ops.readFile(absolutePath);\n\t\t\t\t\t\t\t\tconst base64 = buffer.toString(\"base64\");\n\t\t\t\t\t\t\t\tif (autoResizeImages) {\n\t\t\t\t\t\t\t\t\t// Resize image if needed before sending it back to the model.\n\t\t\t\t\t\t\t\t\tconst resized = await resizeImage({ type: \"image\", data: base64, mimeType });\n\t\t\t\t\t\t\t\t\tif (!resized) {\n\t\t\t\t\t\t\t\t\t\tcontent = [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\t\t\t\ttext: `Read image file [${mimeType}]\\n[Image omitted: could not be resized below the inline image size limit.]`,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tconst dimensionNote = formatDimensionNote(resized);\n\t\t\t\t\t\t\t\t\t\tlet textNote = `Read image file [${resized.mimeType}]`;\n\t\t\t\t\t\t\t\t\t\tif (dimensionNote) textNote += `\\n${dimensionNote}`;\n\t\t\t\t\t\t\t\t\t\tcontent = [\n\t\t\t\t\t\t\t\t\t\t\t{ type: \"text\", text: textNote },\n\t\t\t\t\t\t\t\t\t\t\t{ type: \"image\", data: resized.data, mimeType: resized.mimeType },\n\t\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcontent = [\n\t\t\t\t\t\t\t\t\t\t{ type: \"text\", text: `Read image file [${mimeType}]` },\n\t\t\t\t\t\t\t\t\t\t{ type: \"image\", data: base64, mimeType },\n\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Read text content.\n\t\t\t\t\t\t\t\tconst buffer = await ops.readFile(absolutePath);\n\t\t\t\t\t\t\t\tconst textContent = buffer.toString(\"utf-8\");\n\t\t\t\t\t\t\t\tconst allLines = textContent.split(\"\\n\");\n\t\t\t\t\t\t\t\tconst totalFileLines = allLines.length;\n\t\t\t\t\t\t\t\t// Apply offset if specified. Convert from 1-indexed input to 0-indexed array access.\n\t\t\t\t\t\t\t\tconst startLine = offset ? Math.max(0, offset - 1) : 0;\n\t\t\t\t\t\t\t\tconst startLineDisplay = startLine + 1;\n\t\t\t\t\t\t\t\t// Check if offset is out of bounds.\n\t\t\t\t\t\t\t\tif (startLine >= allLines.length) {\n\t\t\t\t\t\t\t\t\tthrow new Error(`Offset ${offset} is beyond end of file (${allLines.length} lines total)`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tlet selectedContent: string;\n\t\t\t\t\t\t\t\tlet userLimitedLines: number | undefined;\n\t\t\t\t\t\t\t\t// If limit is specified by the user, honor it first. Otherwise truncateHead decides.\n\t\t\t\t\t\t\t\tif (limit !== undefined) {\n\t\t\t\t\t\t\t\t\tconst endLine = Math.min(startLine + limit, allLines.length);\n\t\t\t\t\t\t\t\t\tselectedContent = allLines.slice(startLine, endLine).join(\"\\n\");\n\t\t\t\t\t\t\t\t\tuserLimitedLines = endLine - startLine;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tselectedContent = allLines.slice(startLine).join(\"\\n\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Apply truncation, respecting both line and byte limits.\n\t\t\t\t\t\t\t\tconst truncation = truncateHead(selectedContent);\n\t\t\t\t\t\t\t\tlet outputText: string;\n\t\t\t\t\t\t\t\tif (truncation.firstLineExceedsLimit) {\n\t\t\t\t\t\t\t\t\t// First line alone exceeds the byte limit. Point the model at a bash fallback.\n\t\t\t\t\t\t\t\t\tconst firstLineSize = formatSize(Buffer.byteLength(allLines[startLine], \"utf-8\"));\n\t\t\t\t\t\t\t\t\toutputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(DEFAULT_MAX_BYTES)} limit. Use bash: sed -n '${startLineDisplay}p' ${path} | head -c ${DEFAULT_MAX_BYTES}]`;\n\t\t\t\t\t\t\t\t\tdetails = { truncation };\n\t\t\t\t\t\t\t\t} else if (truncation.truncated) {\n\t\t\t\t\t\t\t\t\t// Truncation occurred. Build an actionable continuation notice.\n\t\t\t\t\t\t\t\t\tconst endLineDisplay = startLineDisplay + truncation.outputLines - 1;\n\t\t\t\t\t\t\t\t\tconst nextOffset = endLineDisplay + 1;\n\t\t\t\t\t\t\t\t\toutputText = truncation.content;\n\t\t\t\t\t\t\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tdetails = { truncation };\n\t\t\t\t\t\t\t\t} else if (userLimitedLines !== undefined && startLine + userLimitedLines < allLines.length) {\n\t\t\t\t\t\t\t\t\t// User-specified limit stopped early, but the file still has more content.\n\t\t\t\t\t\t\t\t\tconst remaining = allLines.length - (startLine + userLimitedLines);\n\t\t\t\t\t\t\t\t\tconst nextOffset = startLine + userLimitedLines + 1;\n\t\t\t\t\t\t\t\t\toutputText = `${truncation.content}\\n\\n[${remaining} more lines in file. Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// No truncation and no remaining user-limited content.\n\t\t\t\t\t\t\t\t\toutputText = truncation.content;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcontent = [{ type: \"text\", text: outputText }];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (aborted) return;\n\t\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\tresolve({ content, details });\n\t\t\t\t\t\t} catch (error: any) {\n\t\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\tif (!aborted) reject(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t})();\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatReadCall(args, theme));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatReadResult(context.args, result as any, options, theme, context.showImages));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createReadTool(cwd: string, options?: ReadToolOptions): AgentTool<typeof readSchema> {\n\treturn wrapToolDefinition(createReadToolDefinition(cwd, options));\n}\n\n/** Default read tool using process.cwd() for backwards compatibility. */\nexport const readToolDefinition = createReadToolDefinition(process.cwd());\nexport const readTool = createReadTool(process.cwd());\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ImageContent, TextContent } from "@hyperspaceng/neural-ai";
|
|
2
|
+
export declare function shortenPath(path: unknown): string;
|
|
3
|
+
export declare function str(value: unknown): string | null;
|
|
4
|
+
export declare function replaceTabs(text: string): string;
|
|
5
|
+
export declare function normalizeDisplayText(text: string): string;
|
|
6
|
+
export declare function getTextOutput(result: {
|
|
7
|
+
content: Array<{
|
|
8
|
+
type: string;
|
|
9
|
+
text?: string;
|
|
10
|
+
data?: string;
|
|
11
|
+
mimeType?: string;
|
|
12
|
+
}>;
|
|
13
|
+
} | undefined, showImages: boolean): string;
|
|
14
|
+
export type ToolRenderResultLike<TDetails> = {
|
|
15
|
+
content: (TextContent | ImageContent)[];
|
|
16
|
+
details: TDetails;
|
|
17
|
+
};
|
|
18
|
+
export declare function invalidArgText(theme: {
|
|
19
|
+
fg: (name: any, text: string) => string;
|
|
20
|
+
}): string;
|
|
21
|
+
//# sourceMappingURL=render-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-utils.d.ts","sourceRoot":"","sources":["../../../src/core/tools/render-utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAKrE,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAOjD;AAED,wBAAgB,GAAG,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAIjD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,aAAa,CAC5B,MAAM,EAAE;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,SAAS,EACzG,UAAU,EAAE,OAAO,GACjB,MAAM,CAsBR;AAED,MAAM,MAAM,oBAAoB,CAAC,QAAQ,IAAI;IAC5C,OAAO,EAAE,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,CAAC;IACxC,OAAO,EAAE,QAAQ,CAAC;CAClB,CAAC;AAEF,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,EAAE,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,GAAG,MAAM,CAEzF","sourcesContent":["import * as os from \"node:os\";\nimport type { ImageContent, TextContent } from \"@hyperspaceng/neural-ai\";\nimport { getCapabilities, getImageDimensions, imageFallback } from \"@hyperspaceng/neural-tui\";\nimport stripAnsi from \"strip-ansi\";\nimport { sanitizeBinaryOutput } from \"../../utils/shell.js\";\n\nexport function shortenPath(path: unknown): string {\n\tif (typeof path !== \"string\") return \"\";\n\tconst home = os.homedir();\n\tif (path.startsWith(home)) {\n\t\treturn `~${path.slice(home.length)}`;\n\t}\n\treturn path;\n}\n\nexport function str(value: unknown): string | null {\n\tif (typeof value === \"string\") return value;\n\tif (value == null) return \"\";\n\treturn null;\n}\n\nexport function replaceTabs(text: string): string {\n\treturn text.replace(/\\t/g, \" \");\n}\n\nexport function normalizeDisplayText(text: string): string {\n\treturn text.replace(/\\r/g, \"\");\n}\n\nexport function getTextOutput(\n\tresult: { content: Array<{ type: string; text?: string; data?: string; mimeType?: string }> } | undefined,\n\tshowImages: boolean,\n): string {\n\tif (!result) return \"\";\n\n\tconst textBlocks = result.content.filter((c) => c.type === \"text\");\n\tconst imageBlocks = result.content.filter((c) => c.type === \"image\");\n\n\tlet output = textBlocks.map((c) => sanitizeBinaryOutput(stripAnsi(c.text || \"\")).replace(/\\r/g, \"\")).join(\"\\n\");\n\n\tconst caps = getCapabilities();\n\tif (imageBlocks.length > 0 && (!caps.images || !showImages)) {\n\t\tconst imageIndicators = imageBlocks\n\t\t\t.map((img) => {\n\t\t\t\tconst mimeType = img.mimeType ?? \"image/unknown\";\n\t\t\t\tconst dims =\n\t\t\t\t\timg.data && img.mimeType ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;\n\t\t\t\treturn imageFallback(mimeType, dims);\n\t\t\t})\n\t\t\t.join(\"\\n\");\n\t\toutput = output ? `${output}\\n${imageIndicators}` : imageIndicators;\n\t}\n\n\treturn output;\n}\n\nexport type ToolRenderResultLike<TDetails> = {\n\tcontent: (TextContent | ImageContent)[];\n\tdetails: TDetails;\n};\n\nexport function invalidArgText(theme: { fg: (name: any, text: string) => string }): string {\n\treturn theme.fg(\"error\", \"[invalid arg]\");\n}\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as os from "node:os";
|
|
2
|
+
import { getCapabilities, getImageDimensions, imageFallback } from "@hyperspaceng/neural-tui";
|
|
3
|
+
import stripAnsi from "strip-ansi";
|
|
4
|
+
import { sanitizeBinaryOutput } from "../../utils/shell.js";
|
|
5
|
+
export function shortenPath(path) {
|
|
6
|
+
if (typeof path !== "string")
|
|
7
|
+
return "";
|
|
8
|
+
const home = os.homedir();
|
|
9
|
+
if (path.startsWith(home)) {
|
|
10
|
+
return `~${path.slice(home.length)}`;
|
|
11
|
+
}
|
|
12
|
+
return path;
|
|
13
|
+
}
|
|
14
|
+
export function str(value) {
|
|
15
|
+
if (typeof value === "string")
|
|
16
|
+
return value;
|
|
17
|
+
if (value == null)
|
|
18
|
+
return "";
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
export function replaceTabs(text) {
|
|
22
|
+
return text.replace(/\t/g, " ");
|
|
23
|
+
}
|
|
24
|
+
export function normalizeDisplayText(text) {
|
|
25
|
+
return text.replace(/\r/g, "");
|
|
26
|
+
}
|
|
27
|
+
export function getTextOutput(result, showImages) {
|
|
28
|
+
if (!result)
|
|
29
|
+
return "";
|
|
30
|
+
const textBlocks = result.content.filter((c) => c.type === "text");
|
|
31
|
+
const imageBlocks = result.content.filter((c) => c.type === "image");
|
|
32
|
+
let output = textBlocks.map((c) => sanitizeBinaryOutput(stripAnsi(c.text || "")).replace(/\r/g, "")).join("\n");
|
|
33
|
+
const caps = getCapabilities();
|
|
34
|
+
if (imageBlocks.length > 0 && (!caps.images || !showImages)) {
|
|
35
|
+
const imageIndicators = imageBlocks
|
|
36
|
+
.map((img) => {
|
|
37
|
+
const mimeType = img.mimeType ?? "image/unknown";
|
|
38
|
+
const dims = img.data && img.mimeType ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;
|
|
39
|
+
return imageFallback(mimeType, dims);
|
|
40
|
+
})
|
|
41
|
+
.join("\n");
|
|
42
|
+
output = output ? `${output}\n${imageIndicators}` : imageIndicators;
|
|
43
|
+
}
|
|
44
|
+
return output;
|
|
45
|
+
}
|
|
46
|
+
export function invalidArgText(theme) {
|
|
47
|
+
return theme.fg("error", "[invalid arg]");
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=render-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-utils.js","sourceRoot":"","sources":["../../../src/core/tools/render-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import * as os from \"node:os\";\nimport type { ImageContent, TextContent } from \"@hyperspaceng/neural-ai\";\nimport { getCapabilities, getImageDimensions, imageFallback } from \"@hyperspaceng/neural-tui\";\nimport stripAnsi from \"strip-ansi\";\nimport { sanitizeBinaryOutput } from \"../../utils/shell.js\";\n\nexport function shortenPath(path: unknown): string {\n\tif (typeof path !== \"string\") return \"\";\n\tconst home = os.homedir();\n\tif (path.startsWith(home)) {\n\t\treturn `~${path.slice(home.length)}`;\n\t}\n\treturn path;\n}\n\nexport function str(value: unknown): string | null {\n\tif (typeof value === \"string\") return value;\n\tif (value == null) return \"\";\n\treturn null;\n}\n\nexport function replaceTabs(text: string): string {\n\treturn text.replace(/\\t/g, \" \");\n}\n\nexport function normalizeDisplayText(text: string): string {\n\treturn text.replace(/\\r/g, \"\");\n}\n\nexport function getTextOutput(\n\tresult: { content: Array<{ type: string; text?: string; data?: string; mimeType?: string }> } | undefined,\n\tshowImages: boolean,\n): string {\n\tif (!result) return \"\";\n\n\tconst textBlocks = result.content.filter((c) => c.type === \"text\");\n\tconst imageBlocks = result.content.filter((c) => c.type === \"image\");\n\n\tlet output = textBlocks.map((c) => sanitizeBinaryOutput(stripAnsi(c.text || \"\")).replace(/\\r/g, \"\")).join(\"\\n\");\n\n\tconst caps = getCapabilities();\n\tif (imageBlocks.length > 0 && (!caps.images || !showImages)) {\n\t\tconst imageIndicators = imageBlocks\n\t\t\t.map((img) => {\n\t\t\t\tconst mimeType = img.mimeType ?? \"image/unknown\";\n\t\t\t\tconst dims =\n\t\t\t\t\timg.data && img.mimeType ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;\n\t\t\t\treturn imageFallback(mimeType, dims);\n\t\t\t})\n\t\t\t.join(\"\\n\");\n\t\toutput = output ? `${output}\\n${imageIndicators}` : imageIndicators;\n\t}\n\n\treturn output;\n}\n\nexport type ToolRenderResultLike<TDetails> = {\n\tcontent: (TextContent | ImageContent)[];\n\tdetails: TDetails;\n};\n\nexport function invalidArgText(theme: { fg: (name: any, text: string) => string }): string {\n\treturn theme.fg(\"error\", \"[invalid arg]\");\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AgentTool } from "@hyperspaceng/neural-agent-core";
|
|
2
|
+
import type { ExtensionContext, ToolDefinition } from "../extensions/types.js";
|
|
3
|
+
/** Wrap a ToolDefinition into an AgentTool for the core runtime. */
|
|
4
|
+
export declare function wrapToolDefinition<TDetails = unknown>(definition: ToolDefinition<any, TDetails>, ctxFactory?: () => ExtensionContext): AgentTool<any, TDetails>;
|
|
5
|
+
/** Wrap multiple ToolDefinitions into AgentTools for the core runtime. */
|
|
6
|
+
export declare function wrapToolDefinitions(definitions: ToolDefinition<any, any>[], ctxFactory?: () => ExtensionContext): AgentTool<any>[];
|
|
7
|
+
/**
|
|
8
|
+
* Synthesize a minimal ToolDefinition from an AgentTool.
|
|
9
|
+
*
|
|
10
|
+
* This keeps AgentSession's internal registry definition-first even when a caller
|
|
11
|
+
* provides plain AgentTool overrides that do not include prompt metadata or renderers.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createToolDefinitionFromAgentTool(tool: AgentTool<any>): ToolDefinition<any, unknown>;
|
|
14
|
+
//# sourceMappingURL=tool-definition-wrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-definition-wrapper.d.ts","sourceRoot":"","sources":["../../../src/core/tools/tool-definition-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE/E,oEAAoE;AACpE,wBAAgB,kBAAkB,CAAC,QAAQ,GAAG,OAAO,EACpD,UAAU,EAAE,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,EACzC,UAAU,CAAC,EAAE,MAAM,gBAAgB,GACjC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,CAS1B;AAED,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAClC,WAAW,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EACvC,UAAU,CAAC,EAAE,MAAM,gBAAgB,GACjC,SAAS,CAAC,GAAG,CAAC,EAAE,CAElB;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAQpG","sourcesContent":["import type { AgentTool } from \"@hyperspaceng/neural-agent-core\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.js\";\n\n/** Wrap a ToolDefinition into an AgentTool for the core runtime. */\nexport function wrapToolDefinition<TDetails = unknown>(\n\tdefinition: ToolDefinition<any, TDetails>,\n\tctxFactory?: () => ExtensionContext,\n): AgentTool<any, TDetails> {\n\treturn {\n\t\tname: definition.name,\n\t\tlabel: definition.label,\n\t\tdescription: definition.description,\n\t\tparameters: definition.parameters,\n\t\texecute: (toolCallId, params, signal, onUpdate) =>\n\t\t\tdefinition.execute(toolCallId, params, signal, onUpdate, ctxFactory?.() as ExtensionContext),\n\t};\n}\n\n/** Wrap multiple ToolDefinitions into AgentTools for the core runtime. */\nexport function wrapToolDefinitions(\n\tdefinitions: ToolDefinition<any, any>[],\n\tctxFactory?: () => ExtensionContext,\n): AgentTool<any>[] {\n\treturn definitions.map((definition) => wrapToolDefinition(definition, ctxFactory));\n}\n\n/**\n * Synthesize a minimal ToolDefinition from an AgentTool.\n *\n * This keeps AgentSession's internal registry definition-first even when a caller\n * provides plain AgentTool overrides that do not include prompt metadata or renderers.\n */\nexport function createToolDefinitionFromAgentTool(tool: AgentTool<any>): ToolDefinition<any, unknown> {\n\treturn {\n\t\tname: tool.name,\n\t\tlabel: tool.label,\n\t\tdescription: tool.description,\n\t\tparameters: tool.parameters as any,\n\t\texecute: async (toolCallId, params, signal, onUpdate) => tool.execute(toolCallId, params, signal, onUpdate),\n\t};\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Wrap a ToolDefinition into an AgentTool for the core runtime. */
|
|
2
|
+
export function wrapToolDefinition(definition, ctxFactory) {
|
|
3
|
+
return {
|
|
4
|
+
name: definition.name,
|
|
5
|
+
label: definition.label,
|
|
6
|
+
description: definition.description,
|
|
7
|
+
parameters: definition.parameters,
|
|
8
|
+
execute: (toolCallId, params, signal, onUpdate) => definition.execute(toolCallId, params, signal, onUpdate, ctxFactory?.()),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/** Wrap multiple ToolDefinitions into AgentTools for the core runtime. */
|
|
12
|
+
export function wrapToolDefinitions(definitions, ctxFactory) {
|
|
13
|
+
return definitions.map((definition) => wrapToolDefinition(definition, ctxFactory));
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Synthesize a minimal ToolDefinition from an AgentTool.
|
|
17
|
+
*
|
|
18
|
+
* This keeps AgentSession's internal registry definition-first even when a caller
|
|
19
|
+
* provides plain AgentTool overrides that do not include prompt metadata or renderers.
|
|
20
|
+
*/
|
|
21
|
+
export function createToolDefinitionFromAgentTool(tool) {
|
|
22
|
+
return {
|
|
23
|
+
name: tool.name,
|
|
24
|
+
label: tool.label,
|
|
25
|
+
description: tool.description,
|
|
26
|
+
parameters: tool.parameters,
|
|
27
|
+
execute: async (toolCallId, params, signal, onUpdate) => tool.execute(toolCallId, params, signal, onUpdate),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=tool-definition-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-definition-wrapper.js","sourceRoot":"","sources":["../../../src/core/tools/tool-definition-wrapper.ts"],"names":[],"mappings":"AAGA,oEAAoE;AACpE,MAAM,UAAU,kBAAkB,CACjC,UAAyC,EACzC,UAAmC,EACR;IAC3B,OAAO;QACN,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,UAAU,EAAE,UAAU,CAAC,UAAU;QACjC,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CACjD,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAsB,CAAC;KAC7F,CAAC;AAAA,CACF;AAED,0EAA0E;AAC1E,MAAM,UAAU,mBAAmB,CAClC,WAAuC,EACvC,UAAmC,EAChB;IACnB,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;AAAA,CACnF;AAED;;;;;GAKG;AACH,MAAM,UAAU,iCAAiC,CAAC,IAAoB,EAAgC;IACrG,OAAO;QACN,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,IAAI,CAAC,UAAiB;QAClC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC;KAC3G,CAAC;AAAA,CACF","sourcesContent":["import type { AgentTool } from \"@hyperspaceng/neural-agent-core\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.js\";\n\n/** Wrap a ToolDefinition into an AgentTool for the core runtime. */\nexport function wrapToolDefinition<TDetails = unknown>(\n\tdefinition: ToolDefinition<any, TDetails>,\n\tctxFactory?: () => ExtensionContext,\n): AgentTool<any, TDetails> {\n\treturn {\n\t\tname: definition.name,\n\t\tlabel: definition.label,\n\t\tdescription: definition.description,\n\t\tparameters: definition.parameters,\n\t\texecute: (toolCallId, params, signal, onUpdate) =>\n\t\t\tdefinition.execute(toolCallId, params, signal, onUpdate, ctxFactory?.() as ExtensionContext),\n\t};\n}\n\n/** Wrap multiple ToolDefinitions into AgentTools for the core runtime. */\nexport function wrapToolDefinitions(\n\tdefinitions: ToolDefinition<any, any>[],\n\tctxFactory?: () => ExtensionContext,\n): AgentTool<any>[] {\n\treturn definitions.map((definition) => wrapToolDefinition(definition, ctxFactory));\n}\n\n/**\n * Synthesize a minimal ToolDefinition from an AgentTool.\n *\n * This keeps AgentSession's internal registry definition-first even when a caller\n * provides plain AgentTool overrides that do not include prompt metadata or renderers.\n */\nexport function createToolDefinitionFromAgentTool(tool: AgentTool<any>): ToolDefinition<any, unknown> {\n\treturn {\n\t\tname: tool.name,\n\t\tlabel: tool.label,\n\t\tdescription: tool.description,\n\t\tparameters: tool.parameters as any,\n\t\texecute: async (toolCallId, params, signal, onUpdate) => tool.execute(toolCallId, params, signal, onUpdate),\n\t};\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { AgentTool } from "@
|
|
1
|
+
import type { AgentTool } from "@hyperspaceng/neural-agent-core";
|
|
2
2
|
import { type Static } from "@sinclair/typebox";
|
|
3
|
+
import type { ToolDefinition } from "../extensions/types.js";
|
|
3
4
|
declare const writeSchema: import("@sinclair/typebox").TObject<{
|
|
4
5
|
path: import("@sinclair/typebox").TString;
|
|
5
6
|
content: import("@sinclair/typebox").TString;
|
|
@@ -7,20 +8,25 @@ declare const writeSchema: import("@sinclair/typebox").TObject<{
|
|
|
7
8
|
export type WriteToolInput = Static<typeof writeSchema>;
|
|
8
9
|
/**
|
|
9
10
|
* Pluggable operations for the write tool.
|
|
10
|
-
* Override these to delegate file writing to remote systems (
|
|
11
|
+
* Override these to delegate file writing to remote systems (for example SSH).
|
|
11
12
|
*/
|
|
12
13
|
export interface WriteOperations {
|
|
13
14
|
/** Write content to a file */
|
|
14
15
|
writeFile: (absolutePath: string, content: string) => Promise<void>;
|
|
15
|
-
/** Create directory
|
|
16
|
+
/** Create directory recursively */
|
|
16
17
|
mkdir: (dir: string) => Promise<void>;
|
|
17
18
|
}
|
|
18
19
|
export interface WriteToolOptions {
|
|
19
20
|
/** Custom operations for file writing. Default: local filesystem */
|
|
20
21
|
operations?: WriteOperations;
|
|
21
22
|
}
|
|
23
|
+
export declare function createWriteToolDefinition(cwd: string, options?: WriteToolOptions): ToolDefinition<typeof writeSchema, undefined>;
|
|
22
24
|
export declare function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema>;
|
|
23
|
-
/** Default write tool using process.cwd()
|
|
25
|
+
/** Default write tool using process.cwd() for backwards compatibility. */
|
|
26
|
+
export declare const writeToolDefinition: ToolDefinition<import("@sinclair/typebox").TObject<{
|
|
27
|
+
path: import("@sinclair/typebox").TString;
|
|
28
|
+
content: import("@sinclair/typebox").TString;
|
|
29
|
+
}>, undefined, any>;
|
|
24
30
|
export declare const writeTool: AgentTool<import("@sinclair/typebox").TObject<{
|
|
25
31
|
path: import("@sinclair/typebox").TString;
|
|
26
32
|
content: import("@sinclair/typebox").TString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAMtD,QAAA,MAAM,WAAW;;;EAGf,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC/B,8BAA8B;IAC9B,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,qCAAqC;IACrC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAOD,MAAM,WAAW,gBAAgB;IAChC,oEAAoE;IACpE,UAAU,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC,OAAO,WAAW,CAAC,CAsFtG;AAED,2EAA2E;AAC3E,eAAO,MAAM,SAAS;;;QAAiC,CAAC","sourcesContent":["import type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { mkdir as fsMkdir, writeFile as fsWriteFile } from \"fs/promises\";\nimport { dirname } from \"path\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.js\";\nimport { resolveToCwd } from \"./path-utils.js\";\n\nconst writeSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to write (relative or absolute)\" }),\n\tcontent: Type.String({ description: \"Content to write to the file\" }),\n});\n\nexport type WriteToolInput = Static<typeof writeSchema>;\n\n/**\n * Pluggable operations for the write tool.\n * Override these to delegate file writing to remote systems (e.g., SSH).\n */\nexport interface WriteOperations {\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Create directory (recursively) */\n\tmkdir: (dir: string) => Promise<void>;\n}\n\nconst defaultWriteOperations: WriteOperations = {\n\twriteFile: (path, content) => fsWriteFile(path, content, \"utf-8\"),\n\tmkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => {}),\n};\n\nexport interface WriteToolOptions {\n\t/** Custom operations for file writing. Default: local filesystem */\n\toperations?: WriteOperations;\n}\n\nexport function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema> {\n\tconst ops = options?.operations ?? defaultWriteOperations;\n\n\treturn {\n\t\tname: \"write\",\n\t\tlabel: \"write\",\n\t\tdescription:\n\t\t\t\"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n\t\tparameters: writeSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ path, content }: { path: string; content: string },\n\t\t\tsignal?: AbortSignal,\n\t\t) => {\n\t\t\tconst absolutePath = resolveToCwd(path, cwd);\n\t\t\tconst dir = dirname(absolutePath);\n\n\t\t\treturn withFileMutationQueue(\n\t\t\t\tabsolutePath,\n\t\t\t\t() =>\n\t\t\t\t\tnew Promise<{ content: Array<{ type: \"text\"; text: string }>; details: undefined }>(\n\t\t\t\t\t\t(resolve, reject) => {\n\t\t\t\t\t\t\t// Check if already aborted\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tlet aborted = false;\n\n\t\t\t\t\t\t\t// Set up abort handler\n\t\t\t\t\t\t\tconst onAbort = () => {\n\t\t\t\t\t\t\t\taborted = true;\n\t\t\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Perform the write operation\n\t\t\t\t\t\t\t(async () => {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t// Create parent directories if needed\n\t\t\t\t\t\t\t\t\tawait ops.mkdir(dir);\n\n\t\t\t\t\t\t\t\t\t// Check if aborted before writing\n\t\t\t\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Write the file\n\t\t\t\t\t\t\t\t\tawait ops.writeFile(absolutePath, content);\n\n\t\t\t\t\t\t\t\t\t// Check if aborted after writing\n\t\t\t\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Clean up abort handler\n\t\t\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t\t\t\t{ type: \"text\", text: `Successfully wrote ${content.length} bytes to ${path}` },\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t} catch (error: any) {\n\t\t\t\t\t\t\t\t\t// Clean up abort handler\n\t\t\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif (!aborted) {\n\t\t\t\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})();\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t);\n\t\t},\n\t};\n}\n\n/** Default write tool using process.cwd() - for backwards compatibility */\nexport const writeTool = createWriteTool(process.cwd());\n"]}
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAKtD,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AAMtF,QAAA,MAAM,WAAW;;;EAGf,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC/B,8BAA8B;IAC9B,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,mCAAmC;IACnC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAOD,MAAM,WAAW,gBAAgB;IAChC,oEAAoE;IACpE,UAAU,CAAC,EAAE,eAAe,CAAC;CAC7B;AA6ID,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,gBAAgB,GACxB,cAAc,CAAC,OAAO,WAAW,EAAE,SAAS,CAAC,CA6F/C;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC,OAAO,WAAW,CAAC,CAEtG;AAED,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB;;;mBAA2C,CAAC;AAC5E,eAAO,MAAM,SAAS;;;QAAiC,CAAC","sourcesContent":["import type { AgentTool } from \"@hyperspaceng/neural-agent-core\";\nimport { Container, Text } from \"@hyperspaceng/neural-tui\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { mkdir as fsMkdir, writeFile as fsWriteFile } from \"fs/promises\";\nimport { dirname } from \"path\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.js\";\nimport { getLanguageFromPath, highlightCode } from \"../../modes/interactive/theme/theme.js\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.js\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.js\";\nimport { resolveToCwd } from \"./path-utils.js\";\nimport { invalidArgText, normalizeDisplayText, replaceTabs, shortenPath, str } from \"./render-utils.js\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.js\";\n\nconst writeSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to write (relative or absolute)\" }),\n\tcontent: Type.String({ description: \"Content to write to the file\" }),\n});\n\nexport type WriteToolInput = Static<typeof writeSchema>;\n\n/**\n * Pluggable operations for the write tool.\n * Override these to delegate file writing to remote systems (for example SSH).\n */\nexport interface WriteOperations {\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Create directory recursively */\n\tmkdir: (dir: string) => Promise<void>;\n}\n\nconst defaultWriteOperations: WriteOperations = {\n\twriteFile: (path, content) => fsWriteFile(path, content, \"utf-8\"),\n\tmkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => {}),\n};\n\nexport interface WriteToolOptions {\n\t/** Custom operations for file writing. Default: local filesystem */\n\toperations?: WriteOperations;\n}\n\ntype WriteHighlightCache = {\n\trawPath: string | null;\n\tlang: string;\n\trawContent: string;\n\tnormalizedLines: string[];\n\thighlightedLines: string[];\n};\n\nclass WriteCallRenderComponent extends Text {\n\tcache?: WriteHighlightCache;\n\n\tconstructor() {\n\t\tsuper(\"\", 0, 0);\n\t}\n}\n\nconst WRITE_PARTIAL_FULL_HIGHLIGHT_LINES = 50;\n\nfunction highlightSingleLine(line: string, lang: string): string {\n\tconst highlighted = highlightCode(line, lang);\n\treturn highlighted[0] ?? \"\";\n}\n\nfunction refreshWriteHighlightPrefix(cache: WriteHighlightCache): void {\n\tconst prefixCount = Math.min(WRITE_PARTIAL_FULL_HIGHLIGHT_LINES, cache.normalizedLines.length);\n\tif (prefixCount === 0) return;\n\tconst prefixSource = cache.normalizedLines.slice(0, prefixCount).join(\"\\n\");\n\tconst prefixHighlighted = highlightCode(prefixSource, cache.lang);\n\tfor (let i = 0; i < prefixCount; i++) {\n\t\tcache.highlightedLines[i] =\n\t\t\tprefixHighlighted[i] ?? highlightSingleLine(cache.normalizedLines[i] ?? \"\", cache.lang);\n\t}\n}\n\nfunction rebuildWriteHighlightCacheFull(rawPath: string | null, fileContent: string): WriteHighlightCache | undefined {\n\tconst lang = rawPath ? getLanguageFromPath(rawPath) : undefined;\n\tif (!lang) return undefined;\n\tconst displayContent = normalizeDisplayText(fileContent);\n\tconst normalized = replaceTabs(displayContent);\n\treturn {\n\t\trawPath,\n\t\tlang,\n\t\trawContent: fileContent,\n\t\tnormalizedLines: normalized.split(\"\\n\"),\n\t\thighlightedLines: highlightCode(normalized, lang),\n\t};\n}\n\nfunction updateWriteHighlightCacheIncremental(\n\tcache: WriteHighlightCache | undefined,\n\trawPath: string | null,\n\tfileContent: string,\n): WriteHighlightCache | undefined {\n\tconst lang = rawPath ? getLanguageFromPath(rawPath) : undefined;\n\tif (!lang) return undefined;\n\tif (!cache) return rebuildWriteHighlightCacheFull(rawPath, fileContent);\n\tif (cache.lang !== lang || cache.rawPath !== rawPath) return rebuildWriteHighlightCacheFull(rawPath, fileContent);\n\tif (!fileContent.startsWith(cache.rawContent)) return rebuildWriteHighlightCacheFull(rawPath, fileContent);\n\tif (fileContent.length === cache.rawContent.length) return cache;\n\n\tconst deltaRaw = fileContent.slice(cache.rawContent.length);\n\tconst deltaDisplay = normalizeDisplayText(deltaRaw);\n\tconst deltaNormalized = replaceTabs(deltaDisplay);\n\tcache.rawContent = fileContent;\n\tif (cache.normalizedLines.length === 0) {\n\t\tcache.normalizedLines.push(\"\");\n\t\tcache.highlightedLines.push(\"\");\n\t}\n\n\tconst segments = deltaNormalized.split(\"\\n\");\n\tconst lastIndex = cache.normalizedLines.length - 1;\n\tcache.normalizedLines[lastIndex] += segments[0];\n\tcache.highlightedLines[lastIndex] = highlightSingleLine(cache.normalizedLines[lastIndex], cache.lang);\n\tfor (let i = 1; i < segments.length; i++) {\n\t\tcache.normalizedLines.push(segments[i]);\n\t\tcache.highlightedLines.push(highlightSingleLine(segments[i], cache.lang));\n\t}\n\trefreshWriteHighlightPrefix(cache);\n\treturn cache;\n}\n\nfunction trimTrailingEmptyLines(lines: string[]): string[] {\n\tlet end = lines.length;\n\twhile (end > 0 && lines[end - 1] === \"\") {\n\t\tend--;\n\t}\n\treturn lines.slice(0, end);\n}\n\nfunction formatWriteCall(\n\targs: { path?: string; file_path?: string; content?: string } | undefined,\n\toptions: ToolRenderResultOptions,\n\ttheme: typeof import(\"../../modes/interactive/theme/theme.js\").theme,\n\tcache: WriteHighlightCache | undefined,\n): string {\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tconst fileContent = str(args?.content);\n\tconst path = rawPath !== null ? shortenPath(rawPath) : null;\n\tconst invalidArg = invalidArgText(theme);\n\tlet text = `${theme.fg(\"toolTitle\", theme.bold(\"write\"))} ${path === null ? invalidArg : path ? theme.fg(\"accent\", path) : theme.fg(\"toolOutput\", \"...\")}`;\n\n\tif (fileContent === null) {\n\t\ttext += `\\n\\n${theme.fg(\"error\", \"[invalid content arg - expected string]\")}`;\n\t} else if (fileContent) {\n\t\tconst lang = rawPath ? getLanguageFromPath(rawPath) : undefined;\n\t\tconst renderedLines = lang\n\t\t\t? (cache?.highlightedLines ?? highlightCode(replaceTabs(normalizeDisplayText(fileContent)), lang))\n\t\t\t: normalizeDisplayText(fileContent).split(\"\\n\");\n\t\tconst lines = trimTrailingEmptyLines(renderedLines);\n\t\tconst totalLines = lines.length;\n\t\tconst maxLines = options.expanded ? lines.length : 10;\n\t\tconst displayLines = lines.slice(0, maxLines);\n\t\tconst remaining = lines.length - maxLines;\n\t\ttext += `\\n\\n${displayLines.map((line) => (lang ? line : theme.fg(\"toolOutput\", replaceTabs(line)))).join(\"\\n\")}`;\n\t\tif (remaining > 0) {\n\t\t\ttext += `${theme.fg(\"muted\", `\\n... (${remaining} more lines, ${totalLines} total,`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t\t}\n\t}\n\n\treturn text;\n}\n\nfunction formatWriteResult(\n\tresult: { content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>; isError?: boolean },\n\ttheme: typeof import(\"../../modes/interactive/theme/theme.js\").theme,\n): string | undefined {\n\tif (!result.isError) {\n\t\treturn undefined;\n\t}\n\tconst output = result.content\n\t\t.filter((c) => c.type === \"text\")\n\t\t.map((c) => c.text || \"\")\n\t\t.join(\"\\n\");\n\tif (!output) {\n\t\treturn undefined;\n\t}\n\treturn `\\n${theme.fg(\"error\", output)}`;\n}\n\nexport function createWriteToolDefinition(\n\tcwd: string,\n\toptions?: WriteToolOptions,\n): ToolDefinition<typeof writeSchema, undefined> {\n\tconst ops = options?.operations ?? defaultWriteOperations;\n\treturn {\n\t\tname: \"write\",\n\t\tlabel: \"write\",\n\t\tdescription:\n\t\t\t\"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n\t\tpromptSnippet: \"Create or overwrite files\",\n\t\tpromptGuidelines: [\"Use write only for new files or complete rewrites.\"],\n\t\tparameters: writeSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ path, content }: { path: string; content: string },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\t_ctx?,\n\t\t) {\n\t\t\tconst absolutePath = resolveToCwd(path, cwd);\n\t\t\tconst dir = dirname(absolutePath);\n\t\t\treturn withFileMutationQueue(\n\t\t\t\tabsolutePath,\n\t\t\t\t() =>\n\t\t\t\t\tnew Promise<{ content: Array<{ type: \"text\"; text: string }>; details: undefined }>(\n\t\t\t\t\t\t(resolve, reject) => {\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlet aborted = false;\n\t\t\t\t\t\t\tconst onAbort = () => {\n\t\t\t\t\t\t\t\taborted = true;\n\t\t\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t\t\t\t(async () => {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t// Create parent directories if needed.\n\t\t\t\t\t\t\t\t\tawait ops.mkdir(dir);\n\t\t\t\t\t\t\t\t\tif (aborted) return;\n\t\t\t\t\t\t\t\t\t// Write the file contents.\n\t\t\t\t\t\t\t\t\tawait ops.writeFile(absolutePath, content);\n\t\t\t\t\t\t\t\t\tif (aborted) return;\n\t\t\t\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t\t\t\t{ type: \"text\", text: `Successfully wrote ${content.length} bytes to ${path}` },\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t} catch (error: any) {\n\t\t\t\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t\t\tif (!aborted) reject(error);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})();\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t);\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst renderArgs = args as { path?: string; file_path?: string; content?: string } | undefined;\n\t\t\tconst rawPath = str(renderArgs?.file_path ?? renderArgs?.path);\n\t\t\tconst fileContent = str(renderArgs?.content);\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as WriteCallRenderComponent | undefined) ?? new WriteCallRenderComponent();\n\t\t\tif (fileContent !== null) {\n\t\t\t\tcomponent.cache = context.argsComplete\n\t\t\t\t\t? rebuildWriteHighlightCacheFull(rawPath, fileContent)\n\t\t\t\t\t: updateWriteHighlightCacheIncremental(component.cache, rawPath, fileContent);\n\t\t\t} else {\n\t\t\t\tcomponent.cache = undefined;\n\t\t\t}\n\t\t\tcomponent.setText(\n\t\t\t\tformatWriteCall(\n\t\t\t\t\trenderArgs,\n\t\t\t\t\t{ expanded: context.expanded, isPartial: context.isPartial },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcomponent.cache,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn component;\n\t\t},\n\t\trenderResult(result, _options, theme, context) {\n\t\t\tconst output = formatWriteResult({ ...result, isError: context.isError }, theme);\n\t\t\tif (!output) {\n\t\t\t\tconst component = (context.lastComponent as Container | undefined) ?? new Container();\n\t\t\t\tcomponent.clear();\n\t\t\t\treturn component;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(output);\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema> {\n\treturn wrapToolDefinition(createWriteToolDefinition(cwd, options));\n}\n\n/** Default write tool using process.cwd() for backwards compatibility. */\nexport const writeToolDefinition = createWriteToolDefinition(process.cwd());\nexport const writeTool = createWriteTool(process.cwd());\n"]}
|
package/dist/core/tools/write.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
import { Container, Text } from "@hyperspaceng/neural-tui";
|
|
1
2
|
import { Type } from "@sinclair/typebox";
|
|
2
3
|
import { mkdir as fsMkdir, writeFile as fsWriteFile } from "fs/promises";
|
|
3
4
|
import { dirname } from "path";
|
|
5
|
+
import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
6
|
+
import { getLanguageFromPath, highlightCode } from "../../modes/interactive/theme/theme.js";
|
|
4
7
|
import { withFileMutationQueue } from "./file-mutation-queue.js";
|
|
5
8
|
import { resolveToCwd } from "./path-utils.js";
|
|
9
|
+
import { invalidArgText, normalizeDisplayText, replaceTabs, shortenPath, str } from "./render-utils.js";
|
|
10
|
+
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
6
11
|
const writeSchema = Type.Object({
|
|
7
12
|
path: Type.String({ description: "Path to the file to write (relative or absolute)" }),
|
|
8
13
|
content: Type.String({ description: "Content to write to the file" }),
|
|
@@ -11,50 +16,153 @@ const defaultWriteOperations = {
|
|
|
11
16
|
writeFile: (path, content) => fsWriteFile(path, content, "utf-8"),
|
|
12
17
|
mkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => { }),
|
|
13
18
|
};
|
|
14
|
-
|
|
19
|
+
class WriteCallRenderComponent extends Text {
|
|
20
|
+
cache;
|
|
21
|
+
constructor() {
|
|
22
|
+
super("", 0, 0);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const WRITE_PARTIAL_FULL_HIGHLIGHT_LINES = 50;
|
|
26
|
+
function highlightSingleLine(line, lang) {
|
|
27
|
+
const highlighted = highlightCode(line, lang);
|
|
28
|
+
return highlighted[0] ?? "";
|
|
29
|
+
}
|
|
30
|
+
function refreshWriteHighlightPrefix(cache) {
|
|
31
|
+
const prefixCount = Math.min(WRITE_PARTIAL_FULL_HIGHLIGHT_LINES, cache.normalizedLines.length);
|
|
32
|
+
if (prefixCount === 0)
|
|
33
|
+
return;
|
|
34
|
+
const prefixSource = cache.normalizedLines.slice(0, prefixCount).join("\n");
|
|
35
|
+
const prefixHighlighted = highlightCode(prefixSource, cache.lang);
|
|
36
|
+
for (let i = 0; i < prefixCount; i++) {
|
|
37
|
+
cache.highlightedLines[i] =
|
|
38
|
+
prefixHighlighted[i] ?? highlightSingleLine(cache.normalizedLines[i] ?? "", cache.lang);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function rebuildWriteHighlightCacheFull(rawPath, fileContent) {
|
|
42
|
+
const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
|
|
43
|
+
if (!lang)
|
|
44
|
+
return undefined;
|
|
45
|
+
const displayContent = normalizeDisplayText(fileContent);
|
|
46
|
+
const normalized = replaceTabs(displayContent);
|
|
47
|
+
return {
|
|
48
|
+
rawPath,
|
|
49
|
+
lang,
|
|
50
|
+
rawContent: fileContent,
|
|
51
|
+
normalizedLines: normalized.split("\n"),
|
|
52
|
+
highlightedLines: highlightCode(normalized, lang),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function updateWriteHighlightCacheIncremental(cache, rawPath, fileContent) {
|
|
56
|
+
const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
|
|
57
|
+
if (!lang)
|
|
58
|
+
return undefined;
|
|
59
|
+
if (!cache)
|
|
60
|
+
return rebuildWriteHighlightCacheFull(rawPath, fileContent);
|
|
61
|
+
if (cache.lang !== lang || cache.rawPath !== rawPath)
|
|
62
|
+
return rebuildWriteHighlightCacheFull(rawPath, fileContent);
|
|
63
|
+
if (!fileContent.startsWith(cache.rawContent))
|
|
64
|
+
return rebuildWriteHighlightCacheFull(rawPath, fileContent);
|
|
65
|
+
if (fileContent.length === cache.rawContent.length)
|
|
66
|
+
return cache;
|
|
67
|
+
const deltaRaw = fileContent.slice(cache.rawContent.length);
|
|
68
|
+
const deltaDisplay = normalizeDisplayText(deltaRaw);
|
|
69
|
+
const deltaNormalized = replaceTabs(deltaDisplay);
|
|
70
|
+
cache.rawContent = fileContent;
|
|
71
|
+
if (cache.normalizedLines.length === 0) {
|
|
72
|
+
cache.normalizedLines.push("");
|
|
73
|
+
cache.highlightedLines.push("");
|
|
74
|
+
}
|
|
75
|
+
const segments = deltaNormalized.split("\n");
|
|
76
|
+
const lastIndex = cache.normalizedLines.length - 1;
|
|
77
|
+
cache.normalizedLines[lastIndex] += segments[0];
|
|
78
|
+
cache.highlightedLines[lastIndex] = highlightSingleLine(cache.normalizedLines[lastIndex], cache.lang);
|
|
79
|
+
for (let i = 1; i < segments.length; i++) {
|
|
80
|
+
cache.normalizedLines.push(segments[i]);
|
|
81
|
+
cache.highlightedLines.push(highlightSingleLine(segments[i], cache.lang));
|
|
82
|
+
}
|
|
83
|
+
refreshWriteHighlightPrefix(cache);
|
|
84
|
+
return cache;
|
|
85
|
+
}
|
|
86
|
+
function trimTrailingEmptyLines(lines) {
|
|
87
|
+
let end = lines.length;
|
|
88
|
+
while (end > 0 && lines[end - 1] === "") {
|
|
89
|
+
end--;
|
|
90
|
+
}
|
|
91
|
+
return lines.slice(0, end);
|
|
92
|
+
}
|
|
93
|
+
function formatWriteCall(args, options, theme, cache) {
|
|
94
|
+
const rawPath = str(args?.file_path ?? args?.path);
|
|
95
|
+
const fileContent = str(args?.content);
|
|
96
|
+
const path = rawPath !== null ? shortenPath(rawPath) : null;
|
|
97
|
+
const invalidArg = invalidArgText(theme);
|
|
98
|
+
let text = `${theme.fg("toolTitle", theme.bold("write"))} ${path === null ? invalidArg : path ? theme.fg("accent", path) : theme.fg("toolOutput", "...")}`;
|
|
99
|
+
if (fileContent === null) {
|
|
100
|
+
text += `\n\n${theme.fg("error", "[invalid content arg - expected string]")}`;
|
|
101
|
+
}
|
|
102
|
+
else if (fileContent) {
|
|
103
|
+
const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
|
|
104
|
+
const renderedLines = lang
|
|
105
|
+
? (cache?.highlightedLines ?? highlightCode(replaceTabs(normalizeDisplayText(fileContent)), lang))
|
|
106
|
+
: normalizeDisplayText(fileContent).split("\n");
|
|
107
|
+
const lines = trimTrailingEmptyLines(renderedLines);
|
|
108
|
+
const totalLines = lines.length;
|
|
109
|
+
const maxLines = options.expanded ? lines.length : 10;
|
|
110
|
+
const displayLines = lines.slice(0, maxLines);
|
|
111
|
+
const remaining = lines.length - maxLines;
|
|
112
|
+
text += `\n\n${displayLines.map((line) => (lang ? line : theme.fg("toolOutput", replaceTabs(line)))).join("\n")}`;
|
|
113
|
+
if (remaining > 0) {
|
|
114
|
+
text += `${theme.fg("muted", `\n... (${remaining} more lines, ${totalLines} total,`)} ${keyHint("app.tools.expand", "to expand")})`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return text;
|
|
118
|
+
}
|
|
119
|
+
function formatWriteResult(result, theme) {
|
|
120
|
+
if (!result.isError) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
const output = result.content
|
|
124
|
+
.filter((c) => c.type === "text")
|
|
125
|
+
.map((c) => c.text || "")
|
|
126
|
+
.join("\n");
|
|
127
|
+
if (!output) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
return `\n${theme.fg("error", output)}`;
|
|
131
|
+
}
|
|
132
|
+
export function createWriteToolDefinition(cwd, options) {
|
|
15
133
|
const ops = options?.operations ?? defaultWriteOperations;
|
|
16
134
|
return {
|
|
17
135
|
name: "write",
|
|
18
136
|
label: "write",
|
|
19
137
|
description: "Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",
|
|
138
|
+
promptSnippet: "Create or overwrite files",
|
|
139
|
+
promptGuidelines: ["Use write only for new files or complete rewrites."],
|
|
20
140
|
parameters: writeSchema,
|
|
21
|
-
|
|
141
|
+
async execute(_toolCallId, { path, content }, signal, _onUpdate, _ctx) {
|
|
22
142
|
const absolutePath = resolveToCwd(path, cwd);
|
|
23
143
|
const dir = dirname(absolutePath);
|
|
24
144
|
return withFileMutationQueue(absolutePath, () => new Promise((resolve, reject) => {
|
|
25
|
-
// Check if already aborted
|
|
26
145
|
if (signal?.aborted) {
|
|
27
146
|
reject(new Error("Operation aborted"));
|
|
28
147
|
return;
|
|
29
148
|
}
|
|
30
149
|
let aborted = false;
|
|
31
|
-
// Set up abort handler
|
|
32
150
|
const onAbort = () => {
|
|
33
151
|
aborted = true;
|
|
34
152
|
reject(new Error("Operation aborted"));
|
|
35
153
|
};
|
|
36
|
-
|
|
37
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
38
|
-
}
|
|
39
|
-
// Perform the write operation
|
|
154
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
40
155
|
(async () => {
|
|
41
156
|
try {
|
|
42
|
-
// Create parent directories if needed
|
|
157
|
+
// Create parent directories if needed.
|
|
43
158
|
await ops.mkdir(dir);
|
|
44
|
-
|
|
45
|
-
if (aborted) {
|
|
159
|
+
if (aborted)
|
|
46
160
|
return;
|
|
47
|
-
|
|
48
|
-
// Write the file
|
|
161
|
+
// Write the file contents.
|
|
49
162
|
await ops.writeFile(absolutePath, content);
|
|
50
|
-
|
|
51
|
-
if (aborted) {
|
|
163
|
+
if (aborted)
|
|
52
164
|
return;
|
|
53
|
-
|
|
54
|
-
// Clean up abort handler
|
|
55
|
-
if (signal) {
|
|
56
|
-
signal.removeEventListener("abort", onAbort);
|
|
57
|
-
}
|
|
165
|
+
signal?.removeEventListener("abort", onAbort);
|
|
58
166
|
resolve({
|
|
59
167
|
content: [
|
|
60
168
|
{ type: "text", text: `Successfully wrote ${content.length} bytes to ${path}` },
|
|
@@ -63,19 +171,46 @@ export function createWriteTool(cwd, options) {
|
|
|
63
171
|
});
|
|
64
172
|
}
|
|
65
173
|
catch (error) {
|
|
66
|
-
|
|
67
|
-
if (
|
|
68
|
-
signal.removeEventListener("abort", onAbort);
|
|
69
|
-
}
|
|
70
|
-
if (!aborted) {
|
|
174
|
+
signal?.removeEventListener("abort", onAbort);
|
|
175
|
+
if (!aborted)
|
|
71
176
|
reject(error);
|
|
72
|
-
}
|
|
73
177
|
}
|
|
74
178
|
})();
|
|
75
179
|
}));
|
|
76
180
|
},
|
|
181
|
+
renderCall(args, theme, context) {
|
|
182
|
+
const renderArgs = args;
|
|
183
|
+
const rawPath = str(renderArgs?.file_path ?? renderArgs?.path);
|
|
184
|
+
const fileContent = str(renderArgs?.content);
|
|
185
|
+
const component = context.lastComponent ?? new WriteCallRenderComponent();
|
|
186
|
+
if (fileContent !== null) {
|
|
187
|
+
component.cache = context.argsComplete
|
|
188
|
+
? rebuildWriteHighlightCacheFull(rawPath, fileContent)
|
|
189
|
+
: updateWriteHighlightCacheIncremental(component.cache, rawPath, fileContent);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
component.cache = undefined;
|
|
193
|
+
}
|
|
194
|
+
component.setText(formatWriteCall(renderArgs, { expanded: context.expanded, isPartial: context.isPartial }, theme, component.cache));
|
|
195
|
+
return component;
|
|
196
|
+
},
|
|
197
|
+
renderResult(result, _options, theme, context) {
|
|
198
|
+
const output = formatWriteResult({ ...result, isError: context.isError }, theme);
|
|
199
|
+
if (!output) {
|
|
200
|
+
const component = context.lastComponent ?? new Container();
|
|
201
|
+
component.clear();
|
|
202
|
+
return component;
|
|
203
|
+
}
|
|
204
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
205
|
+
text.setText(output);
|
|
206
|
+
return text;
|
|
207
|
+
},
|
|
77
208
|
};
|
|
78
209
|
}
|
|
79
|
-
|
|
210
|
+
export function createWriteTool(cwd, options) {
|
|
211
|
+
return wrapToolDefinition(createWriteToolDefinition(cwd, options));
|
|
212
|
+
}
|
|
213
|
+
/** Default write tool using process.cwd() for backwards compatibility. */
|
|
214
|
+
export const writeToolDefinition = createWriteToolDefinition(process.cwd());
|
|
80
215
|
export const writeTool = createWriteTool(process.cwd());
|
|
81
216
|
//# sourceMappingURL=write.js.map
|