@lenylvt/pi-coding-agent 0.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3331 -0
- package/README.md +48 -0
- package/dist/bun/cli.d.ts +3 -0
- package/dist/bun/cli.d.ts.map +1 -0
- package/dist/bun/cli.js +5 -0
- package/dist/bun/cli.js.map +1 -0
- package/dist/cli/args.d.ts +49 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +292 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/config-selector.d.ts +14 -0
- package/dist/cli/config-selector.d.ts.map +1 -0
- package/dist/cli/config-selector.js +31 -0
- package/dist/cli/config-selector.js.map +1 -0
- package/dist/cli/file-processor.d.ts +15 -0
- package/dist/cli/file-processor.d.ts.map +1 -0
- package/dist/cli/file-processor.js +83 -0
- package/dist/cli/file-processor.js.map +1 -0
- package/dist/cli/initial-message.d.ts +18 -0
- package/dist/cli/initial-message.d.ts.map +1 -0
- package/dist/cli/initial-message.js +22 -0
- package/dist/cli/initial-message.js.map +1 -0
- package/dist/cli/list-models.d.ts +9 -0
- package/dist/cli/list-models.d.ts.map +1 -0
- package/dist/cli/list-models.js +92 -0
- package/dist/cli/list-models.js.map +1 -0
- package/dist/cli/session-picker.d.ts +9 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +35 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +14 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +69 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +178 -0
- package/dist/config.js.map +1 -0
- package/dist/core/agent-session.d.ts +622 -0
- package/dist/core/agent-session.d.ts.map +1 -0
- package/dist/core/agent-session.js +2688 -0
- package/dist/core/agent-session.js.map +1 -0
- package/dist/core/auth-storage.d.ts +132 -0
- package/dist/core/auth-storage.d.ts.map +1 -0
- package/dist/core/auth-storage.js +422 -0
- package/dist/core/auth-storage.js.map +1 -0
- package/dist/core/bash-executor.d.ts +46 -0
- package/dist/core/bash-executor.d.ts.map +1 -0
- package/dist/core/bash-executor.js +113 -0
- package/dist/core/bash-executor.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts +88 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
- package/dist/core/compaction/branch-summarization.js +243 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +121 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -0
- package/dist/core/compaction/compaction.js +613 -0
- package/dist/core/compaction/compaction.js.map +1 -0
- package/dist/core/compaction/index.d.ts +7 -0
- package/dist/core/compaction/index.d.ts.map +1 -0
- package/dist/core/compaction/index.js +7 -0
- package/dist/core/compaction/index.js.map +1 -0
- package/dist/core/compaction/utils.d.ts +38 -0
- package/dist/core/compaction/utils.d.ts.map +1 -0
- package/dist/core/compaction/utils.js +153 -0
- package/dist/core/compaction/utils.js.map +1 -0
- package/dist/core/defaults.d.ts +3 -0
- package/dist/core/defaults.d.ts.map +1 -0
- package/dist/core/defaults.js +2 -0
- package/dist/core/defaults.js.map +1 -0
- package/dist/core/diagnostics.d.ts +15 -0
- package/dist/core/diagnostics.d.ts.map +1 -0
- package/dist/core/diagnostics.js +2 -0
- package/dist/core/diagnostics.js.map +1 -0
- package/dist/core/event-bus.d.ts +9 -0
- package/dist/core/event-bus.d.ts.map +1 -0
- package/dist/core/event-bus.js +25 -0
- package/dist/core/event-bus.js.map +1 -0
- package/dist/core/exec.d.ts +29 -0
- package/dist/core/exec.d.ts.map +1 -0
- package/dist/core/exec.js +75 -0
- package/dist/core/exec.js.map +1 -0
- package/dist/core/export-html/ansi-to-html.d.ts +22 -0
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
- package/dist/core/export-html/ansi-to-html.js +249 -0
- package/dist/core/export-html/ansi-to-html.js.map +1 -0
- package/dist/core/export-html/index.d.ts +37 -0
- package/dist/core/export-html/index.d.ts.map +1 -0
- package/dist/core/export-html/index.js +224 -0
- package/dist/core/export-html/index.js.map +1 -0
- package/dist/core/export-html/template.css +1001 -0
- package/dist/core/export-html/template.html +55 -0
- package/dist/core/export-html/template.js +1690 -0
- package/dist/core/export-html/tool-renderer.d.ts +38 -0
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
- package/dist/core/export-html/tool-renderer.js +95 -0
- package/dist/core/export-html/tool-renderer.js.map +1 -0
- package/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/core/export-html/vendor/marked.min.js +6 -0
- package/dist/core/extensions/index.d.ts +12 -0
- package/dist/core/extensions/index.d.ts.map +1 -0
- package/dist/core/extensions/index.js +9 -0
- package/dist/core/extensions/index.js.map +1 -0
- package/dist/core/extensions/loader.d.ts +25 -0
- package/dist/core/extensions/loader.d.ts.map +1 -0
- package/dist/core/extensions/loader.js +436 -0
- package/dist/core/extensions/loader.js.map +1 -0
- package/dist/core/extensions/runner.d.ts +148 -0
- package/dist/core/extensions/runner.d.ts.map +1 -0
- package/dist/core/extensions/runner.js +700 -0
- package/dist/core/extensions/runner.js.map +1 -0
- package/dist/core/extensions/types.d.ts +1085 -0
- package/dist/core/extensions/types.d.ts.map +1 -0
- package/dist/core/extensions/types.js +35 -0
- package/dist/core/extensions/types.js.map +1 -0
- package/dist/core/extensions/wrapper.d.ts +20 -0
- package/dist/core/extensions/wrapper.d.ts.map +1 -0
- package/dist/core/extensions/wrapper.js +22 -0
- package/dist/core/extensions/wrapper.js.map +1 -0
- package/dist/core/footer-data-provider.d.ts +44 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -0
- package/dist/core/footer-data-provider.js +252 -0
- package/dist/core/footer-data-provider.js.map +1 -0
- package/dist/core/index.d.ts +10 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +10 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/keybindings.d.ts +275 -0
- package/dist/core/keybindings.d.ts.map +1 -0
- package/dist/core/keybindings.js +241 -0
- package/dist/core/keybindings.js.map +1 -0
- package/dist/core/messages.d.ts +77 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.js +123 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/model-registry.d.ts +132 -0
- package/dist/core/model-registry.d.ts.map +1 -0
- package/dist/core/model-registry.js +565 -0
- package/dist/core/model-registry.js.map +1 -0
- package/dist/core/model-resolver.d.ts +110 -0
- package/dist/core/model-resolver.d.ts.map +1 -0
- package/dist/core/model-resolver.js +464 -0
- package/dist/core/model-resolver.js.map +1 -0
- 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 +172 -0
- package/dist/core/package-manager.d.ts.map +1 -0
- package/dist/core/package-manager.js +1801 -0
- package/dist/core/package-manager.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +51 -0
- package/dist/core/prompt-templates.d.ts.map +1 -0
- package/dist/core/prompt-templates.js +249 -0
- package/dist/core/prompt-templates.js.map +1 -0
- package/dist/core/resolve-config-value.d.ts +23 -0
- package/dist/core/resolve-config-value.d.ts.map +1 -0
- package/dist/core/resolve-config-value.js +126 -0
- package/dist/core/resolve-config-value.js.map +1 -0
- package/dist/core/resource-loader.d.ts +185 -0
- package/dist/core/resource-loader.d.ts.map +1 -0
- package/dist/core/resource-loader.js +698 -0
- package/dist/core/resource-loader.js.map +1 -0
- package/dist/core/sdk.d.ts +90 -0
- package/dist/core/sdk.d.ts.map +1 -0
- package/dist/core/sdk.js +233 -0
- package/dist/core/sdk.js.map +1 -0
- package/dist/core/self-update.d.ts +3 -0
- package/dist/core/self-update.d.ts.map +1 -0
- package/dist/core/self-update.js +46 -0
- package/dist/core/self-update.js.map +1 -0
- package/dist/core/session-manager.d.ts +329 -0
- package/dist/core/session-manager.d.ts.map +1 -0
- package/dist/core/session-manager.js +1097 -0
- package/dist/core/session-manager.js.map +1 -0
- package/dist/core/settings-manager.d.ts +237 -0
- package/dist/core/settings-manager.d.ts.map +1 -0
- package/dist/core/settings-manager.js +708 -0
- package/dist/core/settings-manager.js.map +1 -0
- package/dist/core/skills.d.ts +60 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +409 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/slash-commands.d.ts +14 -0
- package/dist/core/slash-commands.d.ts.map +1 -0
- package/dist/core/slash-commands.js +22 -0
- package/dist/core/slash-commands.js.map +1 -0
- 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 +28 -0
- package/dist/core/system-prompt.d.ts.map +1 -0
- package/dist/core/system-prompt.js +116 -0
- package/dist/core/system-prompt.js.map +1 -0
- package/dist/core/timings.d.ts +8 -0
- package/dist/core/timings.d.ts.map +1 -0
- package/dist/core/timings.js +31 -0
- package/dist/core/timings.js.map +1 -0
- package/dist/core/tools/bash.d.ts +73 -0
- package/dist/core/tools/bash.d.ts.map +1 -0
- package/dist/core/tools/bash.js +342 -0
- package/dist/core/tools/bash.js.map +1 -0
- package/dist/core/tools/edit-diff.d.ts +85 -0
- package/dist/core/tools/edit-diff.d.ts.map +1 -0
- package/dist/core/tools/edit-diff.js +337 -0
- package/dist/core/tools/edit-diff.js.map +1 -0
- package/dist/core/tools/edit.d.ts +53 -0
- package/dist/core/tools/edit.d.ts.map +1 -0
- package/dist/core/tools/edit.js +196 -0
- package/dist/core/tools/edit.js.map +1 -0
- package/dist/core/tools/file-mutation-queue.d.ts +6 -0
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
- package/dist/core/tools/file-mutation-queue.js +37 -0
- package/dist/core/tools/file-mutation-queue.js.map +1 -0
- package/dist/core/tools/find.d.ts +46 -0
- package/dist/core/tools/find.d.ts.map +1 -0
- package/dist/core/tools/find.js +258 -0
- package/dist/core/tools/find.js.map +1 -0
- package/dist/core/tools/grep.d.ts +56 -0
- package/dist/core/tools/grep.d.ts.map +1 -0
- package/dist/core/tools/grep.js +293 -0
- package/dist/core/tools/grep.js.map +1 -0
- package/dist/core/tools/index.d.ts +115 -0
- package/dist/core/tools/index.d.ts.map +1 -0
- package/dist/core/tools/index.js +86 -0
- package/dist/core/tools/index.js.map +1 -0
- package/dist/core/tools/ls.d.ts +46 -0
- package/dist/core/tools/ls.d.ts.map +1 -0
- package/dist/core/tools/ls.js +172 -0
- package/dist/core/tools/ls.js.map +1 -0
- package/dist/core/tools/path-utils.d.ts +8 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -0
- package/dist/core/tools/path-utils.js +81 -0
- package/dist/core/tools/path-utils.js.map +1 -0
- package/dist/core/tools/read.d.ts +46 -0
- package/dist/core/tools/read.d.ts.map +1 -0
- package/dist/core/tools/read.js +225 -0
- package/dist/core/tools/read.js.map +1 -0
- 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 +32 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
- package/dist/core/tools/truncate.d.ts +70 -0
- package/dist/core/tools/truncate.d.ts.map +1 -0
- package/dist/core/tools/truncate.js +205 -0
- package/dist/core/tools/truncate.js.map +1 -0
- package/dist/core/tools/write.d.ts +35 -0
- package/dist/core/tools/write.d.ts.map +1 -0
- package/dist/core/tools/write.js +216 -0
- package/dist/core/tools/write.js.map +1 -0
- package/dist/core/version-check.d.ts +2 -0
- package/dist/core/version-check.d.ts.map +1 -0
- package/dist/core/version-check.js +73 -0
- package/dist/core/version-check.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +8 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +811 -0
- package/dist/main.js.map +1 -0
- package/dist/migrations.d.ts +32 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +258 -0
- package/dist/migrations.js.map +1 -0
- package/dist/modes/index.d.ts +9 -0
- package/dist/modes/index.d.ts.map +1 -0
- package/dist/modes/index.js +8 -0
- package/dist/modes/index.js.map +1 -0
- package/dist/modes/interactive/components/armin.d.ts +34 -0
- package/dist/modes/interactive/components/armin.d.ts.map +1 -0
- package/dist/modes/interactive/components/armin.js +333 -0
- package/dist/modes/interactive/components/armin.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +18 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/assistant-message.js +107 -0
- package/dist/modes/interactive/components/assistant-message.js.map +1 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +34 -0
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/bash-execution.js +175 -0
- package/dist/modes/interactive/components/bash-execution.js.map +1 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
- package/dist/modes/interactive/components/bordered-loader.js +51 -0
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.js +44 -0
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +45 -0
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/config-selector.d.ts +71 -0
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/config-selector.js +479 -0
- package/dist/modes/interactive/components/config-selector.js.map +1 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -0
- package/dist/modes/interactive/components/countdown-timer.js +33 -0
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -0
- package/dist/modes/interactive/components/custom-editor.d.ts +21 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-editor.js +70 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -0
- package/dist/modes/interactive/components/custom-message.d.ts +20 -0
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-message.js +79 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -0
- package/dist/modes/interactive/components/diff.d.ts +12 -0
- package/dist/modes/interactive/components/diff.d.ts.map +1 -0
- package/dist/modes/interactive/components/diff.js +133 -0
- package/dist/modes/interactive/components/diff.js.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.js +21 -0
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +20 -0
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-editor.js +111 -0
- package/dist/modes/interactive/components/extension-editor.js.map +1 -0
- package/dist/modes/interactive/components/extension-input.d.ts +23 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-input.js +61 -0
- package/dist/modes/interactive/components/extension-input.js.map +1 -0
- package/dist/modes/interactive/components/extension-selector.d.ts +24 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-selector.js +78 -0
- package/dist/modes/interactive/components/extension-selector.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts +26 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -0
- package/dist/modes/interactive/components/footer.js +198 -0
- package/dist/modes/interactive/components/footer.js.map +1 -0
- package/dist/modes/interactive/components/index.d.ts +31 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -0
- package/dist/modes/interactive/components/index.js +32 -0
- package/dist/modes/interactive/components/index.js.map +1 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts +8 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
- package/dist/modes/interactive/components/keybinding-hints.js +22 -0
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
- package/dist/modes/interactive/components/login-dialog.d.ts +42 -0
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
- package/dist/modes/interactive/components/login-dialog.js +145 -0
- package/dist/modes/interactive/components/login-dialog.js.map +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts +47 -0
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/model-selector.js +275 -0
- package/dist/modes/interactive/components/model-selector.js.map +1 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts +19 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/oauth-selector.js +97 -0
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +49 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.js +275 -0
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.js +155 -0
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -0
- package/dist/modes/interactive/components/session-selector.d.ts +95 -0
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector.js +848 -0
- package/dist/modes/interactive/components/session-selector.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +58 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/settings-selector.js +301 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/show-images-selector.js +39 -0
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +47 -0
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
- package/dist/modes/interactive/components/theme-selector.d.ts +11 -0
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/theme-selector.js +50 -0
- package/dist/modes/interactive/components/theme-selector.js.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.js +51 -0
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +58 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-execution.js +274 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +87 -0
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/tree-selector.js +1051 -0
- package/dist/modes/interactive/components/tree-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/user-message-selector.js +113 -0
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message.d.ts +9 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/user-message.js +28 -0
- package/dist/modes/interactive/components/user-message.js.map +1 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
- package/dist/modes/interactive/components/visual-truncate.js +33 -0
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +311 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-mode.js +3798 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -0
- package/dist/modes/interactive/theme/dark.json +85 -0
- package/dist/modes/interactive/theme/light.json +84 -0
- package/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/dist/modes/interactive/theme/theme.d.ts +81 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme.js +975 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -0
- package/dist/modes/print-mode.d.ts +28 -0
- package/dist/modes/print-mode.d.ts.map +1 -0
- package/dist/modes/print-mode.js +107 -0
- package/dist/modes/print-mode.js.map +1 -0
- package/dist/modes/rpc/jsonl.d.ts +17 -0
- package/dist/modes/rpc/jsonl.d.ts.map +1 -0
- package/dist/modes/rpc/jsonl.js +49 -0
- package/dist/modes/rpc/jsonl.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +217 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-client.js +401 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -0
- package/dist/modes/rpc/rpc-mode.d.ts +20 -0
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-mode.js +522 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -0
- package/dist/modes/rpc/rpc-types.d.ts +408 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-types.js +8 -0
- package/dist/modes/rpc/rpc-types.js.map +1 -0
- package/dist/utils/changelog.d.ts +21 -0
- package/dist/utils/changelog.d.ts.map +1 -0
- package/dist/utils/changelog.js +87 -0
- package/dist/utils/changelog.js.map +1 -0
- package/dist/utils/child-process.d.ts +11 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +78 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts +11 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -0
- package/dist/utils/clipboard-image.js +245 -0
- package/dist/utils/clipboard-image.js.map +1 -0
- package/dist/utils/clipboard-native.d.ts +8 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -0
- package/dist/utils/clipboard-native.js +14 -0
- package/dist/utils/clipboard-native.js.map +1 -0
- package/dist/utils/clipboard.d.ts +2 -0
- package/dist/utils/clipboard.d.ts.map +1 -0
- package/dist/utils/clipboard.js +78 -0
- package/dist/utils/clipboard.js.map +1 -0
- package/dist/utils/exif-orientation.d.ts +5 -0
- package/dist/utils/exif-orientation.d.ts.map +1 -0
- package/dist/utils/exif-orientation.js +158 -0
- package/dist/utils/exif-orientation.js.map +1 -0
- package/dist/utils/frontmatter.d.ts +8 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +26 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/git.d.ts +26 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +163 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/image-convert.d.ts +9 -0
- package/dist/utils/image-convert.d.ts.map +1 -0
- package/dist/utils/image-convert.js +39 -0
- package/dist/utils/image-convert.js.map +1 -0
- package/dist/utils/image-resize.d.ts +36 -0
- package/dist/utils/image-resize.d.ts.map +1 -0
- package/dist/utils/image-resize.js +137 -0
- package/dist/utils/image-resize.js.map +1 -0
- package/dist/utils/mime.d.ts +2 -0
- package/dist/utils/mime.d.ts.map +1 -0
- package/dist/utils/mime.js +26 -0
- package/dist/utils/mime.js.map +1 -0
- package/dist/utils/photon.d.ts +21 -0
- package/dist/utils/photon.d.ts.map +1 -0
- package/dist/utils/photon.js +121 -0
- package/dist/utils/photon.js.map +1 -0
- package/dist/utils/shell.d.ts +26 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +186 -0
- package/dist/utils/shell.js.map +1 -0
- package/dist/utils/sleep.d.ts +5 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +17 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/tools-manager.d.ts +3 -0
- package/dist/utils/tools-manager.d.ts.map +1 -0
- package/dist/utils/tools-manager.js +252 -0
- package/dist/utils/tools-manager.js.map +1 -0
- package/docs/compaction.md +394 -0
- package/docs/custom-provider.md +327 -0
- package/docs/extensions.md +2229 -0
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/exy.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/json.md +82 -0
- package/docs/keybindings.md +173 -0
- package/docs/models.md +197 -0
- package/docs/packages.md +218 -0
- package/docs/prompt-templates.md +67 -0
- package/docs/providers.md +98 -0
- package/docs/release.md +40 -0
- package/docs/rpc.md +1377 -0
- package/docs/sdk.md +971 -0
- package/docs/session.md +412 -0
- package/docs/settings.md +149 -0
- package/docs/shell-aliases.md +13 -0
- package/docs/skills.md +232 -0
- package/docs/terminal-setup.md +106 -0
- package/docs/termux.md +127 -0
- package/docs/themes.md +295 -0
- package/docs/tmux.md +61 -0
- package/docs/tree.md +228 -0
- package/docs/tui.md +887 -0
- package/docs/windows.md +17 -0
- package/examples/README.md +25 -0
- package/examples/extensions/README.md +204 -0
- package/examples/extensions/auto-commit-on-exit.ts +49 -0
- package/examples/extensions/bash-spawn-hook.ts +30 -0
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/built-in-tool-renderer.ts +246 -0
- package/examples/extensions/claude-rules.ts +86 -0
- package/examples/extensions/commands.ts +72 -0
- package/examples/extensions/confirm-destructive.ts +59 -0
- package/examples/extensions/custom-compaction.ts +127 -0
- package/examples/extensions/custom-footer.ts +64 -0
- package/examples/extensions/custom-header.ts +73 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/dirty-repo-guard.ts +56 -0
- package/examples/extensions/doom-overlay/README.md +46 -0
- package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
- package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
- package/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
- package/examples/extensions/doom-overlay/doom-component.ts +132 -0
- package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
- package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
- package/examples/extensions/doom-overlay/index.ts +74 -0
- package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
- package/examples/extensions/dynamic-resources/SKILL.md +8 -0
- package/examples/extensions/dynamic-resources/dynamic.json +79 -0
- package/examples/extensions/dynamic-resources/dynamic.md +5 -0
- package/examples/extensions/dynamic-resources/index.ts +15 -0
- package/examples/extensions/dynamic-tools.ts +74 -0
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/file-trigger.ts +41 -0
- package/examples/extensions/git-checkpoint.ts +53 -0
- package/examples/extensions/handoff.ts +153 -0
- package/examples/extensions/hello.ts +25 -0
- package/examples/extensions/hidden-thinking-label.ts +57 -0
- package/examples/extensions/inline-bash.ts +94 -0
- package/examples/extensions/input-transform.ts +43 -0
- package/examples/extensions/interactive-shell.ts +196 -0
- package/examples/extensions/mac-system-theme.ts +47 -0
- package/examples/extensions/message-renderer.ts +59 -0
- package/examples/extensions/minimal-mode.ts +426 -0
- package/examples/extensions/modal-editor.ts +85 -0
- package/examples/extensions/model-status.ts +31 -0
- package/examples/extensions/notify.ts +55 -0
- package/examples/extensions/overlay-qa-tests.ts +1348 -0
- package/examples/extensions/overlay-test.ts +150 -0
- package/examples/extensions/permission-gate.ts +34 -0
- package/examples/extensions/pirate.ts +47 -0
- package/examples/extensions/plan-mode/README.md +65 -0
- package/examples/extensions/plan-mode/index.ts +340 -0
- package/examples/extensions/plan-mode/utils.ts +166 -0
- package/examples/extensions/preset.ts +397 -0
- package/examples/extensions/protected-paths.ts +30 -0
- package/examples/extensions/provider-payload.ts +14 -0
- package/examples/extensions/qna.ts +122 -0
- package/examples/extensions/question.ts +264 -0
- package/examples/extensions/questionnaire.ts +427 -0
- package/examples/extensions/rainbow-editor.ts +88 -0
- package/examples/extensions/reload-runtime.ts +37 -0
- package/examples/extensions/rpc-demo.ts +124 -0
- package/examples/extensions/sandbox/index.ts +321 -0
- package/examples/extensions/sandbox/package.json +19 -0
- package/examples/extensions/send-user-message.ts +97 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/shutdown-command.ts +63 -0
- package/examples/extensions/snake.ts +343 -0
- package/examples/extensions/space-invaders.ts +560 -0
- package/examples/extensions/ssh.ts +220 -0
- package/examples/extensions/status-line.ts +40 -0
- package/examples/extensions/subagent/README.md +172 -0
- package/examples/extensions/subagent/agents/planner.md +37 -0
- package/examples/extensions/subagent/agents/reviewer.md +35 -0
- package/examples/extensions/subagent/agents/scout.md +50 -0
- package/examples/extensions/subagent/agents/worker.md +24 -0
- package/examples/extensions/subagent/agents.ts +126 -0
- package/examples/extensions/subagent/index.ts +986 -0
- package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
- package/examples/extensions/subagent/prompts/implement.md +10 -0
- package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
- package/examples/extensions/summarize.ts +206 -0
- package/examples/extensions/system-prompt-header.ts +17 -0
- package/examples/extensions/timed-confirm.ts +70 -0
- package/examples/extensions/titlebar-spinner.ts +58 -0
- package/examples/extensions/todo.ts +299 -0
- package/examples/extensions/tool-override.ts +144 -0
- package/examples/extensions/tools.ts +146 -0
- package/examples/extensions/trigger-compact.ts +50 -0
- package/examples/extensions/truncated-tool.ts +195 -0
- package/examples/extensions/widget-placement.ts +17 -0
- package/examples/extensions/with-deps/index.ts +32 -0
- package/examples/extensions/with-deps/package.json +22 -0
- package/examples/rpc-extension-ui.ts +632 -0
- package/examples/sdk/01-minimal.ts +22 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +55 -0
- package/examples/sdk/04-skills.ts +52 -0
- package/examples/sdk/05-tools.ts +56 -0
- package/examples/sdk/06-extensions.ts +88 -0
- package/examples/sdk/07-context-files.ts +40 -0
- package/examples/sdk/08-prompt-templates.ts +48 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +48 -0
- package/examples/sdk/10-settings.ts +51 -0
- package/examples/sdk/11-sessions.ts +48 -0
- package/examples/sdk/12-full-control.ts +81 -0
- package/examples/sdk/README.md +144 -0
- package/package.json +95 -0
- package/src/bun/cli.ts +5 -0
- package/src/cli/args.ts +309 -0
- package/src/cli/config-selector.ts +52 -0
- package/src/cli/file-processor.ts +100 -0
- package/src/cli/initial-message.ts +43 -0
- package/src/cli/list-models.ts +104 -0
- package/src/cli/session-picker.ts +52 -0
- package/src/cli.ts +16 -0
- package/src/config.ts +214 -0
- package/src/core/agent-session.ts +3279 -0
- package/src/core/auth-storage.ts +488 -0
- package/src/core/bash-executor.ts +158 -0
- package/src/core/compaction/branch-summarization.ts +355 -0
- package/src/core/compaction/compaction.ts +823 -0
- package/src/core/compaction/index.ts +7 -0
- package/src/core/compaction/utils.ts +170 -0
- package/src/core/defaults.ts +3 -0
- package/src/core/diagnostics.ts +15 -0
- package/src/core/event-bus.ts +33 -0
- package/src/core/exec.ts +107 -0
- package/src/core/export-html/ansi-to-html.ts +258 -0
- package/src/core/export-html/index.ts +314 -0
- package/src/core/export-html/template.css +1001 -0
- package/src/core/export-html/template.html +55 -0
- package/src/core/export-html/template.js +1690 -0
- package/src/core/export-html/tool-renderer.ts +156 -0
- package/src/core/export-html/vendor/highlight.min.js +1213 -0
- package/src/core/export-html/vendor/marked.min.js +6 -0
- package/src/core/extensions/index.ts +168 -0
- package/src/core/extensions/loader.ts +557 -0
- package/src/core/extensions/runner.ts +915 -0
- package/src/core/extensions/types.ts +1461 -0
- package/src/core/extensions/wrapper.ts +27 -0
- package/src/core/footer-data-provider.ts +273 -0
- package/src/core/index.ts +61 -0
- package/src/core/keybindings.ts +302 -0
- package/src/core/messages.ts +195 -0
- package/src/core/model-registry.ts +766 -0
- package/src/core/model-resolver.ts +606 -0
- package/src/core/output-guard.ts +74 -0
- package/src/core/package-manager.ts +2222 -0
- package/src/core/prompt-templates.ts +294 -0
- package/src/core/resolve-config-value.ts +142 -0
- package/src/core/resource-loader.ts +886 -0
- package/src/core/sdk.ts +360 -0
- package/src/core/self-update.ts +57 -0
- package/src/core/session-manager.ts +1410 -0
- package/src/core/settings-manager.ts +973 -0
- package/src/core/skills.ts +508 -0
- package/src/core/slash-commands.ts +37 -0
- package/src/core/source-info.ts +40 -0
- package/src/core/system-prompt.ts +168 -0
- package/src/core/timings.ts +31 -0
- package/src/core/tools/bash.ts +431 -0
- package/src/core/tools/edit-diff.ts +445 -0
- package/src/core/tools/edit.ts +307 -0
- package/src/core/tools/file-mutation-queue.ts +39 -0
- package/src/core/tools/find.ts +314 -0
- package/src/core/tools/grep.ts +375 -0
- package/src/core/tools/index.ts +193 -0
- package/src/core/tools/ls.ts +233 -0
- package/src/core/tools/path-utils.ts +94 -0
- package/src/core/tools/read.ts +269 -0
- package/src/core/tools/render-utils.ts +64 -0
- package/src/core/tools/tool-definition-wrapper.ts +43 -0
- package/src/core/tools/truncate.ts +265 -0
- package/src/core/tools/write.ts +285 -0
- package/src/core/version-check.ts +85 -0
- package/src/index.ts +348 -0
- package/src/main.ts +958 -0
- package/src/migrations.ts +290 -0
- package/src/modes/index.ts +9 -0
- package/src/modes/interactive/components/armin.ts +382 -0
- package/src/modes/interactive/components/assistant-message.ts +130 -0
- package/src/modes/interactive/components/bash-execution.ts +218 -0
- package/src/modes/interactive/components/bordered-loader.ts +66 -0
- package/src/modes/interactive/components/branch-summary-message.ts +58 -0
- package/src/modes/interactive/components/compaction-summary-message.ts +59 -0
- package/src/modes/interactive/components/config-selector.ts +592 -0
- package/src/modes/interactive/components/countdown-timer.ts +38 -0
- package/src/modes/interactive/components/custom-editor.ts +80 -0
- package/src/modes/interactive/components/custom-message.ts +99 -0
- package/src/modes/interactive/components/diff.ts +147 -0
- package/src/modes/interactive/components/dynamic-border.ts +25 -0
- package/src/modes/interactive/components/extension-editor.ts +147 -0
- package/src/modes/interactive/components/extension-input.ts +87 -0
- package/src/modes/interactive/components/extension-selector.ts +107 -0
- package/src/modes/interactive/components/footer.ts +216 -0
- package/src/modes/interactive/components/index.ts +31 -0
- package/src/modes/interactive/components/keybinding-hints.ts +24 -0
- package/src/modes/interactive/components/login-dialog.ts +178 -0
- package/src/modes/interactive/components/model-selector.ts +328 -0
- package/src/modes/interactive/components/oauth-selector.ts +121 -0
- package/src/modes/interactive/components/scoped-models-selector.ts +346 -0
- package/src/modes/interactive/components/session-selector-search.ts +194 -0
- package/src/modes/interactive/components/session-selector.ts +1010 -0
- package/src/modes/interactive/components/settings-selector.ts +432 -0
- package/src/modes/interactive/components/show-images-selector.ts +50 -0
- package/src/modes/interactive/components/skill-invocation-message.ts +55 -0
- package/src/modes/interactive/components/theme-selector.ts +67 -0
- package/src/modes/interactive/components/thinking-selector.ts +74 -0
- package/src/modes/interactive/components/tool-execution.ts +328 -0
- package/src/modes/interactive/components/tree-selector.ts +1197 -0
- package/src/modes/interactive/components/user-message-selector.ts +143 -0
- package/src/modes/interactive/components/user-message.ts +33 -0
- package/src/modes/interactive/components/visual-truncate.ts +50 -0
- package/src/modes/interactive/interactive-mode.ts +4501 -0
- package/src/modes/interactive/theme/dark.json +85 -0
- package/src/modes/interactive/theme/light.json +84 -0
- package/src/modes/interactive/theme/theme-schema.json +335 -0
- package/src/modes/interactive/theme/theme.ts +1137 -0
- package/src/modes/print-mode.ts +131 -0
- package/src/modes/rpc/jsonl.ts +58 -0
- package/src/modes/rpc/rpc-client.ts +505 -0
- package/src/modes/rpc/rpc-mode.ts +654 -0
- package/src/modes/rpc/rpc-types.ts +262 -0
- package/src/utils/changelog.ts +99 -0
- package/src/utils/child-process.ts +86 -0
- package/src/utils/clipboard-image.ts +300 -0
- package/src/utils/clipboard-native.ts +22 -0
- package/src/utils/clipboard.ts +81 -0
- package/src/utils/exif-orientation.ts +183 -0
- package/src/utils/frontmatter.ts +39 -0
- package/src/utils/git.ts +192 -0
- package/src/utils/image-convert.ts +41 -0
- package/src/utils/image-resize.ts +176 -0
- package/src/utils/mime.ts +30 -0
- package/src/utils/photon.ts +139 -0
- package/src/utils/shell.ts +202 -0
- package/src/utils/sleep.ts +18 -0
- package/src/utils/tools-manager.ts +287 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import type { AgentTool } from "@lenylvt/pi-agent-core";
|
|
2
|
+
import { Text } from "@lenylvt/pi-tui";
|
|
3
|
+
import { type Static, Type } from "@sinclair/typebox";
|
|
4
|
+
import { existsSync, readdirSync, statSync } from "fs";
|
|
5
|
+
import nodePath from "path";
|
|
6
|
+
import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
7
|
+
import type { ToolDefinition, ToolRenderResultOptions } from "../extensions/types.js";
|
|
8
|
+
import { resolveToCwd } from "./path-utils.js";
|
|
9
|
+
import { getTextOutput, invalidArgText, shortenPath, str } from "./render-utils.js";
|
|
10
|
+
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
11
|
+
import { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from "./truncate.js";
|
|
12
|
+
|
|
13
|
+
const lsSchema = Type.Object({
|
|
14
|
+
path: Type.Optional(Type.String({ description: "Directory to list (default: current directory)" })),
|
|
15
|
+
limit: Type.Optional(Type.Number({ description: "Maximum number of entries to return (default: 500)" })),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export type LsToolInput = Static<typeof lsSchema>;
|
|
19
|
+
|
|
20
|
+
const DEFAULT_LIMIT = 500;
|
|
21
|
+
|
|
22
|
+
export interface LsToolDetails {
|
|
23
|
+
truncation?: TruncationResult;
|
|
24
|
+
entryLimitReached?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Pluggable operations for the ls tool.
|
|
29
|
+
* Override these to delegate directory listing to remote systems (for example SSH).
|
|
30
|
+
*/
|
|
31
|
+
export interface LsOperations {
|
|
32
|
+
/** Check if path exists */
|
|
33
|
+
exists: (absolutePath: string) => Promise<boolean> | boolean;
|
|
34
|
+
/** Get file or directory stats. Throws if not found. */
|
|
35
|
+
stat: (absolutePath: string) => Promise<{ isDirectory: () => boolean }> | { isDirectory: () => boolean };
|
|
36
|
+
/** Read directory entries */
|
|
37
|
+
readdir: (absolutePath: string) => Promise<string[]> | string[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const defaultLsOperations: LsOperations = {
|
|
41
|
+
exists: existsSync,
|
|
42
|
+
stat: statSync,
|
|
43
|
+
readdir: readdirSync,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export interface LsToolOptions {
|
|
47
|
+
/** Custom operations for directory listing. Default: local filesystem */
|
|
48
|
+
operations?: LsOperations;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function formatLsCall(
|
|
52
|
+
args: { path?: string; limit?: number } | undefined,
|
|
53
|
+
theme: typeof import("../../modes/interactive/theme/theme.js").theme,
|
|
54
|
+
): string {
|
|
55
|
+
const rawPath = str(args?.path);
|
|
56
|
+
const path = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
57
|
+
const limit = args?.limit;
|
|
58
|
+
const invalidArg = invalidArgText(theme);
|
|
59
|
+
let text = `${theme.fg("toolTitle", theme.bold("ls"))} ${path === null ? invalidArg : theme.fg("accent", path)}`;
|
|
60
|
+
if (limit !== undefined) {
|
|
61
|
+
text += theme.fg("toolOutput", ` (limit ${limit})`);
|
|
62
|
+
}
|
|
63
|
+
return text;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function formatLsResult(
|
|
67
|
+
result: {
|
|
68
|
+
content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;
|
|
69
|
+
details?: LsToolDetails;
|
|
70
|
+
},
|
|
71
|
+
options: ToolRenderResultOptions,
|
|
72
|
+
theme: typeof import("../../modes/interactive/theme/theme.js").theme,
|
|
73
|
+
showImages: boolean,
|
|
74
|
+
): string {
|
|
75
|
+
const output = getTextOutput(result, showImages).trim();
|
|
76
|
+
let text = "";
|
|
77
|
+
if (output) {
|
|
78
|
+
const lines = output.split("\n");
|
|
79
|
+
const maxLines = options.expanded ? lines.length : 20;
|
|
80
|
+
const displayLines = lines.slice(0, maxLines);
|
|
81
|
+
const remaining = lines.length - maxLines;
|
|
82
|
+
text += `\n${displayLines.map((line) => theme.fg("toolOutput", line)).join("\n")}`;
|
|
83
|
+
if (remaining > 0) {
|
|
84
|
+
text += `${theme.fg("muted", `\n... (${remaining} more lines,`)} ${keyHint("app.tools.expand", "to expand")})`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const entryLimit = result.details?.entryLimitReached;
|
|
89
|
+
const truncation = result.details?.truncation;
|
|
90
|
+
if (entryLimit || truncation?.truncated) {
|
|
91
|
+
const warnings: string[] = [];
|
|
92
|
+
if (entryLimit) warnings.push(`${entryLimit} entries limit`);
|
|
93
|
+
if (truncation?.truncated) warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);
|
|
94
|
+
text += `\n${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
|
|
95
|
+
}
|
|
96
|
+
return text;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function createLsToolDefinition(
|
|
100
|
+
cwd: string,
|
|
101
|
+
options?: LsToolOptions,
|
|
102
|
+
): ToolDefinition<typeof lsSchema, LsToolDetails | undefined> {
|
|
103
|
+
const ops = options?.operations ?? defaultLsOperations;
|
|
104
|
+
return {
|
|
105
|
+
name: "ls",
|
|
106
|
+
label: "ls",
|
|
107
|
+
description: `List directory contents. Returns entries sorted alphabetically, with '/' suffix for directories. Includes dotfiles. Output is truncated to ${DEFAULT_LIMIT} entries or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first).`,
|
|
108
|
+
promptSnippet: "List directory contents",
|
|
109
|
+
parameters: lsSchema,
|
|
110
|
+
async execute(
|
|
111
|
+
_toolCallId,
|
|
112
|
+
{ path, limit }: { path?: string; limit?: number },
|
|
113
|
+
signal?: AbortSignal,
|
|
114
|
+
_onUpdate?,
|
|
115
|
+
_ctx?,
|
|
116
|
+
) {
|
|
117
|
+
return new Promise((resolve, reject) => {
|
|
118
|
+
if (signal?.aborted) {
|
|
119
|
+
reject(new Error("Operation aborted"));
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const onAbort = () => reject(new Error("Operation aborted"));
|
|
124
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
125
|
+
|
|
126
|
+
(async () => {
|
|
127
|
+
try {
|
|
128
|
+
const dirPath = resolveToCwd(path || ".", cwd);
|
|
129
|
+
const effectiveLimit = limit ?? DEFAULT_LIMIT;
|
|
130
|
+
|
|
131
|
+
// Check if path exists.
|
|
132
|
+
if (!(await ops.exists(dirPath))) {
|
|
133
|
+
reject(new Error(`Path not found: ${dirPath}`));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Check if path is a directory.
|
|
138
|
+
const stat = await ops.stat(dirPath);
|
|
139
|
+
if (!stat.isDirectory()) {
|
|
140
|
+
reject(new Error(`Not a directory: ${dirPath}`));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Read directory entries.
|
|
145
|
+
let entries: string[];
|
|
146
|
+
try {
|
|
147
|
+
entries = await ops.readdir(dirPath);
|
|
148
|
+
} catch (e: any) {
|
|
149
|
+
reject(new Error(`Cannot read directory: ${e.message}`));
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Sort alphabetically, case-insensitive.
|
|
154
|
+
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
155
|
+
|
|
156
|
+
// Format entries with directory indicators.
|
|
157
|
+
const results: string[] = [];
|
|
158
|
+
let entryLimitReached = false;
|
|
159
|
+
for (const entry of entries) {
|
|
160
|
+
if (results.length >= effectiveLimit) {
|
|
161
|
+
entryLimitReached = true;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const fullPath = nodePath.join(dirPath, entry);
|
|
166
|
+
let suffix = "";
|
|
167
|
+
try {
|
|
168
|
+
const entryStat = await ops.stat(fullPath);
|
|
169
|
+
if (entryStat.isDirectory()) suffix = "/";
|
|
170
|
+
} catch {
|
|
171
|
+
// Skip entries we cannot stat.
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
results.push(entry + suffix);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
signal?.removeEventListener("abort", onAbort);
|
|
178
|
+
|
|
179
|
+
if (results.length === 0) {
|
|
180
|
+
resolve({ content: [{ type: "text", text: "(empty directory)" }], details: undefined });
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const rawOutput = results.join("\n");
|
|
185
|
+
// Apply byte truncation. There is no separate line limit because entry count is already capped.
|
|
186
|
+
const truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });
|
|
187
|
+
let output = truncation.content;
|
|
188
|
+
const details: LsToolDetails = {};
|
|
189
|
+
// Build actionable notices for truncation and entry limits.
|
|
190
|
+
const notices: string[] = [];
|
|
191
|
+
if (entryLimitReached) {
|
|
192
|
+
notices.push(`${effectiveLimit} entries limit reached. Use limit=${effectiveLimit * 2} for more`);
|
|
193
|
+
details.entryLimitReached = effectiveLimit;
|
|
194
|
+
}
|
|
195
|
+
if (truncation.truncated) {
|
|
196
|
+
notices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);
|
|
197
|
+
details.truncation = truncation;
|
|
198
|
+
}
|
|
199
|
+
if (notices.length > 0) {
|
|
200
|
+
output += `\n\n[${notices.join(". ")}]`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
resolve({
|
|
204
|
+
content: [{ type: "text", text: output }],
|
|
205
|
+
details: Object.keys(details).length > 0 ? details : undefined,
|
|
206
|
+
});
|
|
207
|
+
} catch (e: any) {
|
|
208
|
+
signal?.removeEventListener("abort", onAbort);
|
|
209
|
+
reject(e);
|
|
210
|
+
}
|
|
211
|
+
})();
|
|
212
|
+
});
|
|
213
|
+
},
|
|
214
|
+
renderCall(args, theme, context) {
|
|
215
|
+
const text = (context.lastComponent as Text | undefined) ?? new Text("", 0, 0);
|
|
216
|
+
text.setText(formatLsCall(args, theme));
|
|
217
|
+
return text;
|
|
218
|
+
},
|
|
219
|
+
renderResult(result, options, theme, context) {
|
|
220
|
+
const text = (context.lastComponent as Text | undefined) ?? new Text("", 0, 0);
|
|
221
|
+
text.setText(formatLsResult(result as any, options, theme, context.showImages));
|
|
222
|
+
return text;
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function createLsTool(cwd: string, options?: LsToolOptions): AgentTool<typeof lsSchema> {
|
|
228
|
+
return wrapToolDefinition(createLsToolDefinition(cwd, options));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Default ls tool using process.cwd() for backwards compatibility. */
|
|
232
|
+
export const lsToolDefinition = createLsToolDefinition(process.cwd());
|
|
233
|
+
export const lsTool = createLsTool(process.cwd());
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { accessSync, constants } from "node:fs";
|
|
2
|
+
import * as os from "node:os";
|
|
3
|
+
import { isAbsolute, resolve as resolvePath } from "node:path";
|
|
4
|
+
|
|
5
|
+
const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
|
|
6
|
+
const NARROW_NO_BREAK_SPACE = "\u202F";
|
|
7
|
+
function normalizeUnicodeSpaces(str: string): string {
|
|
8
|
+
return str.replace(UNICODE_SPACES, " ");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function tryMacOSScreenshotPath(filePath: string): string {
|
|
12
|
+
return filePath.replace(/ (AM|PM)\./g, `${NARROW_NO_BREAK_SPACE}$1.`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function tryNFDVariant(filePath: string): string {
|
|
16
|
+
// macOS stores filenames in NFD (decomposed) form, try converting user input to NFD
|
|
17
|
+
return filePath.normalize("NFD");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function tryCurlyQuoteVariant(filePath: string): string {
|
|
21
|
+
// macOS uses U+2019 (right single quotation mark) in screenshot names like "Capture d'écran"
|
|
22
|
+
// Users typically type U+0027 (straight apostrophe)
|
|
23
|
+
return filePath.replace(/'/g, "\u2019");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function fileExists(filePath: string): boolean {
|
|
27
|
+
try {
|
|
28
|
+
accessSync(filePath, constants.F_OK);
|
|
29
|
+
return true;
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function normalizeAtPrefix(filePath: string): string {
|
|
36
|
+
return filePath.startsWith("@") ? filePath.slice(1) : filePath;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function expandPath(filePath: string): string {
|
|
40
|
+
const normalized = normalizeUnicodeSpaces(normalizeAtPrefix(filePath));
|
|
41
|
+
if (normalized === "~") {
|
|
42
|
+
return os.homedir();
|
|
43
|
+
}
|
|
44
|
+
if (normalized.startsWith("~/")) {
|
|
45
|
+
return os.homedir() + normalized.slice(1);
|
|
46
|
+
}
|
|
47
|
+
return normalized;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Resolve a path relative to the given cwd.
|
|
52
|
+
* Handles ~ expansion and absolute paths.
|
|
53
|
+
*/
|
|
54
|
+
export function resolveToCwd(filePath: string, cwd: string): string {
|
|
55
|
+
const expanded = expandPath(filePath);
|
|
56
|
+
if (isAbsolute(expanded)) {
|
|
57
|
+
return expanded;
|
|
58
|
+
}
|
|
59
|
+
return resolvePath(cwd, expanded);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function resolveReadPath(filePath: string, cwd: string): string {
|
|
63
|
+
const resolved = resolveToCwd(filePath, cwd);
|
|
64
|
+
|
|
65
|
+
if (fileExists(resolved)) {
|
|
66
|
+
return resolved;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Try macOS AM/PM variant (narrow no-break space before AM/PM)
|
|
70
|
+
const amPmVariant = tryMacOSScreenshotPath(resolved);
|
|
71
|
+
if (amPmVariant !== resolved && fileExists(amPmVariant)) {
|
|
72
|
+
return amPmVariant;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Try NFD variant (macOS stores filenames in NFD form)
|
|
76
|
+
const nfdVariant = tryNFDVariant(resolved);
|
|
77
|
+
if (nfdVariant !== resolved && fileExists(nfdVariant)) {
|
|
78
|
+
return nfdVariant;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Try curly quote variant (macOS uses U+2019 in screenshot names)
|
|
82
|
+
const curlyVariant = tryCurlyQuoteVariant(resolved);
|
|
83
|
+
if (curlyVariant !== resolved && fileExists(curlyVariant)) {
|
|
84
|
+
return curlyVariant;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Try combined NFD + curly quote (for French macOS screenshots like "Capture d'écran")
|
|
88
|
+
const nfdCurlyVariant = tryCurlyQuoteVariant(nfdVariant);
|
|
89
|
+
if (nfdCurlyVariant !== resolved && fileExists(nfdCurlyVariant)) {
|
|
90
|
+
return nfdCurlyVariant;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return resolved;
|
|
94
|
+
}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import type { AgentTool } from "@lenylvt/pi-agent-core";
|
|
2
|
+
import type { ImageContent, TextContent } from "@lenylvt/pi-ai";
|
|
3
|
+
import { Text } from "@lenylvt/pi-tui";
|
|
4
|
+
import { type Static, Type } from "@sinclair/typebox";
|
|
5
|
+
import { constants } from "fs";
|
|
6
|
+
import { access as fsAccess, readFile as fsReadFile } from "fs/promises";
|
|
7
|
+
import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
8
|
+
import { getLanguageFromPath, highlightCode } from "../../modes/interactive/theme/theme.js";
|
|
9
|
+
import { formatDimensionNote, resizeImage } from "../../utils/image-resize.js";
|
|
10
|
+
import { detectSupportedImageMimeTypeFromFile } from "../../utils/mime.js";
|
|
11
|
+
import type { ToolDefinition, ToolRenderResultOptions } from "../extensions/types.js";
|
|
12
|
+
import { resolveReadPath } from "./path-utils.js";
|
|
13
|
+
import { getTextOutput, invalidArgText, replaceTabs, shortenPath, str } from "./render-utils.js";
|
|
14
|
+
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
15
|
+
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult, truncateHead } from "./truncate.js";
|
|
16
|
+
|
|
17
|
+
const readSchema = Type.Object({
|
|
18
|
+
path: Type.String({ description: "Path to the file to read (relative or absolute)" }),
|
|
19
|
+
offset: Type.Optional(Type.Number({ description: "Line number to start reading from (1-indexed)" })),
|
|
20
|
+
limit: Type.Optional(Type.Number({ description: "Maximum number of lines to read" })),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export type ReadToolInput = Static<typeof readSchema>;
|
|
24
|
+
|
|
25
|
+
export interface ReadToolDetails {
|
|
26
|
+
truncation?: TruncationResult;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Pluggable operations for the read tool.
|
|
31
|
+
* Override these to delegate file reading to remote systems (for example SSH).
|
|
32
|
+
*/
|
|
33
|
+
export interface ReadOperations {
|
|
34
|
+
/** Read file contents as a Buffer */
|
|
35
|
+
readFile: (absolutePath: string) => Promise<Buffer>;
|
|
36
|
+
/** Check if file is readable (throw if not) */
|
|
37
|
+
access: (absolutePath: string) => Promise<void>;
|
|
38
|
+
/** Detect image MIME type, return null or undefined for non-images */
|
|
39
|
+
detectImageMimeType?: (absolutePath: string) => Promise<string | null | undefined>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const defaultReadOperations: ReadOperations = {
|
|
43
|
+
readFile: (path) => fsReadFile(path),
|
|
44
|
+
access: (path) => fsAccess(path, constants.R_OK),
|
|
45
|
+
detectImageMimeType: detectSupportedImageMimeTypeFromFile,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export interface ReadToolOptions {
|
|
49
|
+
/** Whether to auto-resize images to 2000x2000 max. Default: true */
|
|
50
|
+
autoResizeImages?: boolean;
|
|
51
|
+
/** Custom operations for file reading. Default: local filesystem */
|
|
52
|
+
operations?: ReadOperations;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function formatReadCall(
|
|
56
|
+
args: { path?: string; file_path?: string; offset?: number; limit?: number } | undefined,
|
|
57
|
+
theme: typeof import("../../modes/interactive/theme/theme.js").theme,
|
|
58
|
+
): string {
|
|
59
|
+
const rawPath = str(args?.file_path ?? args?.path);
|
|
60
|
+
const path = rawPath !== null ? shortenPath(rawPath) : null;
|
|
61
|
+
const offset = args?.offset;
|
|
62
|
+
const limit = args?.limit;
|
|
63
|
+
const invalidArg = invalidArgText(theme);
|
|
64
|
+
let pathDisplay = path === null ? invalidArg : path ? theme.fg("accent", path) : theme.fg("toolOutput", "...");
|
|
65
|
+
if (offset !== undefined || limit !== undefined) {
|
|
66
|
+
const startLine = offset ?? 1;
|
|
67
|
+
const endLine = limit !== undefined ? startLine + limit - 1 : "";
|
|
68
|
+
pathDisplay += theme.fg("warning", `:${startLine}${endLine ? `-${endLine}` : ""}`);
|
|
69
|
+
}
|
|
70
|
+
return `${theme.fg("toolTitle", theme.bold("read"))} ${pathDisplay}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function trimTrailingEmptyLines(lines: string[]): string[] {
|
|
74
|
+
let end = lines.length;
|
|
75
|
+
while (end > 0 && lines[end - 1] === "") {
|
|
76
|
+
end--;
|
|
77
|
+
}
|
|
78
|
+
return lines.slice(0, end);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function formatReadResult(
|
|
82
|
+
args: { path?: string; file_path?: string; offset?: number; limit?: number } | undefined,
|
|
83
|
+
result: { content: (TextContent | ImageContent)[]; details?: ReadToolDetails },
|
|
84
|
+
options: ToolRenderResultOptions,
|
|
85
|
+
theme: typeof import("../../modes/interactive/theme/theme.js").theme,
|
|
86
|
+
showImages: boolean,
|
|
87
|
+
): string {
|
|
88
|
+
const rawPath = str(args?.file_path ?? args?.path);
|
|
89
|
+
const output = getTextOutput(result as any, showImages);
|
|
90
|
+
const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
|
|
91
|
+
const renderedLines = lang ? highlightCode(replaceTabs(output), lang) : output.split("\n");
|
|
92
|
+
const lines = trimTrailingEmptyLines(renderedLines);
|
|
93
|
+
const maxLines = options.expanded ? lines.length : 10;
|
|
94
|
+
const displayLines = lines.slice(0, maxLines);
|
|
95
|
+
const remaining = lines.length - maxLines;
|
|
96
|
+
let text = `\n${displayLines.map((line) => (lang ? replaceTabs(line) : theme.fg("toolOutput", replaceTabs(line)))).join("\n")}`;
|
|
97
|
+
if (remaining > 0) {
|
|
98
|
+
text += `${theme.fg("muted", `\n... (${remaining} more lines,`)} ${keyHint("app.tools.expand", "to expand")})`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const truncation = result.details?.truncation;
|
|
102
|
+
if (truncation?.truncated) {
|
|
103
|
+
if (truncation.firstLineExceedsLimit) {
|
|
104
|
+
text += `\n${theme.fg("warning", `[First line exceeds ${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit]`)}`;
|
|
105
|
+
} else if (truncation.truncatedBy === "lines") {
|
|
106
|
+
text += `\n${theme.fg("warning", `[Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines (${truncation.maxLines ?? DEFAULT_MAX_LINES} line limit)]`)}`;
|
|
107
|
+
} else {
|
|
108
|
+
text += `\n${theme.fg("warning", `[Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)]`)}`;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return text;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function createReadToolDefinition(
|
|
115
|
+
cwd: string,
|
|
116
|
+
options?: ReadToolOptions,
|
|
117
|
+
): ToolDefinition<typeof readSchema, ReadToolDetails | undefined> {
|
|
118
|
+
const autoResizeImages = options?.autoResizeImages ?? true;
|
|
119
|
+
const ops = options?.operations ?? defaultReadOperations;
|
|
120
|
+
return {
|
|
121
|
+
name: "read",
|
|
122
|
+
label: "read",
|
|
123
|
+
description: `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.`,
|
|
124
|
+
promptSnippet: "Read file contents",
|
|
125
|
+
promptGuidelines: ["Use read to examine files instead of cat or sed."],
|
|
126
|
+
parameters: readSchema,
|
|
127
|
+
async execute(
|
|
128
|
+
_toolCallId,
|
|
129
|
+
{ path, offset, limit }: { path: string; offset?: number; limit?: number },
|
|
130
|
+
signal?: AbortSignal,
|
|
131
|
+
_onUpdate?,
|
|
132
|
+
_ctx?,
|
|
133
|
+
) {
|
|
134
|
+
const absolutePath = resolveReadPath(path, cwd);
|
|
135
|
+
return new Promise<{ content: (TextContent | ImageContent)[]; details: ReadToolDetails | undefined }>(
|
|
136
|
+
(resolve, reject) => {
|
|
137
|
+
if (signal?.aborted) {
|
|
138
|
+
reject(new Error("Operation aborted"));
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
let aborted = false;
|
|
142
|
+
const onAbort = () => {
|
|
143
|
+
aborted = true;
|
|
144
|
+
reject(new Error("Operation aborted"));
|
|
145
|
+
};
|
|
146
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
147
|
+
|
|
148
|
+
(async () => {
|
|
149
|
+
try {
|
|
150
|
+
// Check if file exists and is readable.
|
|
151
|
+
await ops.access(absolutePath);
|
|
152
|
+
if (aborted) return;
|
|
153
|
+
const mimeType = ops.detectImageMimeType ? await ops.detectImageMimeType(absolutePath) : undefined;
|
|
154
|
+
let content: (TextContent | ImageContent)[];
|
|
155
|
+
let details: ReadToolDetails | undefined;
|
|
156
|
+
if (mimeType) {
|
|
157
|
+
// Read image as binary.
|
|
158
|
+
const buffer = await ops.readFile(absolutePath);
|
|
159
|
+
const base64 = buffer.toString("base64");
|
|
160
|
+
if (autoResizeImages) {
|
|
161
|
+
// Resize image if needed before sending it back to the model.
|
|
162
|
+
const resized = await resizeImage({ type: "image", data: base64, mimeType });
|
|
163
|
+
if (!resized) {
|
|
164
|
+
content = [
|
|
165
|
+
{
|
|
166
|
+
type: "text",
|
|
167
|
+
text: `Read image file [${mimeType}]\n[Image omitted: could not be resized below the inline image size limit.]`,
|
|
168
|
+
},
|
|
169
|
+
];
|
|
170
|
+
} else {
|
|
171
|
+
const dimensionNote = formatDimensionNote(resized);
|
|
172
|
+
let textNote = `Read image file [${resized.mimeType}]`;
|
|
173
|
+
if (dimensionNote) textNote += `\n${dimensionNote}`;
|
|
174
|
+
content = [
|
|
175
|
+
{ type: "text", text: textNote },
|
|
176
|
+
{ type: "image", data: resized.data, mimeType: resized.mimeType },
|
|
177
|
+
];
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
content = [
|
|
181
|
+
{ type: "text", text: `Read image file [${mimeType}]` },
|
|
182
|
+
{ type: "image", data: base64, mimeType },
|
|
183
|
+
];
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
// Read text content.
|
|
187
|
+
const buffer = await ops.readFile(absolutePath);
|
|
188
|
+
const textContent = buffer.toString("utf-8");
|
|
189
|
+
const allLines = textContent.split("\n");
|
|
190
|
+
const totalFileLines = allLines.length;
|
|
191
|
+
// Apply offset if specified. Convert from 1-indexed input to 0-indexed array access.
|
|
192
|
+
const startLine = offset ? Math.max(0, offset - 1) : 0;
|
|
193
|
+
const startLineDisplay = startLine + 1;
|
|
194
|
+
// Check if offset is out of bounds.
|
|
195
|
+
if (startLine >= allLines.length) {
|
|
196
|
+
throw new Error(`Offset ${offset} is beyond end of file (${allLines.length} lines total)`);
|
|
197
|
+
}
|
|
198
|
+
let selectedContent: string;
|
|
199
|
+
let userLimitedLines: number | undefined;
|
|
200
|
+
// If limit is specified by the user, honor it first. Otherwise truncateHead decides.
|
|
201
|
+
if (limit !== undefined) {
|
|
202
|
+
const endLine = Math.min(startLine + limit, allLines.length);
|
|
203
|
+
selectedContent = allLines.slice(startLine, endLine).join("\n");
|
|
204
|
+
userLimitedLines = endLine - startLine;
|
|
205
|
+
} else {
|
|
206
|
+
selectedContent = allLines.slice(startLine).join("\n");
|
|
207
|
+
}
|
|
208
|
+
// Apply truncation, respecting both line and byte limits.
|
|
209
|
+
const truncation = truncateHead(selectedContent);
|
|
210
|
+
let outputText: string;
|
|
211
|
+
if (truncation.firstLineExceedsLimit) {
|
|
212
|
+
// First line alone exceeds the byte limit. Point the model at a bash fallback.
|
|
213
|
+
const firstLineSize = formatSize(Buffer.byteLength(allLines[startLine], "utf-8"));
|
|
214
|
+
outputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(DEFAULT_MAX_BYTES)} limit. Use bash: sed -n '${startLineDisplay}p' ${path} | head -c ${DEFAULT_MAX_BYTES}]`;
|
|
215
|
+
details = { truncation };
|
|
216
|
+
} else if (truncation.truncated) {
|
|
217
|
+
// Truncation occurred. Build an actionable continuation notice.
|
|
218
|
+
const endLineDisplay = startLineDisplay + truncation.outputLines - 1;
|
|
219
|
+
const nextOffset = endLineDisplay + 1;
|
|
220
|
+
outputText = truncation.content;
|
|
221
|
+
if (truncation.truncatedBy === "lines") {
|
|
222
|
+
outputText += `\n\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue.]`;
|
|
223
|
+
} else {
|
|
224
|
+
outputText += `\n\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue.]`;
|
|
225
|
+
}
|
|
226
|
+
details = { truncation };
|
|
227
|
+
} else if (userLimitedLines !== undefined && startLine + userLimitedLines < allLines.length) {
|
|
228
|
+
// User-specified limit stopped early, but the file still has more content.
|
|
229
|
+
const remaining = allLines.length - (startLine + userLimitedLines);
|
|
230
|
+
const nextOffset = startLine + userLimitedLines + 1;
|
|
231
|
+
outputText = `${truncation.content}\n\n[${remaining} more lines in file. Use offset=${nextOffset} to continue.]`;
|
|
232
|
+
} else {
|
|
233
|
+
// No truncation and no remaining user-limited content.
|
|
234
|
+
outputText = truncation.content;
|
|
235
|
+
}
|
|
236
|
+
content = [{ type: "text", text: outputText }];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (aborted) return;
|
|
240
|
+
signal?.removeEventListener("abort", onAbort);
|
|
241
|
+
resolve({ content, details });
|
|
242
|
+
} catch (error: any) {
|
|
243
|
+
signal?.removeEventListener("abort", onAbort);
|
|
244
|
+
if (!aborted) reject(error);
|
|
245
|
+
}
|
|
246
|
+
})();
|
|
247
|
+
},
|
|
248
|
+
);
|
|
249
|
+
},
|
|
250
|
+
renderCall(args, theme, context) {
|
|
251
|
+
const text = (context.lastComponent as Text | undefined) ?? new Text("", 0, 0);
|
|
252
|
+
text.setText(formatReadCall(args, theme));
|
|
253
|
+
return text;
|
|
254
|
+
},
|
|
255
|
+
renderResult(result, options, theme, context) {
|
|
256
|
+
const text = (context.lastComponent as Text | undefined) ?? new Text("", 0, 0);
|
|
257
|
+
text.setText(formatReadResult(context.args, result as any, options, theme, context.showImages));
|
|
258
|
+
return text;
|
|
259
|
+
},
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function createReadTool(cwd: string, options?: ReadToolOptions): AgentTool<typeof readSchema> {
|
|
264
|
+
return wrapToolDefinition(createReadToolDefinition(cwd, options));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Default read tool using process.cwd() for backwards compatibility. */
|
|
268
|
+
export const readToolDefinition = createReadToolDefinition(process.cwd());
|
|
269
|
+
export const readTool = createReadTool(process.cwd());
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as os from "node:os";
|
|
2
|
+
import type { ImageContent, TextContent } from "@lenylvt/pi-ai";
|
|
3
|
+
import { getCapabilities, getImageDimensions, imageFallback } from "@lenylvt/pi-tui";
|
|
4
|
+
import stripAnsi from "strip-ansi";
|
|
5
|
+
import { sanitizeBinaryOutput } from "../../utils/shell.js";
|
|
6
|
+
|
|
7
|
+
export function shortenPath(path: unknown): string {
|
|
8
|
+
if (typeof path !== "string") return "";
|
|
9
|
+
const home = os.homedir();
|
|
10
|
+
if (path.startsWith(home)) {
|
|
11
|
+
return `~${path.slice(home.length)}`;
|
|
12
|
+
}
|
|
13
|
+
return path;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function str(value: unknown): string | null {
|
|
17
|
+
if (typeof value === "string") return value;
|
|
18
|
+
if (value == null) return "";
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function replaceTabs(text: string): string {
|
|
23
|
+
return text.replace(/\t/g, " ");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function normalizeDisplayText(text: string): string {
|
|
27
|
+
return text.replace(/\r/g, "");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function getTextOutput(
|
|
31
|
+
result: { content: Array<{ type: string; text?: string; data?: string; mimeType?: string }> } | undefined,
|
|
32
|
+
showImages: boolean,
|
|
33
|
+
): string {
|
|
34
|
+
if (!result) return "";
|
|
35
|
+
|
|
36
|
+
const textBlocks = result.content.filter((c) => c.type === "text");
|
|
37
|
+
const imageBlocks = result.content.filter((c) => c.type === "image");
|
|
38
|
+
|
|
39
|
+
let output = textBlocks.map((c) => sanitizeBinaryOutput(stripAnsi(c.text || "")).replace(/\r/g, "")).join("\n");
|
|
40
|
+
|
|
41
|
+
const caps = getCapabilities();
|
|
42
|
+
if (imageBlocks.length > 0 && (!caps.images || !showImages)) {
|
|
43
|
+
const imageIndicators = imageBlocks
|
|
44
|
+
.map((img) => {
|
|
45
|
+
const mimeType = img.mimeType ?? "image/unknown";
|
|
46
|
+
const dims =
|
|
47
|
+
img.data && img.mimeType ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;
|
|
48
|
+
return imageFallback(mimeType, dims);
|
|
49
|
+
})
|
|
50
|
+
.join("\n");
|
|
51
|
+
output = output ? `${output}\n${imageIndicators}` : imageIndicators;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return output;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type ToolRenderResultLike<TDetails> = {
|
|
58
|
+
content: (TextContent | ImageContent)[];
|
|
59
|
+
details: TDetails;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export function invalidArgText(theme: { fg: (name: any, text: string) => string }): string {
|
|
63
|
+
return theme.fg("error", "[invalid arg]");
|
|
64
|
+
}
|