@dreb/coding-agent 1.16.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 +3316 -0
- package/README.md +657 -0
- package/agents/code-reviewer.md +55 -0
- package/agents/completeness-checker.md +71 -0
- package/agents/error-auditor.md +65 -0
- package/agents/explore.md +13 -0
- package/agents/feature-dev.md +23 -0
- package/agents/independent-assessor.md +61 -0
- package/agents/sandbox.md +14 -0
- package/agents/simplifier.md +69 -0
- package/agents/test-reviewer.md +63 -0
- package/dist/bun/cli.d.ts +3 -0
- package/dist/bun/cli.d.ts.map +1 -0
- package/dist/bun/cli.js +7 -0
- package/dist/bun/cli.js.map +1 -0
- package/dist/bun/register-bedrock.d.ts +2 -0
- package/dist/bun/register-bedrock.d.ts.map +1 -0
- package/dist/bun/register-bedrock.js +4 -0
- package/dist/bun/register-bedrock.js.map +1 -0
- package/dist/cli/args.d.ts +50 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +310 -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 +76 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +234 -0
- package/dist/config.js.map +1 -0
- package/dist/core/agent-session.d.ts +658 -0
- package/dist/core/agent-session.d.ts.map +1 -0
- package/dist/core/agent-session.js +2898 -0
- package/dist/core/agent-session.js.map +1 -0
- package/dist/core/auth-storage.d.ts +130 -0
- package/dist/core/auth-storage.d.ts.map +1 -0
- package/dist/core/auth-storage.js +421 -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/buddy/buddy-controller.d.ts +139 -0
- package/dist/core/buddy/buddy-controller.d.ts.map +1 -0
- package/dist/core/buddy/buddy-controller.js +428 -0
- package/dist/core/buddy/buddy-controller.js.map +1 -0
- package/dist/core/buddy/buddy-manager.d.ts +68 -0
- package/dist/core/buddy/buddy-manager.d.ts.map +1 -0
- package/dist/core/buddy/buddy-manager.js +399 -0
- package/dist/core/buddy/buddy-manager.js.map +1 -0
- package/dist/core/buddy/buddy-prng.d.ts +28 -0
- package/dist/core/buddy/buddy-prng.d.ts.map +1 -0
- package/dist/core/buddy/buddy-prng.js +65 -0
- package/dist/core/buddy/buddy-prng.js.map +1 -0
- package/dist/core/buddy/buddy-species.d.ts +37 -0
- package/dist/core/buddy/buddy-species.d.ts.map +1 -0
- package/dist/core/buddy/buddy-species.js +287 -0
- package/dist/core/buddy/buddy-species.js.map +1 -0
- package/dist/core/buddy/buddy-types.d.ts +58 -0
- package/dist/core/buddy/buddy-types.d.ts.map +1 -0
- package/dist/core/buddy/buddy-types.js +46 -0
- package/dist/core/buddy/buddy-types.js.map +1 -0
- package/dist/core/buddy/index.d.ts +7 -0
- package/dist/core/buddy/index.d.ts.map +1 -0
- package/dist/core/buddy/index.js +6 -0
- package/dist/core/buddy/index.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts +86 -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 +612 -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 +147 -0
- package/dist/core/extensions/runner.d.ts.map +1 -0
- package/dist/core/extensions/runner.js +696 -0
- package/dist/core/extensions/runner.js.map +1 -0
- package/dist/core/extensions/types.d.ts +1072 -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/forbidden-commands.d.ts +31 -0
- package/dist/core/forbidden-commands.d.ts.map +1 -0
- package/dist/core/forbidden-commands.js +184 -0
- package/dist/core/forbidden-commands.js.map +1 -0
- package/dist/core/git-root.d.ts +6 -0
- package/dist/core/git-root.d.ts.map +1 -0
- package/dist/core/git-root.js +32 -0
- package/dist/core/git-root.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 +280 -0
- package/dist/core/keybindings.d.ts.map +1 -0
- package/dist/core/keybindings.js +245 -0
- package/dist/core/keybindings.js.map +1 -0
- package/dist/core/memory-prompt.d.ts +10 -0
- package/dist/core/memory-prompt.d.ts.map +1 -0
- package/dist/core/memory-prompt.js +95 -0
- package/dist/core/memory-prompt.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 +114 -0
- package/dist/core/model-registry.d.ts.map +1 -0
- package/dist/core/model-registry.js +563 -0
- package/dist/core/model-registry.js.map +1 -0
- package/dist/core/model-resolver.d.ts +116 -0
- package/dist/core/model-resolver.d.ts.map +1 -0
- package/dist/core/model-resolver.js +465 -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 +1767 -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 +251 -0
- package/dist/core/prompt-templates.js.map +1 -0
- package/dist/core/resolve-config-value.d.ts +17 -0
- package/dist/core/resolve-config-value.d.ts.map +1 -0
- package/dist/core/resolve-config-value.js +94 -0
- package/dist/core/resolve-config-value.js.map +1 -0
- package/dist/core/resource-loader.d.ts +205 -0
- package/dist/core/resource-loader.d.ts.map +1 -0
- package/dist/core/resource-loader.js +866 -0
- package/dist/core/resource-loader.js.map +1 -0
- package/dist/core/sdk.d.ts +92 -0
- package/dist/core/sdk.d.ts.map +1 -0
- package/dist/core/sdk.js +258 -0
- package/dist/core/sdk.js.map +1 -0
- package/dist/core/search/chunker.d.ts +21 -0
- package/dist/core/search/chunker.d.ts.map +1 -0
- package/dist/core/search/chunker.js +51 -0
- package/dist/core/search/chunker.js.map +1 -0
- package/dist/core/search/db.d.ts +89 -0
- package/dist/core/search/db.d.ts.map +1 -0
- package/dist/core/search/db.js +406 -0
- package/dist/core/search/db.js.map +1 -0
- package/dist/core/search/embedder.d.ts +51 -0
- package/dist/core/search/embedder.d.ts.map +1 -0
- package/dist/core/search/embedder.js +143 -0
- package/dist/core/search/embedder.js.map +1 -0
- package/dist/core/search/index-manager.d.ts +55 -0
- package/dist/core/search/index-manager.d.ts.map +1 -0
- package/dist/core/search/index-manager.js +311 -0
- package/dist/core/search/index-manager.js.map +1 -0
- package/dist/core/search/metrics/bm25.d.ts +10 -0
- package/dist/core/search/metrics/bm25.d.ts.map +1 -0
- package/dist/core/search/metrics/bm25.js +32 -0
- package/dist/core/search/metrics/bm25.js.map +1 -0
- package/dist/core/search/metrics/git-recency.d.ts +14 -0
- package/dist/core/search/metrics/git-recency.d.ts.map +1 -0
- package/dist/core/search/metrics/git-recency.js +123 -0
- package/dist/core/search/metrics/git-recency.js.map +1 -0
- package/dist/core/search/metrics/import-graph.d.ts +15 -0
- package/dist/core/search/metrics/import-graph.d.ts.map +1 -0
- package/dist/core/search/metrics/import-graph.js +115 -0
- package/dist/core/search/metrics/import-graph.js.map +1 -0
- package/dist/core/search/metrics/path-match.d.ts +13 -0
- package/dist/core/search/metrics/path-match.d.ts.map +1 -0
- package/dist/core/search/metrics/path-match.js +54 -0
- package/dist/core/search/metrics/path-match.js.map +1 -0
- package/dist/core/search/metrics/symbol-match.d.ts +12 -0
- package/dist/core/search/metrics/symbol-match.d.ts.map +1 -0
- package/dist/core/search/metrics/symbol-match.js +62 -0
- package/dist/core/search/metrics/symbol-match.js.map +1 -0
- package/dist/core/search/metrics/tokenize.d.ts +12 -0
- package/dist/core/search/metrics/tokenize.d.ts.map +1 -0
- package/dist/core/search/metrics/tokenize.js +29 -0
- package/dist/core/search/metrics/tokenize.js.map +1 -0
- package/dist/core/search/poem.d.ts +38 -0
- package/dist/core/search/poem.d.ts.map +1 -0
- package/dist/core/search/poem.js +214 -0
- package/dist/core/search/poem.js.map +1 -0
- package/dist/core/search/query-classifier.d.ts +17 -0
- package/dist/core/search/query-classifier.d.ts.map +1 -0
- package/dist/core/search/query-classifier.js +54 -0
- package/dist/core/search/query-classifier.js.map +1 -0
- package/dist/core/search/scanner.d.ts +30 -0
- package/dist/core/search/scanner.d.ts.map +1 -0
- package/dist/core/search/scanner.js +335 -0
- package/dist/core/search/scanner.js.map +1 -0
- package/dist/core/search/search.d.ts +42 -0
- package/dist/core/search/search.d.ts.map +1 -0
- package/dist/core/search/search.js +337 -0
- package/dist/core/search/search.js.map +1 -0
- package/dist/core/search/text-chunker.d.ts +15 -0
- package/dist/core/search/text-chunker.d.ts.map +1 -0
- package/dist/core/search/text-chunker.js +580 -0
- package/dist/core/search/text-chunker.js.map +1 -0
- package/dist/core/search/tree-sitter-chunker.d.ts +25 -0
- package/dist/core/search/tree-sitter-chunker.d.ts.map +1 -0
- package/dist/core/search/tree-sitter-chunker.js +357 -0
- package/dist/core/search/tree-sitter-chunker.js.map +1 -0
- package/dist/core/search/types.d.ts +96 -0
- package/dist/core/search/types.d.ts.map +1 -0
- package/dist/core/search/types.js +6 -0
- package/dist/core/search/types.js.map +1 -0
- package/dist/core/search/vector-store.d.ts +43 -0
- package/dist/core/search/vector-store.d.ts.map +1 -0
- package/dist/core/search/vector-store.js +73 -0
- package/dist/core/search/vector-store.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 +239 -0
- package/dist/core/settings-manager.d.ts.map +1 -0
- package/dist/core/settings-manager.js +705 -0
- package/dist/core/settings-manager.js.map +1 -0
- package/dist/core/skills.d.ts +67 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +428 -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 +23 -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 +33 -0
- package/dist/core/system-prompt.d.ts.map +1 -0
- package/dist/core/system-prompt.js +184 -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 +63 -0
- package/dist/core/tools/edit-diff.d.ts.map +1 -0
- package/dist/core/tools/edit-diff.js +244 -0
- package/dist/core/tools/edit-diff.js.map +1 -0
- package/dist/core/tools/edit.d.ts +51 -0
- package/dist/core/tools/edit.d.ts.map +1 -0
- package/dist/core/tools/edit.js +218 -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 +241 -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 +176 -0
- package/dist/core/tools/index.d.ts.map +1 -0
- package/dist/core/tools/index.js +137 -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/search.d.ts +29 -0
- package/dist/core/tools/search.d.ts.map +1 -0
- package/dist/core/tools/search.js +187 -0
- package/dist/core/tools/search.js.map +1 -0
- package/dist/core/tools/skill.d.ts +26 -0
- package/dist/core/tools/skill.d.ts.map +1 -0
- package/dist/core/tools/skill.js +127 -0
- package/dist/core/tools/skill.js.map +1 -0
- package/dist/core/tools/subagent.d.ts +147 -0
- package/dist/core/tools/subagent.d.ts.map +1 -0
- package/dist/core/tools/subagent.js +950 -0
- package/dist/core/tools/subagent.js.map +1 -0
- package/dist/core/tools/tasks.d.ts +32 -0
- package/dist/core/tools/tasks.d.ts.map +1 -0
- package/dist/core/tools/tasks.js +110 -0
- package/dist/core/tools/tasks.js.map +1 -0
- package/dist/core/tools/tmp-read.d.ts +11 -0
- package/dist/core/tools/tmp-read.d.ts.map +1 -0
- package/dist/core/tools/tmp-read.js +63 -0
- package/dist/core/tools/tmp-read.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/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/web.d.ts +42 -0
- package/dist/core/tools/web.d.ts.map +1 -0
- package/dist/core/tools/web.js +518 -0
- package/dist/core/tools/web.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/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 +789 -0
- package/dist/main.js.map +1 -0
- package/dist/migrations.d.ts +33 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +261 -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 +16 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/assistant-message.js +96 -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/buddy-component.d.ts +58 -0
- package/dist/modes/interactive/components/buddy-component.d.ts.map +1 -0
- package/dist/modes/interactive/components/buddy-component.js +351 -0
- package/dist/modes/interactive/components/buddy-component.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/daxnuts.d.ts +23 -0
- package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -0
- package/dist/modes/interactive/components/daxnuts.js +140 -0
- package/dist/modes/interactive/components/daxnuts.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 +33 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -0
- package/dist/modes/interactive/components/index.js +34 -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/tasks-panel.d.ts +20 -0
- package/dist/modes/interactive/components/tasks-panel.d.ts.map +1 -0
- package/dist/modes/interactive/components/tasks-panel.js +66 -0
- package/dist/modes/interactive/components/tasks-panel.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 +59 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-execution.js +279 -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 +338 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-mode.js +4167 -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/index.d.ts +10 -0
- package/dist/modes/rpc/index.d.ts.map +1 -0
- package/dist/modes/rpc/index.js +8 -0
- package/dist/modes/rpc/index.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 +237 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-client.js +448 -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 +592 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -0
- package/dist/modes/rpc/rpc-types.d.ts +471 -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/dist/utils/xml.d.ts +2 -0
- package/dist/utils/xml.d.ts.map +1 -0
- package/dist/utils/xml.js +9 -0
- package/dist/utils/xml.js.map +1 -0
- package/docs/buddy.md +111 -0
- package/docs/compaction.md +392 -0
- package/docs/custom-provider.md +599 -0
- package/docs/development.md +108 -0
- package/docs/extensions.md +2130 -0
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/json.md +112 -0
- package/docs/keybindings.md +174 -0
- package/docs/mach6.md +150 -0
- package/docs/models.md +335 -0
- package/docs/packages.md +197 -0
- package/docs/prompt-templates.md +67 -0
- package/docs/providers.md +194 -0
- package/docs/rpc.md +1426 -0
- package/docs/sdk.md +969 -0
- package/docs/session.md +412 -0
- package/docs/settings.md +247 -0
- package/docs/shell-aliases.md +55 -0
- package/docs/skills.md +296 -0
- package/docs/terminal-setup.md +104 -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 +61 -0
- package/examples/README.md +25 -0
- package/examples/extensions/README.md +205 -0
- package/examples/extensions/antigravity-image-gen.ts +418 -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 +114 -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-lock.json +24 -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/custom-provider-qwen-cli/index.ts +345 -0
- package/examples/extensions/custom-provider-qwen-cli/package.json +16 -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 +73 -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 +150 -0
- package/examples/extensions/hello.ts +25 -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 +168 -0
- package/examples/extensions/preset.ts +403 -0
- package/examples/extensions/protected-paths.ts +30 -0
- package/examples/extensions/provider-payload.ts +14 -0
- package/examples/extensions/qna.ts +119 -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 +317 -0
- package/examples/extensions/sandbox/package-lock.json +92 -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 +195 -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 +40 -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-lock.json +31 -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 +53 -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 +87 -0
- package/examples/sdk/README.md +144 -0
- package/package.json +123 -0
- package/skills/mach6-implement/SKILL.md +170 -0
- package/skills/mach6-issue/SKILL.md +129 -0
- package/skills/mach6-plan/SKILL.md +123 -0
- package/skills/mach6-publish/SKILL.md +188 -0
- package/skills/mach6-push/SKILL.md +101 -0
- package/skills/mach6-review/SKILL.md +192 -0
- package/skills/telegram-send/SKILL.md +46 -0
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { Text } from "@dreb/tui";
|
|
5
|
+
import { Type } from "@sinclair/typebox";
|
|
6
|
+
import { CONFIG_DIR_NAME } from "../../config.js";
|
|
7
|
+
import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
8
|
+
import { getTextOutput, invalidArgText, str } from "./render-utils.js";
|
|
9
|
+
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
10
|
+
import { DEFAULT_MAX_BYTES, formatSize, truncateHead } from "./truncate.js";
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Shared: HTTP fetching and HTML extraction
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
const FETCH_TIMEOUT_MS = 30_000;
|
|
15
|
+
const MAX_CONTENT_LENGTH = 100_000;
|
|
16
|
+
const CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes
|
|
17
|
+
const fetchCache = new Map();
|
|
18
|
+
function stripHtmlToText(html) {
|
|
19
|
+
let text = html;
|
|
20
|
+
// Remove script/style/nav/footer blocks entirely
|
|
21
|
+
text = text.replace(/<(script|style|nav|footer|header|aside|iframe|noscript)\b[^>]*>[\s\S]*?<\/\1>/gi, "");
|
|
22
|
+
// Convert block elements to newlines
|
|
23
|
+
text = text.replace(/<\/(p|div|li|tr|h[1-6]|blockquote|pre|section|article)>/gi, "\n");
|
|
24
|
+
text = text.replace(/<(br|hr)\s*\/?>/gi, "\n");
|
|
25
|
+
// Convert links to text with URL
|
|
26
|
+
text = text.replace(/<a\b[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/gi, "$2 ($1)");
|
|
27
|
+
// Convert headings to markdown-style
|
|
28
|
+
text = text.replace(/<h([1-6])\b[^>]*>([\s\S]*?)<\/h\1>/gi, (_match, level, content) => {
|
|
29
|
+
return `\n${"#".repeat(Number(level))} ${content.trim()}\n`;
|
|
30
|
+
});
|
|
31
|
+
// Convert list items
|
|
32
|
+
text = text.replace(/<li\b[^>]*>/gi, "\n- ");
|
|
33
|
+
// Strip all remaining tags
|
|
34
|
+
text = text.replace(/<[^>]+>/g, "");
|
|
35
|
+
// Decode common HTML entities
|
|
36
|
+
text = text.replace(/&/g, "&");
|
|
37
|
+
text = text.replace(/</g, "<");
|
|
38
|
+
text = text.replace(/>/g, ">");
|
|
39
|
+
text = text.replace(/"/g, '"');
|
|
40
|
+
text = text.replace(/'/g, "'");
|
|
41
|
+
text = text.replace(/ /g, " ");
|
|
42
|
+
// Collapse whitespace
|
|
43
|
+
text = text.replace(/[ \t]+/g, " ");
|
|
44
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
45
|
+
return text.trim();
|
|
46
|
+
}
|
|
47
|
+
function extractTitle(html) {
|
|
48
|
+
const match = html.match(/<title\b[^>]*>([\s\S]*?)<\/title>/i);
|
|
49
|
+
return match ? match[1].trim().replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") : "";
|
|
50
|
+
}
|
|
51
|
+
const FETCH_HEADERS = {
|
|
52
|
+
"User-Agent": "dreb/1.0 (web fetch tool)",
|
|
53
|
+
Accept: "text/html,application/xhtml+xml,text/plain,application/pdf",
|
|
54
|
+
};
|
|
55
|
+
// Block fetches to private/internal networks to prevent SSRF
|
|
56
|
+
const BLOCKED_HOSTNAMES = new Set(["localhost", "127.0.0.1", "[::1]", "0.0.0.0"]);
|
|
57
|
+
function isPrivateHost(hostname) {
|
|
58
|
+
if (BLOCKED_HOSTNAMES.has(hostname))
|
|
59
|
+
return true;
|
|
60
|
+
// IPv4 private ranges
|
|
61
|
+
const ipv4Match = hostname.match(/^(\d+)\.(\d+)\.\d+\.\d+$/);
|
|
62
|
+
if (ipv4Match) {
|
|
63
|
+
const [, first, second] = ipv4Match.map(Number);
|
|
64
|
+
if (first === 10)
|
|
65
|
+
return true; // 10.0.0.0/8
|
|
66
|
+
if (first === 172 && second >= 16 && second <= 31)
|
|
67
|
+
return true; // 172.16.0.0/12
|
|
68
|
+
if (first === 192 && second === 168)
|
|
69
|
+
return true; // 192.168.0.0/16
|
|
70
|
+
if (first === 169 && second === 254)
|
|
71
|
+
return true; // link-local 169.254.0.0/16
|
|
72
|
+
}
|
|
73
|
+
// IPv6 loopback, link-local, and ULA (fc00::/7)
|
|
74
|
+
if (hostname.startsWith("[")) {
|
|
75
|
+
const lh = hostname.toLowerCase();
|
|
76
|
+
if (lh.includes("::1") || lh.startsWith("[fe80:") || lh.startsWith("[fc") || lh.startsWith("[fd"))
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
function buildResponse(response) {
|
|
82
|
+
const ct = response.headers.get("content-type") || "";
|
|
83
|
+
if (ct.includes("application/pdf")) {
|
|
84
|
+
return response.arrayBuffer().then((buf) => ({ body: Buffer.from(buf), contentType: ct }));
|
|
85
|
+
}
|
|
86
|
+
return response.text().then((text) => ({ body: text, contentType: ct }));
|
|
87
|
+
}
|
|
88
|
+
async function httpFetch(url) {
|
|
89
|
+
const originalHost = new URL(url).hostname;
|
|
90
|
+
if (isPrivateHost(originalHost)) {
|
|
91
|
+
throw new Error(`Blocked: ${originalHost} is a private/internal address`);
|
|
92
|
+
}
|
|
93
|
+
// Manual redirect loop to enforce same-host on every hop
|
|
94
|
+
let currentUrl = url;
|
|
95
|
+
const maxRedirects = 10;
|
|
96
|
+
for (let i = 0; i <= maxRedirects; i++) {
|
|
97
|
+
const response = await fetch(currentUrl, {
|
|
98
|
+
method: "GET",
|
|
99
|
+
headers: FETCH_HEADERS,
|
|
100
|
+
redirect: "manual",
|
|
101
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
102
|
+
});
|
|
103
|
+
if (response.status >= 300 && response.status < 400) {
|
|
104
|
+
const location = response.headers.get("location");
|
|
105
|
+
if (!location) {
|
|
106
|
+
throw new Error(`HTTP ${response.status}: redirect with no Location header`);
|
|
107
|
+
}
|
|
108
|
+
const redirectUrl = new URL(location, currentUrl);
|
|
109
|
+
// Block private IPs before revealing them in cross-host messages
|
|
110
|
+
if (isPrivateHost(redirectUrl.hostname)) {
|
|
111
|
+
throw new Error(`Blocked: redirect to private/internal address`);
|
|
112
|
+
}
|
|
113
|
+
if (redirectUrl.hostname !== originalHost) {
|
|
114
|
+
return {
|
|
115
|
+
body: `Cross-host redirect detected.\nOriginal: ${url}\nRedirects to: ${redirectUrl.href}\n\nThe redirect target is on a different host. Fetch the new URL directly if you want to follow it.`,
|
|
116
|
+
contentType: "text/plain",
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
currentUrl = redirectUrl.href;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
const errorBody = await response.text();
|
|
124
|
+
throw new Error(`HTTP ${response.status}: ${errorBody.slice(0, 200)}`);
|
|
125
|
+
}
|
|
126
|
+
return buildResponse(response);
|
|
127
|
+
}
|
|
128
|
+
throw new Error(`Too many redirects (${maxRedirects})`);
|
|
129
|
+
}
|
|
130
|
+
// -- PDF text extraction (basic) ---------------------------------------------
|
|
131
|
+
function extractPdfText(buffer) {
|
|
132
|
+
// Minimal PDF text extraction — only works on uncompressed PDFs with literal
|
|
133
|
+
// string objects in BT/ET text blocks. Most production PDFs use FlateDecode
|
|
134
|
+
// compression and will fall through to the failure message.
|
|
135
|
+
// latin1 preserves raw byte values 0-255 as code points for safe regex matching.
|
|
136
|
+
const raw = buffer.toString("latin1");
|
|
137
|
+
const textChunks = [];
|
|
138
|
+
const btEtRegex = /BT\s([\s\S]*?)ET/g;
|
|
139
|
+
for (const match of raw.matchAll(btEtRegex)) {
|
|
140
|
+
const block = match[1];
|
|
141
|
+
const strRegex = /\(([^)]*)\)/g;
|
|
142
|
+
for (const strMatch of block.matchAll(strRegex)) {
|
|
143
|
+
const decoded = strMatch[1]
|
|
144
|
+
.replace(/\\n/g, "\n")
|
|
145
|
+
.replace(/\\r/g, "\r")
|
|
146
|
+
.replace(/\\t/g, "\t")
|
|
147
|
+
.replace(/\\\(/g, "(")
|
|
148
|
+
.replace(/\\\)/g, ")")
|
|
149
|
+
.replace(/\\\\/g, "\\");
|
|
150
|
+
if (decoded.trim()) {
|
|
151
|
+
textChunks.push(decoded);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (textChunks.length === 0) {
|
|
156
|
+
return "[PDF text extraction failed — the PDF may use embedded fonts or image-based content that requires OCR]";
|
|
157
|
+
}
|
|
158
|
+
return textChunks.join(" ").replace(/\s+/g, " ").trim();
|
|
159
|
+
}
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
// web_search tool
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
const webSearchSchema = Type.Object({
|
|
164
|
+
query: Type.String({ description: "The search query" }),
|
|
165
|
+
});
|
|
166
|
+
async function searchDuckDuckGo(query) {
|
|
167
|
+
const encodedQuery = encodeURIComponent(query);
|
|
168
|
+
const response = await fetch(`https://html.duckduckgo.com/html/?q=${encodedQuery}`, {
|
|
169
|
+
method: "GET",
|
|
170
|
+
headers: {
|
|
171
|
+
"User-Agent": "dreb/1.0 (web search tool)",
|
|
172
|
+
Accept: "text/html",
|
|
173
|
+
},
|
|
174
|
+
redirect: "follow",
|
|
175
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
176
|
+
});
|
|
177
|
+
if (!response.ok) {
|
|
178
|
+
throw new Error(`DuckDuckGo search failed: HTTP ${response.status}`);
|
|
179
|
+
}
|
|
180
|
+
const html = await response.text();
|
|
181
|
+
const results = [];
|
|
182
|
+
// Parse DuckDuckGo HTML results — split on result block class
|
|
183
|
+
const resultBlocks = html.split(/class="result results_links/);
|
|
184
|
+
for (const block of resultBlocks.slice(1, 11)) {
|
|
185
|
+
const titleMatch = block.match(/class="result__a"[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/);
|
|
186
|
+
const snippetMatch = block.match(/class="result__snippet"[^>]*>([\s\S]*?)<\/(?:a|td|div)/);
|
|
187
|
+
if (titleMatch) {
|
|
188
|
+
let url = titleMatch[1];
|
|
189
|
+
// DDG wraps URLs in a redirect — extract the actual URL
|
|
190
|
+
const uddgMatch = url.match(/uddg=([^&]*)/);
|
|
191
|
+
if (uddgMatch) {
|
|
192
|
+
url = decodeURIComponent(uddgMatch[1]);
|
|
193
|
+
}
|
|
194
|
+
const title = titleMatch[2].replace(/<[^>]+>/g, "").trim();
|
|
195
|
+
const snippet = snippetMatch ? snippetMatch[1].replace(/<[^>]+>/g, "").trim() : "";
|
|
196
|
+
if (title && url) {
|
|
197
|
+
results.push({ title, url, snippet });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (results.length === 0 && html.length > 1000) {
|
|
202
|
+
// Got a substantial response but parsed 0 results — DDG HTML structure may have changed
|
|
203
|
+
console.error("Warning: DDG returned HTML but 0 results were parsed. The HTML structure may have changed.");
|
|
204
|
+
}
|
|
205
|
+
return results;
|
|
206
|
+
}
|
|
207
|
+
async function searchSearXNG(query, baseUrl) {
|
|
208
|
+
const encodedQuery = encodeURIComponent(query);
|
|
209
|
+
const response = await fetch(`${baseUrl}/search?q=${encodedQuery}&format=json`, {
|
|
210
|
+
method: "GET",
|
|
211
|
+
headers: { Accept: "application/json" },
|
|
212
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
213
|
+
});
|
|
214
|
+
if (!response.ok) {
|
|
215
|
+
throw new Error(`SearXNG search failed: HTTP ${response.status}`);
|
|
216
|
+
}
|
|
217
|
+
const data = (await response.json());
|
|
218
|
+
return (data.results || []).slice(0, 10).map((r) => ({
|
|
219
|
+
title: r.title,
|
|
220
|
+
url: r.url,
|
|
221
|
+
snippet: r.content || "",
|
|
222
|
+
}));
|
|
223
|
+
}
|
|
224
|
+
async function searchBrave(query, apiKey) {
|
|
225
|
+
const encodedQuery = encodeURIComponent(query);
|
|
226
|
+
const response = await fetch(`https://api.search.brave.com/res/v1/web/search?q=${encodedQuery}`, {
|
|
227
|
+
method: "GET",
|
|
228
|
+
headers: {
|
|
229
|
+
Accept: "application/json",
|
|
230
|
+
"X-Subscription-Token": apiKey,
|
|
231
|
+
},
|
|
232
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
233
|
+
});
|
|
234
|
+
if (!response.ok) {
|
|
235
|
+
throw new Error(`Brave search failed: HTTP ${response.status}`);
|
|
236
|
+
}
|
|
237
|
+
const data = (await response.json());
|
|
238
|
+
return (data.web?.results || []).slice(0, 10).map((r) => ({
|
|
239
|
+
title: r.title,
|
|
240
|
+
url: r.url,
|
|
241
|
+
snippet: r.description || "",
|
|
242
|
+
}));
|
|
243
|
+
}
|
|
244
|
+
const VALID_BACKENDS = ["ddg", "searxng", "brave"];
|
|
245
|
+
function loadDrebConfig() {
|
|
246
|
+
// Config file precedence: project-local > home directory. First valid file wins.
|
|
247
|
+
const candidates = [
|
|
248
|
+
join(process.cwd(), CONFIG_DIR_NAME, "config.json"),
|
|
249
|
+
join(process.cwd(), ".dreb", "config.json"),
|
|
250
|
+
join(homedir(), CONFIG_DIR_NAME, "config.json"),
|
|
251
|
+
join(homedir(), ".dreb", "config.json"),
|
|
252
|
+
];
|
|
253
|
+
for (const configPath of candidates) {
|
|
254
|
+
if (existsSync(configPath)) {
|
|
255
|
+
try {
|
|
256
|
+
return JSON.parse(readFileSync(configPath, "utf-8"));
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
260
|
+
console.error(`Warning: failed to parse config at ${configPath}: ${msg}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return {};
|
|
265
|
+
}
|
|
266
|
+
function getSearchConfig() {
|
|
267
|
+
const fileConfig = loadDrebConfig();
|
|
268
|
+
// Environment variables override config file
|
|
269
|
+
const rawBackend = process.env.DREB_SEARCH_BACKEND || fileConfig.search?.backend;
|
|
270
|
+
let backend = "ddg";
|
|
271
|
+
if (rawBackend) {
|
|
272
|
+
if (VALID_BACKENDS.includes(rawBackend)) {
|
|
273
|
+
backend = rawBackend;
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
console.error(`Warning: unrecognized search backend "${rawBackend}", falling back to ddg. Valid: ${VALID_BACKENDS.join(", ")}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
backend,
|
|
281
|
+
searxngUrl: process.env.DREB_SEARXNG_URL || fileConfig.search?.searxng_url || "http://localhost:8888",
|
|
282
|
+
braveApiKey: process.env.DREB_BRAVE_API_KEY || fileConfig.search?.brave_api_key,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
async function executeSearch(query) {
|
|
286
|
+
const config = getSearchConfig();
|
|
287
|
+
switch (config.backend) {
|
|
288
|
+
case "searxng":
|
|
289
|
+
return searchSearXNG(query, config.searxngUrl);
|
|
290
|
+
case "brave":
|
|
291
|
+
if (!config.braveApiKey)
|
|
292
|
+
throw new Error("DREB_BRAVE_API_KEY not set");
|
|
293
|
+
return searchBrave(query, config.braveApiKey);
|
|
294
|
+
default:
|
|
295
|
+
return searchDuckDuckGo(query);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function formatSearchCall(args, theme) {
|
|
299
|
+
const query = str(args?.query);
|
|
300
|
+
const invalidArg = invalidArgText(theme);
|
|
301
|
+
return (theme.fg("toolTitle", theme.bold("web_search")) +
|
|
302
|
+
" " +
|
|
303
|
+
(query === null ? invalidArg : theme.fg("accent", `"${query}"`)));
|
|
304
|
+
}
|
|
305
|
+
function formatSearchResult(result, options, theme, showImages) {
|
|
306
|
+
const output = getTextOutput(result, showImages).trim();
|
|
307
|
+
let text = "";
|
|
308
|
+
if (output) {
|
|
309
|
+
const lines = output.split("\n");
|
|
310
|
+
const maxLines = options.expanded ? lines.length : 15;
|
|
311
|
+
const displayLines = lines.slice(0, maxLines);
|
|
312
|
+
const remaining = lines.length - maxLines;
|
|
313
|
+
text += `\n${displayLines.map((line) => theme.fg("toolOutput", line)).join("\n")}`;
|
|
314
|
+
if (remaining > 0) {
|
|
315
|
+
text += `${theme.fg("muted", `\n... (${remaining} more lines,`)} ${keyHint("app.tools.expand", "to expand")})`;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return text;
|
|
319
|
+
}
|
|
320
|
+
export function createWebSearchToolDefinition(_cwd) {
|
|
321
|
+
return {
|
|
322
|
+
name: "web_search",
|
|
323
|
+
label: "web_search",
|
|
324
|
+
description: "Search the web. Returns titles, URLs, and snippets. Configure backend via DREB_SEARCH_BACKEND env var (ddg, searxng, brave).",
|
|
325
|
+
promptSnippet: "Search the web for information",
|
|
326
|
+
parameters: webSearchSchema,
|
|
327
|
+
async execute(_toolCallId, { query }) {
|
|
328
|
+
let results;
|
|
329
|
+
try {
|
|
330
|
+
results = await executeSearch(query);
|
|
331
|
+
}
|
|
332
|
+
catch (error) {
|
|
333
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
334
|
+
return {
|
|
335
|
+
content: [{ type: "text", text: `Search failed for "${query}": ${msg}` }],
|
|
336
|
+
details: undefined,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
if (results.length === 0) {
|
|
340
|
+
return {
|
|
341
|
+
content: [{ type: "text", text: `No results found for: ${query}` }],
|
|
342
|
+
details: undefined,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
const formatted = results.map((r, i) => `${i + 1}. ${r.title}\n ${r.url}\n ${r.snippet}`).join("\n\n");
|
|
346
|
+
const output = `Search results for: ${query}\n\n${formatted}`;
|
|
347
|
+
return {
|
|
348
|
+
content: [{ type: "text", text: output }],
|
|
349
|
+
details: undefined,
|
|
350
|
+
};
|
|
351
|
+
},
|
|
352
|
+
renderCall(args, theme, context) {
|
|
353
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
354
|
+
text.setText(formatSearchCall(args, theme));
|
|
355
|
+
return text;
|
|
356
|
+
},
|
|
357
|
+
renderResult(result, options, theme, context) {
|
|
358
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
359
|
+
text.setText(formatSearchResult(result, options, theme, context.showImages));
|
|
360
|
+
return text;
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
export function createWebSearchTool(cwd) {
|
|
365
|
+
return wrapToolDefinition(createWebSearchToolDefinition(cwd));
|
|
366
|
+
}
|
|
367
|
+
export const webSearchToolDefinition = createWebSearchToolDefinition(process.cwd());
|
|
368
|
+
export const webSearchTool = createWebSearchTool(process.cwd());
|
|
369
|
+
// ---------------------------------------------------------------------------
|
|
370
|
+
// web_fetch tool
|
|
371
|
+
// ---------------------------------------------------------------------------
|
|
372
|
+
const webFetchSchema = Type.Object({
|
|
373
|
+
url: Type.String({ description: "The URL to fetch" }),
|
|
374
|
+
});
|
|
375
|
+
function formatFetchCall(args, theme) {
|
|
376
|
+
const url = str(args?.url);
|
|
377
|
+
const invalidArg = invalidArgText(theme);
|
|
378
|
+
return `${theme.fg("toolTitle", theme.bold("web_fetch"))} ${url === null ? invalidArg : theme.fg("accent", url || "")}`;
|
|
379
|
+
}
|
|
380
|
+
function formatFetchResult(result, options, theme, showImages) {
|
|
381
|
+
const output = getTextOutput(result, showImages).trim();
|
|
382
|
+
let text = "";
|
|
383
|
+
if (output) {
|
|
384
|
+
const lines = output.split("\n");
|
|
385
|
+
const maxLines = options.expanded ? lines.length : 30;
|
|
386
|
+
const displayLines = lines.slice(0, maxLines);
|
|
387
|
+
const remaining = lines.length - maxLines;
|
|
388
|
+
text += `\n${displayLines.map((line) => theme.fg("toolOutput", line)).join("\n")}`;
|
|
389
|
+
if (remaining > 0) {
|
|
390
|
+
text += `${theme.fg("muted", `\n... (${remaining} more lines,`)} ${keyHint("app.tools.expand", "to expand")})`;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
const details = result.details;
|
|
394
|
+
if (details?.truncatedContent || details?.truncation?.truncated) {
|
|
395
|
+
const warnings = [];
|
|
396
|
+
if (details.truncatedContent)
|
|
397
|
+
warnings.push(`~${Math.round(MAX_CONTENT_LENGTH / 1024)}KB content limit`);
|
|
398
|
+
if (details.truncation?.truncated)
|
|
399
|
+
warnings.push(`${formatSize(DEFAULT_MAX_BYTES)} output limit`);
|
|
400
|
+
text += `\n${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
|
|
401
|
+
}
|
|
402
|
+
return text;
|
|
403
|
+
}
|
|
404
|
+
export function createWebFetchToolDefinition(_cwd) {
|
|
405
|
+
return {
|
|
406
|
+
name: "web_fetch",
|
|
407
|
+
label: "web_fetch",
|
|
408
|
+
description: `Fetch a URL and return its text content. Extracts readable text from HTML pages. Supports PDF text extraction. Content truncated to ~${Math.round(MAX_CONTENT_LENGTH / 1024)}KB. Results cached for 15 minutes.`,
|
|
409
|
+
promptSnippet: "Fetch a URL and extract its text content",
|
|
410
|
+
parameters: webFetchSchema,
|
|
411
|
+
async execute(_toolCallId, { url }) {
|
|
412
|
+
// Validate URL
|
|
413
|
+
let parsed;
|
|
414
|
+
try {
|
|
415
|
+
parsed = new URL(url);
|
|
416
|
+
}
|
|
417
|
+
catch {
|
|
418
|
+
return {
|
|
419
|
+
content: [{ type: "text", text: `Invalid URL: ${url}` }],
|
|
420
|
+
details: undefined,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
if (!parsed.protocol.startsWith("http")) {
|
|
424
|
+
return {
|
|
425
|
+
content: [{ type: "text", text: `Unsupported protocol: ${parsed.protocol}` }],
|
|
426
|
+
details: undefined,
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
// Check cache (15-minute TTL, evict stale entries)
|
|
430
|
+
const cached = fetchCache.get(url);
|
|
431
|
+
if (cached) {
|
|
432
|
+
if (Date.now() - cached.timestamp < CACHE_TTL_MS) {
|
|
433
|
+
const r = cached.content;
|
|
434
|
+
const output = `${r.title}\n${r.url}\nFetched: ${r.fetchedAt} (cached)\n\n${r.content}`;
|
|
435
|
+
return {
|
|
436
|
+
content: [{ type: "text", text: output }],
|
|
437
|
+
details: undefined,
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
fetchCache.delete(url);
|
|
441
|
+
}
|
|
442
|
+
// Fetch (with same-host redirect enforcement)
|
|
443
|
+
let body;
|
|
444
|
+
let contentType;
|
|
445
|
+
try {
|
|
446
|
+
const result = await httpFetch(url);
|
|
447
|
+
body = result.body;
|
|
448
|
+
contentType = result.contentType;
|
|
449
|
+
}
|
|
450
|
+
catch (error) {
|
|
451
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
452
|
+
return {
|
|
453
|
+
content: [{ type: "text", text: `Failed to fetch ${url}: ${msg}` }],
|
|
454
|
+
details: undefined,
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
// Extract content based on content type
|
|
458
|
+
let text;
|
|
459
|
+
let title;
|
|
460
|
+
const details = {};
|
|
461
|
+
const fetchedAt = new Date().toISOString();
|
|
462
|
+
if (contentType.includes("application/pdf")) {
|
|
463
|
+
title = url;
|
|
464
|
+
text = extractPdfText(body);
|
|
465
|
+
}
|
|
466
|
+
else if (contentType.includes("text/html") || contentType.includes("application/xhtml")) {
|
|
467
|
+
const htmlBody = body;
|
|
468
|
+
title = extractTitle(htmlBody) || url;
|
|
469
|
+
text = stripHtmlToText(htmlBody);
|
|
470
|
+
}
|
|
471
|
+
else if (contentType.includes("text/plain") ||
|
|
472
|
+
contentType.includes("application/json") ||
|
|
473
|
+
contentType.includes("text/xml") ||
|
|
474
|
+
contentType.includes("application/xml")) {
|
|
475
|
+
title = url;
|
|
476
|
+
text = body;
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
return {
|
|
480
|
+
content: [{ type: "text", text: `Unsupported content type: ${contentType}` }],
|
|
481
|
+
details: undefined,
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
// Truncate to prevent context overflow (~100K characters)
|
|
485
|
+
if (text.length > MAX_CONTENT_LENGTH) {
|
|
486
|
+
text = `${text.slice(0, MAX_CONTENT_LENGTH)}\n\n[Content truncated at ~${Math.round(MAX_CONTENT_LENGTH / 1024)}KB]`;
|
|
487
|
+
details.truncatedContent = true;
|
|
488
|
+
}
|
|
489
|
+
const fetchResult = { url, title, content: text, fetchedAt };
|
|
490
|
+
fetchCache.set(url, { content: fetchResult, timestamp: Date.now() });
|
|
491
|
+
const output = `${title}\n${url}\nFetched: ${fetchedAt}\n\n${text}`;
|
|
492
|
+
const truncation = truncateHead(output, { maxLines: Number.MAX_SAFE_INTEGER });
|
|
493
|
+
if (truncation.truncated) {
|
|
494
|
+
details.truncation = truncation;
|
|
495
|
+
}
|
|
496
|
+
return {
|
|
497
|
+
content: [{ type: "text", text: truncation.content }],
|
|
498
|
+
details: Object.keys(details).length > 0 ? details : undefined,
|
|
499
|
+
};
|
|
500
|
+
},
|
|
501
|
+
renderCall(args, theme, context) {
|
|
502
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
503
|
+
text.setText(formatFetchCall(args, theme));
|
|
504
|
+
return text;
|
|
505
|
+
},
|
|
506
|
+
renderResult(result, options, theme, context) {
|
|
507
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
508
|
+
text.setText(formatFetchResult(result, options, theme, context.showImages));
|
|
509
|
+
return text;
|
|
510
|
+
},
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
export function createWebFetchTool(cwd) {
|
|
514
|
+
return wrapToolDefinition(createWebFetchToolDefinition(cwd));
|
|
515
|
+
}
|
|
516
|
+
export const webFetchToolDefinition = createWebFetchToolDefinition(process.cwd());
|
|
517
|
+
export const webFetchTool = createWebFetchTool(process.cwd());
|
|
518
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../../src/core/tools/web.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { AgentTool } from \"@dreb/agent-core\";\nimport { Text } from \"@dreb/tui\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { CONFIG_DIR_NAME } from \"../../config.js\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.js\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.js\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.js\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.js\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from \"./truncate.js\";\n\n// ---------------------------------------------------------------------------\n// Shared: HTTP fetching and HTML extraction\n// ---------------------------------------------------------------------------\n\nconst FETCH_TIMEOUT_MS = 30_000;\nconst MAX_CONTENT_LENGTH = 100_000;\nconst CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\nconst fetchCache = new Map<string, { content: WebFetchResult; timestamp: number }>();\n\ninterface WebFetchResult {\n\turl: string;\n\ttitle: string;\n\tcontent: string;\n\tfetchedAt: string;\n}\n\nfunction stripHtmlToText(html: string): string {\n\tlet text = html;\n\t// Remove script/style/nav/footer blocks entirely\n\ttext = text.replace(/<(script|style|nav|footer|header|aside|iframe|noscript)\\b[^>]*>[\\s\\S]*?<\\/\\1>/gi, \"\");\n\t// Convert block elements to newlines\n\ttext = text.replace(/<\\/(p|div|li|tr|h[1-6]|blockquote|pre|section|article)>/gi, \"\\n\");\n\ttext = text.replace(/<(br|hr)\\s*\\/?>/gi, \"\\n\");\n\t// Convert links to text with URL\n\ttext = text.replace(/<a\\b[^>]*href=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/a>/gi, \"$2 ($1)\");\n\t// Convert headings to markdown-style\n\ttext = text.replace(/<h([1-6])\\b[^>]*>([\\s\\S]*?)<\\/h\\1>/gi, (_match, level, content) => {\n\t\treturn `\\n${\"#\".repeat(Number(level))} ${content.trim()}\\n`;\n\t});\n\t// Convert list items\n\ttext = text.replace(/<li\\b[^>]*>/gi, \"\\n- \");\n\t// Strip all remaining tags\n\ttext = text.replace(/<[^>]+>/g, \"\");\n\t// Decode common HTML entities\n\ttext = text.replace(/&/g, \"&\");\n\ttext = text.replace(/</g, \"<\");\n\ttext = text.replace(/>/g, \">\");\n\ttext = text.replace(/"/g, '\"');\n\ttext = text.replace(/'/g, \"'\");\n\ttext = text.replace(/ /g, \" \");\n\t// Collapse whitespace\n\ttext = text.replace(/[ \\t]+/g, \" \");\n\ttext = text.replace(/\\n{3,}/g, \"\\n\\n\");\n\treturn text.trim();\n}\n\nfunction extractTitle(html: string): string {\n\tconst match = html.match(/<title\\b[^>]*>([\\s\\S]*?)<\\/title>/i);\n\treturn match ? match[1].trim().replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\") : \"\";\n}\n\nconst FETCH_HEADERS = {\n\t\"User-Agent\": \"dreb/1.0 (web fetch tool)\",\n\tAccept: \"text/html,application/xhtml+xml,text/plain,application/pdf\",\n};\n\n// Block fetches to private/internal networks to prevent SSRF\nconst BLOCKED_HOSTNAMES = new Set([\"localhost\", \"127.0.0.1\", \"[::1]\", \"0.0.0.0\"]);\n\nfunction isPrivateHost(hostname: string): boolean {\n\tif (BLOCKED_HOSTNAMES.has(hostname)) return true;\n\t// IPv4 private ranges\n\tconst ipv4Match = hostname.match(/^(\\d+)\\.(\\d+)\\.\\d+\\.\\d+$/);\n\tif (ipv4Match) {\n\t\tconst [, first, second] = ipv4Match.map(Number);\n\t\tif (first === 10) return true; // 10.0.0.0/8\n\t\tif (first === 172 && second >= 16 && second <= 31) return true; // 172.16.0.0/12\n\t\tif (first === 192 && second === 168) return true; // 192.168.0.0/16\n\t\tif (first === 169 && second === 254) return true; // link-local 169.254.0.0/16\n\t}\n\t// IPv6 loopback, link-local, and ULA (fc00::/7)\n\tif (hostname.startsWith(\"[\")) {\n\t\tconst lh = hostname.toLowerCase();\n\t\tif (lh.includes(\"::1\") || lh.startsWith(\"[fe80:\") || lh.startsWith(\"[fc\") || lh.startsWith(\"[fd\")) return true;\n\t}\n\treturn false;\n}\n\nfunction buildResponse(response: Response): Promise<{ body: string | Buffer; contentType: string }> {\n\tconst ct = response.headers.get(\"content-type\") || \"\";\n\tif (ct.includes(\"application/pdf\")) {\n\t\treturn response.arrayBuffer().then((buf) => ({ body: Buffer.from(buf), contentType: ct }));\n\t}\n\treturn response.text().then((text) => ({ body: text, contentType: ct }));\n}\n\nasync function httpFetch(url: string): Promise<{ body: string | Buffer; contentType: string }> {\n\tconst originalHost = new URL(url).hostname;\n\tif (isPrivateHost(originalHost)) {\n\t\tthrow new Error(`Blocked: ${originalHost} is a private/internal address`);\n\t}\n\n\t// Manual redirect loop to enforce same-host on every hop\n\tlet currentUrl = url;\n\tconst maxRedirects = 10;\n\tfor (let i = 0; i <= maxRedirects; i++) {\n\t\tconst response = await fetch(currentUrl, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: FETCH_HEADERS,\n\t\t\tredirect: \"manual\",\n\t\t\tsignal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n\t\t});\n\n\t\tif (response.status >= 300 && response.status < 400) {\n\t\t\tconst location = response.headers.get(\"location\");\n\t\t\tif (!location) {\n\t\t\t\tthrow new Error(`HTTP ${response.status}: redirect with no Location header`);\n\t\t\t}\n\t\t\tconst redirectUrl = new URL(location, currentUrl);\n\t\t\t// Block private IPs before revealing them in cross-host messages\n\t\t\tif (isPrivateHost(redirectUrl.hostname)) {\n\t\t\t\tthrow new Error(`Blocked: redirect to private/internal address`);\n\t\t\t}\n\t\t\tif (redirectUrl.hostname !== originalHost) {\n\t\t\t\treturn {\n\t\t\t\t\tbody: `Cross-host redirect detected.\\nOriginal: ${url}\\nRedirects to: ${redirectUrl.href}\\n\\nThe redirect target is on a different host. Fetch the new URL directly if you want to follow it.`,\n\t\t\t\t\tcontentType: \"text/plain\",\n\t\t\t\t};\n\t\t\t}\n\t\t\tcurrentUrl = redirectUrl.href;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tconst errorBody = await response.text();\n\t\t\tthrow new Error(`HTTP ${response.status}: ${errorBody.slice(0, 200)}`);\n\t\t}\n\n\t\treturn buildResponse(response);\n\t}\n\tthrow new Error(`Too many redirects (${maxRedirects})`);\n}\n\n// -- PDF text extraction (basic) ---------------------------------------------\n\nfunction extractPdfText(buffer: Buffer): string {\n\t// Minimal PDF text extraction — only works on uncompressed PDFs with literal\n\t// string objects in BT/ET text blocks. Most production PDFs use FlateDecode\n\t// compression and will fall through to the failure message.\n\t// latin1 preserves raw byte values 0-255 as code points for safe regex matching.\n\tconst raw = buffer.toString(\"latin1\");\n\tconst textChunks: string[] = [];\n\n\tconst btEtRegex = /BT\\s([\\s\\S]*?)ET/g;\n\tfor (const match of raw.matchAll(btEtRegex)) {\n\t\tconst block = match[1];\n\t\tconst strRegex = /\\(([^)]*)\\)/g;\n\t\tfor (const strMatch of block.matchAll(strRegex)) {\n\t\t\tconst decoded = strMatch[1]\n\t\t\t\t.replace(/\\\\n/g, \"\\n\")\n\t\t\t\t.replace(/\\\\r/g, \"\\r\")\n\t\t\t\t.replace(/\\\\t/g, \"\\t\")\n\t\t\t\t.replace(/\\\\\\(/g, \"(\")\n\t\t\t\t.replace(/\\\\\\)/g, \")\")\n\t\t\t\t.replace(/\\\\\\\\/g, \"\\\\\");\n\t\t\tif (decoded.trim()) {\n\t\t\t\ttextChunks.push(decoded);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (textChunks.length === 0) {\n\t\treturn \"[PDF text extraction failed — the PDF may use embedded fonts or image-based content that requires OCR]\";\n\t}\n\n\treturn textChunks.join(\" \").replace(/\\s+/g, \" \").trim();\n}\n\n// ---------------------------------------------------------------------------\n// web_search tool\n// ---------------------------------------------------------------------------\n\nconst webSearchSchema = Type.Object({\n\tquery: Type.String({ description: \"The search query\" }),\n});\n\nexport type WebSearchToolInput = Static<typeof webSearchSchema>;\n\nexport interface WebSearchToolDetails {\n\ttruncation?: TruncationResult;\n}\n\ninterface SearchResult {\n\ttitle: string;\n\turl: string;\n\tsnippet: string;\n}\n\nasync function searchDuckDuckGo(query: string): Promise<SearchResult[]> {\n\tconst encodedQuery = encodeURIComponent(query);\n\tconst response = await fetch(`https://html.duckduckgo.com/html/?q=${encodedQuery}`, {\n\t\tmethod: \"GET\",\n\t\theaders: {\n\t\t\t\"User-Agent\": \"dreb/1.0 (web search tool)\",\n\t\t\tAccept: \"text/html\",\n\t\t},\n\t\tredirect: \"follow\",\n\t\tsignal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`DuckDuckGo search failed: HTTP ${response.status}`);\n\t}\n\tconst html = await response.text();\n\tconst results: SearchResult[] = [];\n\n\t// Parse DuckDuckGo HTML results — split on result block class\n\tconst resultBlocks = html.split(/class=\"result results_links/);\n\tfor (const block of resultBlocks.slice(1, 11)) {\n\t\tconst titleMatch = block.match(/class=\"result__a\"[^>]*href=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/a>/);\n\t\tconst snippetMatch = block.match(/class=\"result__snippet\"[^>]*>([\\s\\S]*?)<\\/(?:a|td|div)/);\n\n\t\tif (titleMatch) {\n\t\t\tlet url = titleMatch[1];\n\t\t\t// DDG wraps URLs in a redirect — extract the actual URL\n\t\t\tconst uddgMatch = url.match(/uddg=([^&]*)/);\n\t\t\tif (uddgMatch) {\n\t\t\t\turl = decodeURIComponent(uddgMatch[1]);\n\t\t\t}\n\t\t\tconst title = titleMatch[2].replace(/<[^>]+>/g, \"\").trim();\n\t\t\tconst snippet = snippetMatch ? snippetMatch[1].replace(/<[^>]+>/g, \"\").trim() : \"\";\n\t\t\tif (title && url) {\n\t\t\t\tresults.push({ title, url, snippet });\n\t\t\t}\n\t\t}\n\t}\n\tif (results.length === 0 && html.length > 1000) {\n\t\t// Got a substantial response but parsed 0 results — DDG HTML structure may have changed\n\t\tconsole.error(\"Warning: DDG returned HTML but 0 results were parsed. The HTML structure may have changed.\");\n\t}\n\treturn results;\n}\n\nasync function searchSearXNG(query: string, baseUrl: string): Promise<SearchResult[]> {\n\tconst encodedQuery = encodeURIComponent(query);\n\tconst response = await fetch(`${baseUrl}/search?q=${encodedQuery}&format=json`, {\n\t\tmethod: \"GET\",\n\t\theaders: { Accept: \"application/json\" },\n\t\tsignal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`SearXNG search failed: HTTP ${response.status}`);\n\t}\n\tconst data = (await response.json()) as { results?: Array<{ title: string; url: string; content?: string }> };\n\treturn (data.results || []).slice(0, 10).map((r) => ({\n\t\ttitle: r.title,\n\t\turl: r.url,\n\t\tsnippet: r.content || \"\",\n\t}));\n}\n\nasync function searchBrave(query: string, apiKey: string): Promise<SearchResult[]> {\n\tconst encodedQuery = encodeURIComponent(query);\n\tconst response = await fetch(`https://api.search.brave.com/res/v1/web/search?q=${encodedQuery}`, {\n\t\tmethod: \"GET\",\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t\t\"X-Subscription-Token\": apiKey,\n\t\t},\n\t\tsignal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`Brave search failed: HTTP ${response.status}`);\n\t}\n\tconst data = (await response.json()) as {\n\t\tweb?: { results?: Array<{ title: string; url: string; description?: string }> };\n\t};\n\treturn (data.web?.results || []).slice(0, 10).map((r) => ({\n\t\ttitle: r.title,\n\t\turl: r.url,\n\t\tsnippet: r.description || \"\",\n\t}));\n}\n\nexport interface WebSearchConfig {\n\tbackend?: \"ddg\" | \"searxng\" | \"brave\";\n\tsearxngUrl?: string;\n\tbraveApiKey?: string;\n}\n\ninterface DrebConfig {\n\tsearch?: {\n\t\tbackend?: string;\n\t\tsearxng_url?: string;\n\t\tbrave_api_key?: string;\n\t};\n}\n\nconst VALID_BACKENDS = [\"ddg\", \"searxng\", \"brave\"] as const;\n\nfunction loadDrebConfig(): DrebConfig {\n\t// Config file precedence: project-local > home directory. First valid file wins.\n\tconst candidates = [\n\t\tjoin(process.cwd(), CONFIG_DIR_NAME, \"config.json\"),\n\t\tjoin(process.cwd(), \".dreb\", \"config.json\"),\n\t\tjoin(homedir(), CONFIG_DIR_NAME, \"config.json\"),\n\t\tjoin(homedir(), \".dreb\", \"config.json\"),\n\t];\n\tfor (const configPath of candidates) {\n\t\tif (existsSync(configPath)) {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(readFileSync(configPath, \"utf-8\")) as DrebConfig;\n\t\t\t} catch (err) {\n\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\tconsole.error(`Warning: failed to parse config at ${configPath}: ${msg}`);\n\t\t\t}\n\t\t}\n\t}\n\treturn {};\n}\n\nfunction getSearchConfig(): WebSearchConfig {\n\tconst fileConfig = loadDrebConfig();\n\t// Environment variables override config file\n\tconst rawBackend = process.env.DREB_SEARCH_BACKEND || fileConfig.search?.backend;\n\tlet backend: WebSearchConfig[\"backend\"] = \"ddg\";\n\tif (rawBackend) {\n\t\tif ((VALID_BACKENDS as readonly string[]).includes(rawBackend)) {\n\t\t\tbackend = rawBackend as WebSearchConfig[\"backend\"];\n\t\t} else {\n\t\t\tconsole.error(\n\t\t\t\t`Warning: unrecognized search backend \"${rawBackend}\", falling back to ddg. Valid: ${VALID_BACKENDS.join(\", \")}`,\n\t\t\t);\n\t\t}\n\t}\n\treturn {\n\t\tbackend,\n\t\tsearxngUrl: process.env.DREB_SEARXNG_URL || fileConfig.search?.searxng_url || \"http://localhost:8888\",\n\t\tbraveApiKey: process.env.DREB_BRAVE_API_KEY || fileConfig.search?.brave_api_key,\n\t};\n}\n\nasync function executeSearch(query: string): Promise<SearchResult[]> {\n\tconst config = getSearchConfig();\n\tswitch (config.backend) {\n\t\tcase \"searxng\":\n\t\t\treturn searchSearXNG(query, config.searxngUrl!);\n\t\tcase \"brave\":\n\t\t\tif (!config.braveApiKey) throw new Error(\"DREB_BRAVE_API_KEY not set\");\n\t\t\treturn searchBrave(query, config.braveApiKey);\n\t\tdefault:\n\t\t\treturn searchDuckDuckGo(query);\n\t}\n}\n\nfunction formatSearchCall(\n\targs: { query: string } | undefined,\n\ttheme: typeof import(\"../../modes/interactive/theme/theme.js\").theme,\n): string {\n\tconst query = str(args?.query);\n\tconst invalidArg = invalidArgText(theme);\n\treturn (\n\t\ttheme.fg(\"toolTitle\", theme.bold(\"web_search\")) +\n\t\t\" \" +\n\t\t(query === null ? invalidArg : theme.fg(\"accent\", `\"${query}\"`))\n\t);\n}\n\nfunction formatSearchResult(\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string }>;\n\t\tdetails?: WebSearchToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\ttheme: typeof import(\"../../modes/interactive/theme/theme.js\").theme,\n\tshowImages: boolean,\n): string {\n\tconst output = getTextOutput(result, showImages).trim();\n\tlet text = \"\";\n\tif (output) {\n\t\tconst lines = output.split(\"\\n\");\n\t\tconst maxLines = options.expanded ? lines.length : 15;\n\t\tconst displayLines = lines.slice(0, maxLines);\n\t\tconst remaining = lines.length - maxLines;\n\t\ttext += `\\n${displayLines.map((line) => theme.fg(\"toolOutput\", line)).join(\"\\n\")}`;\n\t\tif (remaining > 0) {\n\t\t\ttext += `${theme.fg(\"muted\", `\\n... (${remaining} more lines,`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t\t}\n\t}\n\treturn text;\n}\n\nexport function createWebSearchToolDefinition(\n\t_cwd: string,\n): ToolDefinition<typeof webSearchSchema, WebSearchToolDetails | undefined> {\n\treturn {\n\t\tname: \"web_search\",\n\t\tlabel: \"web_search\",\n\t\tdescription:\n\t\t\t\"Search the web. Returns titles, URLs, and snippets. Configure backend via DREB_SEARCH_BACKEND env var (ddg, searxng, brave).\",\n\t\tpromptSnippet: \"Search the web for information\",\n\t\tparameters: webSearchSchema,\n\t\tasync execute(_toolCallId, { query }: { query: string }) {\n\t\t\tlet results: SearchResult[];\n\t\t\ttry {\n\t\t\t\tresults = await executeSearch(query);\n\t\t\t} catch (error) {\n\t\t\t\tconst msg = error instanceof Error ? error.message : String(error);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Search failed for \"${query}\": ${msg}` }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (results.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `No results found for: ${query}` }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst formatted = results.map((r, i) => `${i + 1}. ${r.title}\\n ${r.url}\\n ${r.snippet}`).join(\"\\n\\n\");\n\t\t\tconst output = `Search results for: ${query}\\n\\n${formatted}`;\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: output }],\n\t\t\t\tdetails: undefined,\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(formatSearchCall(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(formatSearchResult(result as any, options, theme, context.showImages));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createWebSearchTool(cwd: string): AgentTool<typeof webSearchSchema> {\n\treturn wrapToolDefinition(createWebSearchToolDefinition(cwd));\n}\n\nexport const webSearchToolDefinition = createWebSearchToolDefinition(process.cwd());\nexport const webSearchTool = createWebSearchTool(process.cwd());\n\n// ---------------------------------------------------------------------------\n// web_fetch tool\n// ---------------------------------------------------------------------------\n\nconst webFetchSchema = Type.Object({\n\turl: Type.String({ description: \"The URL to fetch\" }),\n});\n\nexport type WebFetchToolInput = Static<typeof webFetchSchema>;\n\nexport interface WebFetchToolDetails {\n\ttruncation?: TruncationResult;\n\ttruncatedContent?: boolean;\n}\n\nfunction formatFetchCall(\n\targs: { url: string } | undefined,\n\ttheme: typeof import(\"../../modes/interactive/theme/theme.js\").theme,\n): string {\n\tconst url = str(args?.url);\n\tconst invalidArg = invalidArgText(theme);\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"web_fetch\"))} ${url === null ? invalidArg : theme.fg(\"accent\", url || \"\")}`;\n}\n\nfunction formatFetchResult(\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string }>;\n\t\tdetails?: WebFetchToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\ttheme: typeof import(\"../../modes/interactive/theme/theme.js\").theme,\n\tshowImages: boolean,\n): string {\n\tconst output = getTextOutput(result, showImages).trim();\n\tlet text = \"\";\n\tif (output) {\n\t\tconst lines = output.split(\"\\n\");\n\t\tconst maxLines = options.expanded ? lines.length : 30;\n\t\tconst displayLines = lines.slice(0, maxLines);\n\t\tconst remaining = lines.length - maxLines;\n\t\ttext += `\\n${displayLines.map((line) => theme.fg(\"toolOutput\", line)).join(\"\\n\")}`;\n\t\tif (remaining > 0) {\n\t\t\ttext += `${theme.fg(\"muted\", `\\n... (${remaining} more lines,`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t\t}\n\t}\n\tconst details = result.details;\n\tif (details?.truncatedContent || details?.truncation?.truncated) {\n\t\tconst warnings: string[] = [];\n\t\tif (details.truncatedContent) warnings.push(`~${Math.round(MAX_CONTENT_LENGTH / 1024)}KB content limit`);\n\t\tif (details.truncation?.truncated) warnings.push(`${formatSize(DEFAULT_MAX_BYTES)} output limit`);\n\t\ttext += `\\n${theme.fg(\"warning\", `[Truncated: ${warnings.join(\", \")}]`)}`;\n\t}\n\treturn text;\n}\n\nexport function createWebFetchToolDefinition(\n\t_cwd: string,\n): ToolDefinition<typeof webFetchSchema, WebFetchToolDetails | undefined> {\n\treturn {\n\t\tname: \"web_fetch\",\n\t\tlabel: \"web_fetch\",\n\t\tdescription: `Fetch a URL and return its text content. Extracts readable text from HTML pages. Supports PDF text extraction. Content truncated to ~${Math.round(MAX_CONTENT_LENGTH / 1024)}KB. Results cached for 15 minutes.`,\n\t\tpromptSnippet: \"Fetch a URL and extract its text content\",\n\t\tparameters: webFetchSchema,\n\t\tasync execute(_toolCallId, { url }: { url: string }) {\n\t\t\t// Validate URL\n\t\t\tlet parsed: URL;\n\t\t\ttry {\n\t\t\t\tparsed = new URL(url);\n\t\t\t} catch {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Invalid URL: ${url}` }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (!parsed.protocol.startsWith(\"http\")) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Unsupported protocol: ${parsed.protocol}` }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Check cache (15-minute TTL, evict stale entries)\n\t\t\tconst cached = fetchCache.get(url);\n\t\t\tif (cached) {\n\t\t\t\tif (Date.now() - cached.timestamp < CACHE_TTL_MS) {\n\t\t\t\t\tconst r = cached.content;\n\t\t\t\t\tconst output = `${r.title}\\n${r.url}\\nFetched: ${r.fetchedAt} (cached)\\n\\n${r.content}`;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: output }],\n\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tfetchCache.delete(url);\n\t\t\t}\n\n\t\t\t// Fetch (with same-host redirect enforcement)\n\t\t\tlet body: string | Buffer;\n\t\t\tlet contentType: string;\n\t\t\ttry {\n\t\t\t\tconst result = await httpFetch(url);\n\t\t\t\tbody = result.body;\n\t\t\t\tcontentType = result.contentType;\n\t\t\t} catch (error) {\n\t\t\t\tconst msg = error instanceof Error ? error.message : String(error);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Failed to fetch ${url}: ${msg}` }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Extract content based on content type\n\t\t\tlet text: string;\n\t\t\tlet title: string;\n\t\t\tconst details: WebFetchToolDetails = {};\n\t\t\tconst fetchedAt = new Date().toISOString();\n\n\t\t\tif (contentType.includes(\"application/pdf\")) {\n\t\t\t\ttitle = url;\n\t\t\t\ttext = extractPdfText(body as Buffer);\n\t\t\t} else if (contentType.includes(\"text/html\") || contentType.includes(\"application/xhtml\")) {\n\t\t\t\tconst htmlBody = body as string;\n\t\t\t\ttitle = extractTitle(htmlBody) || url;\n\t\t\t\ttext = stripHtmlToText(htmlBody);\n\t\t\t} else if (\n\t\t\t\tcontentType.includes(\"text/plain\") ||\n\t\t\t\tcontentType.includes(\"application/json\") ||\n\t\t\t\tcontentType.includes(\"text/xml\") ||\n\t\t\t\tcontentType.includes(\"application/xml\")\n\t\t\t) {\n\t\t\t\ttitle = url;\n\t\t\t\ttext = body as string;\n\t\t\t} else {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Unsupported content type: ${contentType}` }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Truncate to prevent context overflow (~100K characters)\n\t\t\tif (text.length > MAX_CONTENT_LENGTH) {\n\t\t\t\ttext = `${text.slice(0, MAX_CONTENT_LENGTH)}\\n\\n[Content truncated at ~${Math.round(MAX_CONTENT_LENGTH / 1024)}KB]`;\n\t\t\t\tdetails.truncatedContent = true;\n\t\t\t}\n\n\t\t\tconst fetchResult: WebFetchResult = { url, title, content: text, fetchedAt };\n\t\t\tfetchCache.set(url, { content: fetchResult, timestamp: Date.now() });\n\n\t\t\tconst output = `${title}\\n${url}\\nFetched: ${fetchedAt}\\n\\n${text}`;\n\t\t\tconst truncation = truncateHead(output, { maxLines: Number.MAX_SAFE_INTEGER });\n\t\t\tif (truncation.truncated) {\n\t\t\t\tdetails.truncation = truncation;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: truncation.content }],\n\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\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(formatFetchCall(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(formatFetchResult(result as any, options, theme, context.showImages));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createWebFetchTool(cwd: string): AgentTool<typeof webFetchSchema> {\n\treturn wrapToolDefinition(createWebFetchToolDefinition(cwd));\n}\n\nexport const webFetchToolDefinition = createWebFetchToolDefinition(process.cwd());\nexport const webFetchTool = createWebFetchTool(process.cwd());\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AgentTool } from "@dreb/agent-core";
|
|
2
|
+
import { type Static } from "@sinclair/typebox";
|
|
3
|
+
import type { ToolDefinition } from "../extensions/types.js";
|
|
4
|
+
declare const writeSchema: import("@sinclair/typebox").TObject<{
|
|
5
|
+
path: import("@sinclair/typebox").TString;
|
|
6
|
+
content: import("@sinclair/typebox").TString;
|
|
7
|
+
}>;
|
|
8
|
+
export type WriteToolInput = Static<typeof writeSchema>;
|
|
9
|
+
/**
|
|
10
|
+
* Pluggable operations for the write tool.
|
|
11
|
+
* Override these to delegate file writing to remote systems (for example SSH).
|
|
12
|
+
*/
|
|
13
|
+
export interface WriteOperations {
|
|
14
|
+
/** Write content to a file */
|
|
15
|
+
writeFile: (absolutePath: string, content: string) => Promise<void>;
|
|
16
|
+
/** Create directory recursively */
|
|
17
|
+
mkdir: (dir: string) => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export interface WriteToolOptions {
|
|
20
|
+
/** Custom operations for file writing. Default: local filesystem */
|
|
21
|
+
operations?: WriteOperations;
|
|
22
|
+
}
|
|
23
|
+
export declare function createWriteToolDefinition(cwd: string, options?: WriteToolOptions): ToolDefinition<typeof writeSchema, undefined>;
|
|
24
|
+
export declare function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema>;
|
|
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>;
|
|
30
|
+
export declare const writeTool: AgentTool<import("@sinclair/typebox").TObject<{
|
|
31
|
+
path: import("@sinclair/typebox").TString;
|
|
32
|
+
content: import("@sinclair/typebox").TString;
|
|
33
|
+
}>, any>;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=write.d.ts.map
|