@m4ike1/ion-coding-agent 0.1.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 +5747 -0
- package/README.md +738 -0
- package/dist/bun/cli.d.ts +5 -0
- package/dist/bun/cli.d.ts.map +1 -0
- package/dist/bun/cli.js +5 -0
- package/dist/bun/cli.js.map +1 -0
- package/dist/bun/restore-sandbox-env.d.ts +17 -0
- package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
- package/dist/bun/restore-sandbox-env.js +36 -0
- package/dist/bun/restore-sandbox-env.js.map +1 -0
- package/dist/bun/runtime-setup.d.ts +2 -0
- package/dist/bun/runtime-setup.d.ts.map +1 -0
- package/dist/bun/runtime-setup.js +9 -0
- package/dist/bun/runtime-setup.js.map +1 -0
- package/dist/bun/sandbox-env-setup.d.ts +2 -0
- package/dist/bun/sandbox-env-setup.d.ts.map +1 -0
- package/dist/bun/sandbox-env-setup.js +4 -0
- package/dist/bun/sandbox-env-setup.js.map +1 -0
- package/dist/bundle/chunks/anthropic-messages-RPVA4Z4Y.js +6 -0
- package/dist/bundle/chunks/anthropic.js +75 -0
- package/dist/bundle/chunks/azure-openai-responses-AJS3XTKL.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +78 -0
- package/dist/bundle/chunks/chunk-2MOZ6JBC.js +2 -0
- package/dist/bundle/chunks/chunk-3BIJ3AQO.js +12 -0
- package/dist/bundle/chunks/chunk-47K3I3YT.js +6 -0
- package/dist/bundle/chunks/chunk-4BN67GCJ.js +1664 -0
- package/dist/bundle/chunks/chunk-4PN6UIWX.js +2 -0
- package/dist/bundle/chunks/chunk-4TQA6ATT.js +4 -0
- package/dist/bundle/chunks/chunk-5NVSYJOG.js +2 -0
- package/dist/bundle/chunks/chunk-7OJL7DR5.js +2 -0
- package/dist/bundle/chunks/chunk-BEER2HEL.js +2 -0
- package/dist/bundle/chunks/chunk-CQX3HQAT.js +2 -0
- package/dist/bundle/chunks/chunk-FBMFFBV2.js +2 -0
- package/dist/bundle/chunks/chunk-GAZIWLQB.js +2 -0
- package/dist/bundle/chunks/chunk-HFYRAIWC.js +44 -0
- package/dist/bundle/chunks/chunk-IH7HUXWH.js +2 -0
- package/dist/bundle/chunks/chunk-LPP2XRBR.js +11 -0
- package/dist/bundle/chunks/chunk-LUTYILPM.js +25 -0
- package/dist/bundle/chunks/chunk-Q3ZNVFWD.js +42 -0
- package/dist/bundle/chunks/chunk-QNBVCBN3.js +2 -0
- package/dist/bundle/chunks/chunk-SWVWKUIA.js +2 -0
- package/dist/bundle/chunks/chunk-SY4QP6EI.js +2 -0
- package/dist/bundle/chunks/chunk-TVAWBPPS.js +2 -0
- package/dist/bundle/chunks/chunk-WPN6KEON.js +2 -0
- package/dist/bundle/chunks/chunk-WRID246J.js +2 -0
- package/dist/bundle/chunks/github-copilot.js +2 -0
- package/dist/bundle/chunks/google-generative-ai-S7SD5HC7.js +2 -0
- package/dist/bundle/chunks/google-vertex-NUNHA7QM.js +2 -0
- package/dist/bundle/chunks/https-proxy-agent-O2332S4O.js +13 -0
- package/dist/bundle/chunks/image-resize-worker.js +2 -0
- package/dist/bundle/chunks/ion-messages-KTW6MD7U.js +8 -0
- package/dist/bundle/chunks/kimi-coding.js +2 -0
- package/dist/bundle/chunks/lib-D4EQQPRR.js +9 -0
- package/dist/bundle/chunks/mistral-conversations-C7I3G2LA.js +5 -0
- package/dist/bundle/chunks/multipart-parser-PL2BXRDT.js +3 -0
- package/dist/bundle/chunks/node-7OQEATQA.js +2 -0
- package/dist/bundle/chunks/node-QIUI6CIW.js +16 -0
- package/dist/bundle/chunks/openai-codex-responses-2KRULDYR.js +10 -0
- package/dist/bundle/chunks/openai-codex.js +75 -0
- package/dist/bundle/chunks/openai-completions-64KX63FN.js +7 -0
- package/dist/bundle/chunks/openai-responses-QF3PPSTS.js +2 -0
- package/dist/bundle/chunks/openrouter-images-GQVXT3PO.js +2 -0
- package/dist/bundle/chunks/openrouter.js +75 -0
- package/dist/bundle/chunks/radius.js +75 -0
- package/dist/bundle/chunks/src-AZ7LBHGY.js +4 -0
- package/dist/bundle/chunks/xai.js +2 -0
- package/dist/bundle/cli.js +3 -0
- package/dist/bundle/index.js +2 -0
- package/dist/bundle/rpc-entry.js +3 -0
- package/dist/cli/args.d.ts +61 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +440 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/auth-check.d.ts +19 -0
- package/dist/cli/auth-check.d.ts.map +1 -0
- package/dist/cli/auth-check.js +50 -0
- package/dist/cli/auth-check.js.map +1 -0
- package/dist/cli/auth-command.d.ts +24 -0
- package/dist/cli/auth-command.d.ts.map +1 -0
- package/dist/cli/auth-command.js +103 -0
- package/dist/cli/auth-command.js.map +1 -0
- package/dist/cli/config-selector.d.ts +16 -0
- package/dist/cli/config-selector.d.ts.map +1 -0
- package/dist/cli/config-selector.js +32 -0
- package/dist/cli/config-selector.js.map +1 -0
- package/dist/cli/credential-print.d.ts +13 -0
- package/dist/cli/credential-print.d.ts.map +1 -0
- package/dist/cli/credential-print.js +76 -0
- package/dist/cli/credential-print.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 +71 -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 +98 -0
- package/dist/cli/list-models.js.map +1 -0
- package/dist/cli/project-trust.d.ts +10 -0
- package/dist/cli/project-trust.d.ts.map +1 -0
- package/dist/cli/project-trust.js +48 -0
- package/dist/cli/project-trust.js.map +1 -0
- package/dist/cli/session-picker.d.ts +10 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +36 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli/setup.d.ts +2 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +12 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/startup-ui.d.ts +20 -0
- package/dist/cli/startup-ui.d.ts.map +1 -0
- package/dist/cli/startup-ui.js +185 -0
- package/dist/cli/startup-ui.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +122 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +609 -0
- package/dist/config.js.map +1 -0
- package/dist/core/agent-session-runtime.d.ts +119 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -0
- package/dist/core/agent-session-runtime.js +317 -0
- package/dist/core/agent-session-runtime.js.map +1 -0
- package/dist/core/agent-session-services.d.ts +86 -0
- package/dist/core/agent-session-services.d.ts.map +1 -0
- package/dist/core/agent-session-services.js +134 -0
- package/dist/core/agent-session-services.js.map +1 -0
- package/dist/core/agent-session.d.ts +725 -0
- package/dist/core/agent-session.d.ts.map +1 -0
- package/dist/core/agent-session.js +2968 -0
- package/dist/core/agent-session.js.map +1 -0
- package/dist/core/auth-guidance.d.ts +5 -0
- package/dist/core/auth-guidance.d.ts.map +1 -0
- package/dist/core/auth-guidance.js +21 -0
- package/dist/core/auth-guidance.js.map +1 -0
- package/dist/core/auth-storage.d.ts +72 -0
- package/dist/core/auth-storage.d.ts.map +1 -0
- package/dist/core/auth-storage.js +426 -0
- package/dist/core/auth-storage.js.map +1 -0
- package/dist/core/bash-executor.d.ts +32 -0
- package/dist/core/bash-executor.d.ts.map +1 -0
- package/dist/core/bash-executor.js +111 -0
- package/dist/core/bash-executor.js.map +1 -0
- package/dist/core/cache-stats.d.ts +49 -0
- package/dist/core/cache-stats.d.ts.map +1 -0
- package/dist/core/cache-stats.js +101 -0
- package/dist/core/cache-stats.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts +98 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
- package/dist/core/compaction/branch-summarization.js +251 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +145 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -0
- package/dist/core/compaction/compaction.js +690 -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 +142 -0
- package/dist/core/compaction/utils.js.map +1 -0
- package/dist/core/defaults.d.ts +4 -0
- package/dist/core/defaults.d.ts.map +1 -0
- package/dist/core/defaults.js +11 -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/experimental.d.ts +2 -0
- package/dist/core/experimental.d.ts.map +1 -0
- package/dist/core/experimental.js +4 -0
- package/dist/core/experimental.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 +226 -0
- package/dist/core/export-html/index.js.map +1 -0
- package/dist/core/export-html/template.css +1066 -0
- package/dist/core/export-html/template.html +55 -0
- package/dist/core/export-html/template.js +1871 -0
- package/dist/core/export-html/tool-renderer.d.ts +34 -0
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
- package/dist/core/export-html/tool-renderer.js +108 -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 +78 -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 +23 -0
- package/dist/core/extensions/loader.d.ts.map +1 -0
- package/dist/core/extensions/loader.js +655 -0
- package/dist/core/extensions/loader.js.map +1 -0
- package/dist/core/extensions/runner.d.ts +178 -0
- package/dist/core/extensions/runner.d.ts.map +1 -0
- package/dist/core/extensions/runner.js +1011 -0
- package/dist/core/extensions/runner.js.map +1 -0
- package/dist/core/extensions/types.d.ts +1375 -0
- package/dist/core/extensions/types.d.ts.map +1 -0
- package/dist/core/extensions/types.js +54 -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 +41 -0
- package/dist/core/extensions/wrapper.js.map +1 -0
- package/dist/core/footer-data-provider.d.ts +64 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -0
- package/dist/core/footer-data-provider.js +338 -0
- package/dist/core/footer-data-provider.js.map +1 -0
- package/dist/core/http-dispatcher.d.ts +22 -0
- package/dist/core/http-dispatcher.d.ts.map +1 -0
- package/dist/core/http-dispatcher.js +98 -0
- package/dist/core/http-dispatcher.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +13 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/ion-manifest.d.ts +8 -0
- package/dist/core/ion-manifest.d.ts.map +1 -0
- package/dist/core/ion-manifest.js +26 -0
- package/dist/core/ion-manifest.js.map +1 -0
- package/dist/core/keybindings.d.ts +475 -0
- package/dist/core/keybindings.d.ts.map +1 -0
- package/dist/core/keybindings.js +321 -0
- package/dist/core/keybindings.js.map +1 -0
- package/dist/core/messages.d.ts +77 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.js +123 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/model-config.d.ts +591 -0
- package/dist/core/model-config.d.ts.map +1 -0
- package/dist/core/model-config.js +259 -0
- package/dist/core/model-config.js.map +1 -0
- package/dist/core/model-registry.d.ts +49 -0
- package/dist/core/model-registry.d.ts.map +1 -0
- package/dist/core/model-registry.js +115 -0
- package/dist/core/model-registry.js.map +1 -0
- package/dist/core/model-resolver.d.ts +124 -0
- package/dist/core/model-resolver.d.ts.map +1 -0
- package/dist/core/model-resolver.js +591 -0
- package/dist/core/model-resolver.js.map +1 -0
- package/dist/core/model-runtime.d.ts +101 -0
- package/dist/core/model-runtime.d.ts.map +1 -0
- package/dist/core/model-runtime.js +606 -0
- package/dist/core/model-runtime.js.map +1 -0
- package/dist/core/models-store.d.ts +22 -0
- package/dist/core/models-store.d.ts.map +1 -0
- package/dist/core/models-store.js +115 -0
- package/dist/core/models-store.js.map +1 -0
- package/dist/core/output-guard.d.ts +7 -0
- package/dist/core/output-guard.d.ts.map +1 -0
- package/dist/core/output-guard.js +89 -0
- package/dist/core/output-guard.js.map +1 -0
- package/dist/core/package-manager.d.ts +216 -0
- package/dist/core/package-manager.d.ts.map +1 -0
- package/dist/core/package-manager.js +2207 -0
- package/dist/core/package-manager.js.map +1 -0
- package/dist/core/project-trust.d.ts +15 -0
- package/dist/core/project-trust.d.ts.map +1 -0
- package/dist/core/project-trust.js +59 -0
- package/dist/core/project-trust.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +54 -0
- package/dist/core/prompt-templates.d.ts.map +1 -0
- package/dist/core/prompt-templates.js +236 -0
- package/dist/core/prompt-templates.js.map +1 -0
- package/dist/core/provider-attribution.d.ts +4 -0
- package/dist/core/provider-attribution.d.ts.map +1 -0
- package/dist/core/provider-attribution.js +72 -0
- package/dist/core/provider-attribution.js.map +1 -0
- package/dist/core/provider-composer.d.ts +58 -0
- package/dist/core/provider-composer.d.ts.map +1 -0
- package/dist/core/provider-composer.js +402 -0
- package/dist/core/provider-composer.js.map +1 -0
- package/dist/core/radius.d.ts +2 -0
- package/dist/core/radius.d.ts.map +1 -0
- package/dist/core/radius.js +2 -0
- package/dist/core/radius.js.map +1 -0
- package/dist/core/remote-catalog-provider.d.ts +5 -0
- package/dist/core/remote-catalog-provider.d.ts.map +1 -0
- package/dist/core/remote-catalog-provider.js +137 -0
- package/dist/core/remote-catalog-provider.js.map +1 -0
- package/dist/core/resolve-config-value.d.ts +30 -0
- package/dist/core/resolve-config-value.d.ts.map +1 -0
- package/dist/core/resolve-config-value.js +247 -0
- package/dist/core/resolve-config-value.js.map +1 -0
- package/dist/core/resource-loader.d.ts +221 -0
- package/dist/core/resource-loader.d.ts.map +1 -0
- package/dist/core/resource-loader.js +875 -0
- package/dist/core/resource-loader.js.map +1 -0
- package/dist/core/runtime-credentials.d.ts +15 -0
- package/dist/core/runtime-credentials.d.ts.map +1 -0
- package/dist/core/runtime-credentials.js +39 -0
- package/dist/core/runtime-credentials.js.map +1 -0
- package/dist/core/sdk.d.ts +108 -0
- package/dist/core/sdk.d.ts.map +1 -0
- package/dist/core/sdk.js +285 -0
- package/dist/core/sdk.js.map +1 -0
- package/dist/core/session-cwd.d.ts +19 -0
- package/dist/core/session-cwd.d.ts.map +1 -0
- package/dist/core/session-cwd.js +38 -0
- package/dist/core/session-cwd.js.map +1 -0
- package/dist/core/session-export.d.ts +4 -0
- package/dist/core/session-export.d.ts.map +1 -0
- package/dist/core/session-export.js +32 -0
- package/dist/core/session-export.js.map +1 -0
- package/dist/core/session-index.d.ts +67 -0
- package/dist/core/session-index.d.ts.map +1 -0
- package/dist/core/session-index.js +376 -0
- package/dist/core/session-index.js.map +1 -0
- package/dist/core/session-manager.d.ts +376 -0
- package/dist/core/session-manager.d.ts.map +1 -0
- package/dist/core/session-manager.js +1587 -0
- package/dist/core/session-manager.js.map +1 -0
- package/dist/core/session-naming-runtime.d.ts +153 -0
- package/dist/core/session-naming-runtime.d.ts.map +1 -0
- package/dist/core/session-naming-runtime.js +336 -0
- package/dist/core/session-naming-runtime.js.map +1 -0
- package/dist/core/settings-diagnostics.d.ts +9 -0
- package/dist/core/settings-diagnostics.d.ts.map +1 -0
- package/dist/core/settings-diagnostics.js +21 -0
- package/dist/core/settings-diagnostics.js.map +1 -0
- package/dist/core/settings-manager.d.ts +375 -0
- package/dist/core/settings-manager.d.ts.map +1 -0
- package/dist/core/settings-manager.js +1110 -0
- package/dist/core/settings-manager.js.map +1 -0
- package/dist/core/skills.d.ts +60 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +412 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/slash-commands.d.ts +17 -0
- package/dist/core/slash-commands.d.ts.map +1 -0
- package/dist/core/slash-commands.js +33 -0
- package/dist/core/slash-commands.js.map +1 -0
- package/dist/core/source-info.d.ts +18 -0
- package/dist/core/source-info.d.ts.map +1 -0
- package/dist/core/source-info.js +19 -0
- package/dist/core/source-info.js.map +1 -0
- package/dist/core/system-prompt.d.ts +28 -0
- package/dist/core/system-prompt.d.ts.map +1 -0
- package/dist/core/system-prompt.js +118 -0
- package/dist/core/system-prompt.js.map +1 -0
- package/dist/core/telemetry.d.ts +3 -0
- package/dist/core/telemetry.d.ts.map +1 -0
- package/dist/core/telemetry.js +9 -0
- package/dist/core/telemetry.js.map +1 -0
- package/dist/core/timings.d.ts +10 -0
- package/dist/core/timings.d.ts.map +1 -0
- package/dist/core/timings.js +41 -0
- package/dist/core/timings.js.map +1 -0
- package/dist/core/tools/bash.d.ts +87 -0
- package/dist/core/tools/bash.d.ts.map +1 -0
- package/dist/core/tools/bash.js +295 -0
- package/dist/core/tools/bash.js.map +1 -0
- package/dist/core/tools/edit-diff.d.ts +101 -0
- package/dist/core/tools/edit-diff.d.ts.map +1 -0
- package/dist/core/tools/edit-diff.js +421 -0
- package/dist/core/tools/edit-diff.js.map +1 -0
- package/dist/core/tools/edit.d.ts +44 -0
- package/dist/core/tools/edit.d.ts.map +1 -0
- package/dist/core/tools/edit.js +147 -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 +52 -0
- package/dist/core/tools/file-mutation-queue.js.map +1 -0
- package/dist/core/tools/find.d.ts +42 -0
- package/dist/core/tools/find.d.ts.map +1 -0
- package/dist/core/tools/find.js +251 -0
- package/dist/core/tools/find.js.map +1 -0
- package/dist/core/tools/grep.d.ts +53 -0
- package/dist/core/tools/grep.d.ts.map +1 -0
- package/dist/core/tools/grep.js +463 -0
- package/dist/core/tools/grep.js.map +1 -0
- package/dist/core/tools/index.d.ts +49 -0
- package/dist/core/tools/index.d.ts.map +1 -0
- package/dist/core/tools/index.js +147 -0
- package/dist/core/tools/index.js.map +1 -0
- package/dist/core/tools/ls.d.ts +48 -0
- package/dist/core/tools/ls.d.ts.map +1 -0
- package/dist/core/tools/ls.js +224 -0
- package/dist/core/tools/ls.js.map +1 -0
- package/dist/core/tools/output-accumulator.d.ts +52 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -0
- package/dist/core/tools/output-accumulator.js +184 -0
- package/dist/core/tools/output-accumulator.js.map +1 -0
- package/dist/core/tools/path-utils.d.ts +10 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -0
- package/dist/core/tools/path-utils.js +99 -0
- package/dist/core/tools/path-utils.js.map +1 -0
- package/dist/core/tools/powershell.d.ts +16 -0
- package/dist/core/tools/powershell.d.ts.map +1 -0
- package/dist/core/tools/powershell.js +39 -0
- package/dist/core/tools/powershell.js.map +1 -0
- package/dist/core/tools/read.d.ts +39 -0
- package/dist/core/tools/read.d.ts.map +1 -0
- package/dist/core/tools/read.js +165 -0
- package/dist/core/tools/read.js.map +1 -0
- package/dist/core/tools/render-utils.d.ts +24 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -0
- package/dist/core/tools/render-utils.js +65 -0
- package/dist/core/tools/render-utils.js.map +1 -0
- package/dist/core/tools/renderers/bash.d.ts +12 -0
- package/dist/core/tools/renderers/bash.d.ts.map +1 -0
- package/dist/core/tools/renderers/bash.js +130 -0
- package/dist/core/tools/renderers/bash.js.map +1 -0
- package/dist/core/tools/renderers/edit.d.ts +23 -0
- package/dist/core/tools/renderers/edit.d.ts.map +1 -0
- package/dist/core/tools/renderers/edit.js +167 -0
- package/dist/core/tools/renderers/edit.js.map +1 -0
- package/dist/core/tools/renderers/find.d.ts +10 -0
- package/dist/core/tools/renderers/find.d.ts.map +1 -0
- package/dist/core/tools/renderers/find.js +64 -0
- package/dist/core/tools/renderers/find.js.map +1 -0
- package/dist/core/tools/renderers/grep.d.ts +10 -0
- package/dist/core/tools/renderers/grep.d.ts.map +1 -0
- package/dist/core/tools/renderers/grep.js +69 -0
- package/dist/core/tools/renderers/grep.js.map +1 -0
- package/dist/core/tools/renderers/index.d.ts +29 -0
- package/dist/core/tools/renderers/index.d.ts.map +1 -0
- package/dist/core/tools/renderers/index.js +50 -0
- package/dist/core/tools/renderers/index.js.map +1 -0
- package/dist/core/tools/renderers/ls.d.ts +10 -0
- package/dist/core/tools/renderers/ls.d.ts.map +1 -0
- package/dist/core/tools/renderers/ls.js +66 -0
- package/dist/core/tools/renderers/ls.js.map +1 -0
- package/dist/core/tools/renderers/read.d.ts +11 -0
- package/dist/core/tools/renderers/read.d.ts.map +1 -0
- package/dist/core/tools/renderers/read.js +129 -0
- package/dist/core/tools/renderers/read.js.map +1 -0
- package/dist/core/tools/renderers/webfetch.d.ts +11 -0
- package/dist/core/tools/renderers/webfetch.d.ts.map +1 -0
- package/dist/core/tools/renderers/webfetch.js +89 -0
- package/dist/core/tools/renderers/webfetch.js.map +1 -0
- package/dist/core/tools/renderers/write.d.ts +10 -0
- package/dist/core/tools/renderers/write.d.ts.map +1 -0
- package/dist/core/tools/renderers/write.js +153 -0
- package/dist/core/tools/renderers/write.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 +36 -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 +215 -0
- package/dist/core/tools/truncate.js.map +1 -0
- package/dist/core/tools/webextract.d.ts +36 -0
- package/dist/core/tools/webextract.d.ts.map +1 -0
- package/dist/core/tools/webextract.js +130 -0
- package/dist/core/tools/webextract.js.map +1 -0
- package/dist/core/tools/webfetch.d.ts +104 -0
- package/dist/core/tools/webfetch.d.ts.map +1 -0
- package/dist/core/tools/webfetch.js +231 -0
- package/dist/core/tools/webfetch.js.map +1 -0
- package/dist/core/tools/write.d.ts +30 -0
- package/dist/core/tools/write.d.ts.map +1 -0
- package/dist/core/tools/write.js +61 -0
- package/dist/core/tools/write.js.map +1 -0
- package/dist/core/trust-manager.d.ts +36 -0
- package/dist/core/trust-manager.d.ts.map +1 -0
- package/dist/core/trust-manager.js +203 -0
- package/dist/core/trust-manager.js.map +1 -0
- package/dist/core/usage-totals.d.ts +19 -0
- package/dist/core/usage-totals.d.ts.map +1 -0
- package/dist/core/usage-totals.js +52 -0
- package/dist/core/usage-totals.js.map +1 -0
- package/dist/core/webfetch/backend-exa.d.ts +65 -0
- package/dist/core/webfetch/backend-exa.d.ts.map +1 -0
- package/dist/core/webfetch/backend-exa.js +282 -0
- package/dist/core/webfetch/backend-exa.js.map +1 -0
- package/dist/core/webfetch/backend-firecrawl.d.ts +59 -0
- package/dist/core/webfetch/backend-firecrawl.d.ts.map +1 -0
- package/dist/core/webfetch/backend-firecrawl.js +339 -0
- package/dist/core/webfetch/backend-firecrawl.js.map +1 -0
- package/dist/core/webfetch/backend-undici.d.ts +21 -0
- package/dist/core/webfetch/backend-undici.d.ts.map +1 -0
- package/dist/core/webfetch/backend-undici.js +109 -0
- package/dist/core/webfetch/backend-undici.js.map +1 -0
- package/dist/core/webfetch/backend.d.ts +45 -0
- package/dist/core/webfetch/backend.d.ts.map +1 -0
- package/dist/core/webfetch/backend.js +9 -0
- package/dist/core/webfetch/backend.js.map +1 -0
- package/dist/core/webfetch/doc-store.d.ts +45 -0
- package/dist/core/webfetch/doc-store.d.ts.map +1 -0
- package/dist/core/webfetch/doc-store.js +57 -0
- package/dist/core/webfetch/doc-store.js.map +1 -0
- package/dist/core/webfetch/guardrails.d.ts +75 -0
- package/dist/core/webfetch/guardrails.d.ts.map +1 -0
- package/dist/core/webfetch/guardrails.js +195 -0
- package/dist/core/webfetch/guardrails.js.map +1 -0
- package/dist/core/webfetch/robots.d.ts +46 -0
- package/dist/core/webfetch/robots.d.ts.map +1 -0
- package/dist/core/webfetch/robots.js +153 -0
- package/dist/core/webfetch/robots.js.map +1 -0
- package/dist/core/webfetch/search-intent.d.ts +59 -0
- package/dist/core/webfetch/search-intent.d.ts.map +1 -0
- package/dist/core/webfetch/search-intent.js +89 -0
- package/dist/core/webfetch/search-intent.js.map +1 -0
- package/dist/core/webfetch/search-tags.d.ts +23 -0
- package/dist/core/webfetch/search-tags.d.ts.map +1 -0
- package/dist/core/webfetch/search-tags.js +118 -0
- package/dist/core/webfetch/search-tags.js.map +1 -0
- package/dist/env-compat.d.ts +2 -0
- package/dist/env-compat.d.ts.map +1 -0
- package/dist/env-compat.js +17 -0
- package/dist/env-compat.js.map +1 -0
- package/dist/extensions/cue/autocomplete.d.ts +126 -0
- package/dist/extensions/cue/autocomplete.d.ts.map +1 -0
- package/dist/extensions/cue/autocomplete.js +744 -0
- package/dist/extensions/cue/autocomplete.js.map +1 -0
- package/dist/extensions/cue/index.d.ts +3 -0
- package/dist/extensions/cue/index.d.ts.map +1 -0
- package/dist/extensions/cue/index.js +341 -0
- package/dist/extensions/cue/index.js.map +1 -0
- package/dist/extensions/index.d.ts +13 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +18 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/llama/client.d.ts +67 -0
- package/dist/extensions/llama/client.d.ts.map +1 -0
- package/dist/extensions/llama/client.js +309 -0
- package/dist/extensions/llama/client.js.map +1 -0
- package/dist/extensions/llama/huggingface.d.ts +23 -0
- package/dist/extensions/llama/huggingface.d.ts.map +1 -0
- package/dist/extensions/llama/huggingface.js +141 -0
- package/dist/extensions/llama/huggingface.js.map +1 -0
- package/dist/extensions/llama/index.d.ts +3 -0
- package/dist/extensions/llama/index.d.ts.map +1 -0
- package/dist/extensions/llama/index.js +219 -0
- package/dist/extensions/llama/index.js.map +1 -0
- package/dist/extensions/llama/provider.d.ts +12 -0
- package/dist/extensions/llama/provider.d.ts.map +1 -0
- package/dist/extensions/llama/provider.js +146 -0
- package/dist/extensions/llama/provider.js.map +1 -0
- package/dist/extensions/llama/ui.d.ts +42 -0
- package/dist/extensions/llama/ui.d.ts.map +1 -0
- package/dist/extensions/llama/ui.js +416 -0
- package/dist/extensions/llama/ui.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +17 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +820 -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 +288 -0
- package/dist/migrations.js.map +1 -0
- package/dist/modes/index.d.ts +10 -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/assets/clankolas.png +0 -0
- package/dist/modes/interactive/chat-viewport.d.ts +20 -0
- package/dist/modes/interactive/chat-viewport.d.ts.map +1 -0
- package/dist/modes/interactive/chat-viewport.js +28 -0
- package/dist/modes/interactive/chat-viewport.js.map +1 -0
- package/dist/modes/interactive/components/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 +26 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/assistant-message.js +171 -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 +54 -0
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.js +44 -0
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +45 -0
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/config-selector.d.ts +102 -0
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/config-selector.js +770 -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 +30 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-editor.js +115 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -0
- package/dist/modes/interactive/components/custom-entry.d.ts +19 -0
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-entry.js +52 -0
- package/dist/modes/interactive/components/custom-entry.js.map +1 -0
- package/dist/modes/interactive/components/custom-message.d.ts +22 -0
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-message.js +87 -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/earendil-announcement.d.ts +5 -0
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -0
- package/dist/modes/interactive/components/earendil-announcement.js +40 -0
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +21 -0
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-editor.js +98 -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 +26 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-selector.js +83 -0
- package/dist/modes/interactive/components/extension-selector.js.map +1 -0
- package/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -0
- package/dist/modes/interactive/components/first-time-setup.js +103 -0
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts +32 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -0
- package/dist/modes/interactive/components/footer.js +230 -0
- package/dist/modes/interactive/components/footer.js.map +1 -0
- package/dist/modes/interactive/components/index.d.ts +34 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -0
- package/dist/modes/interactive/components/index.js +35 -0
- package/dist/modes/interactive/components/index.js.map +1 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
- package/dist/modes/interactive/components/keybinding-hints.js +36 -0
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
- package/dist/modes/interactive/components/login-dialog.d.ts +52 -0
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
- package/dist/modes/interactive/components/login-dialog.js +188 -0
- package/dist/modes/interactive/components/login-dialog.js.map +1 -0
- package/dist/modes/interactive/components/markdown-transform.d.ts +3 -0
- package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -0
- package/dist/modes/interactive/components/markdown-transform.js +19 -0
- package/dist/modes/interactive/components/markdown-transform.js.map +1 -0
- package/dist/modes/interactive/components/mermaid.d.ts +11 -0
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
- package/dist/modes/interactive/components/mermaid.js +75 -0
- package/dist/modes/interactive/components/mermaid.js.map +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts +60 -0
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/model-selector.js +361 -0
- package/dist/modes/interactive/components/model-selector.js.map +1 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/oauth-selector.js +163 -0
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +46 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.js +326 -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 +98 -0
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector.js +891 -0
- package/dist/modes/interactive/components/session-selector.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +98 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/settings-selector.js +745 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -0
- package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
- package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
- package/dist/modes/interactive/components/settings-submenu.js +165 -0
- package/dist/modes/interactive/components/settings-submenu.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/status-indicator.d.ts +30 -0
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -0
- package/dist/modes/interactive/components/status-indicator.js +67 -0
- package/dist/modes/interactive/components/status-indicator.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 +23 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.js +109 -0
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +80 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-execution.js +328 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +94 -0
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/tree-selector.js +1245 -0
- package/dist/modes/interactive/components/tree-selector.js.map +1 -0
- package/dist/modes/interactive/components/trust-selector.d.ts +23 -0
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/trust-selector.js +91 -0
- package/dist/modes/interactive/components/trust-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 +114 -0
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message.d.ts +16 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/user-message.js +49 -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/external-editor.d.ts +12 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -0
- package/dist/modes/interactive/external-editor.js +38 -0
- package/dist/modes/interactive/external-editor.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +471 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-mode.js +5735 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -0
- package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
- package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
- package/dist/modes/interactive/model-catalog-refresh.js +34 -0
- package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
- package/dist/modes/interactive/model-search.d.ts +12 -0
- package/dist/modes/interactive/model-search.d.ts.map +1 -0
- package/dist/modes/interactive/model-search.js +15 -0
- package/dist/modes/interactive/model-search.js.map +1 -0
- package/dist/modes/interactive/session-share.d.ts +16 -0
- package/dist/modes/interactive/session-share.d.ts.map +1 -0
- package/dist/modes/interactive/session-share.js +184 -0
- package/dist/modes/interactive/session-share.js.map +1 -0
- package/dist/modes/interactive/theme/dark.json +91 -0
- package/dist/modes/interactive/theme/light.json +90 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +41 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-controller.js +130 -0
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -0
- package/dist/modes/interactive/theme/theme-json.d.ts +84 -0
- package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-json.js +130 -0
- package/dist/modes/interactive/theme/theme-json.js.map +1 -0
- package/dist/modes/interactive/theme/theme-schema.json +356 -0
- package/dist/modes/interactive/theme/theme.d.ts +131 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme.js +991 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -0
- package/dist/modes/interactive/tui-renderer.d.ts +21 -0
- package/dist/modes/interactive/tui-renderer.d.ts.map +1 -0
- package/dist/modes/interactive/tui-renderer.js +66 -0
- package/dist/modes/interactive/tui-renderer.js.map +1 -0
- package/dist/modes/json-event.d.ts +34 -0
- package/dist/modes/json-event.d.ts.map +1 -0
- package/dist/modes/json-event.js +29 -0
- package/dist/modes/json-event.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 +142 -0
- package/dist/modes/print-mode.js.map +1 -0
- package/dist/modes/rpc/jsonl.d.ts +17 -0
- package/dist/modes/rpc/jsonl.d.ts.map +1 -0
- package/dist/modes/rpc/jsonl.js +49 -0
- package/dist/modes/rpc/jsonl.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +254 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-client.js +495 -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 +657 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -0
- package/dist/modes/rpc/rpc-types.d.ts +469 -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/package-manager-cli.d.ts +9 -0
- package/dist/package-manager-cli.d.ts.map +1 -0
- package/dist/package-manager-cli.js +961 -0
- package/dist/package-manager-cli.js.map +1 -0
- package/dist/rpc-entry.d.ts +3 -0
- package/dist/rpc-entry.d.ts.map +1 -0
- package/dist/rpc-entry.js +12 -0
- package/dist/rpc-entry.js.map +1 -0
- package/dist/utils/abort.d.ts +5 -0
- package/dist/utils/abort.d.ts.map +1 -0
- package/dist/utils/abort.js +48 -0
- package/dist/utils/abort.js.map +1 -0
- package/dist/utils/ansi.d.ts +2 -0
- package/dist/utils/ansi.d.ts.map +1 -0
- package/dist/utils/ansi.js +52 -0
- package/dist/utils/ansi.js.map +1 -0
- package/dist/utils/changelog.d.ts +22 -0
- package/dist/utils/changelog.d.ts.map +1 -0
- package/dist/utils/changelog.js +165 -0
- package/dist/utils/changelog.js.map +1 -0
- package/dist/utils/child-process.d.ts +18 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +106 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/clipboard-command.d.ts +7 -0
- package/dist/utils/clipboard-command.d.ts.map +1 -0
- package/dist/utils/clipboard-command.js +45 -0
- package/dist/utils/clipboard-command.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts +11 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -0
- package/dist/utils/clipboard-image.js +228 -0
- package/dist/utils/clipboard-image.js.map +1 -0
- package/dist/utils/clipboard.d.ts +4 -0
- package/dist/utils/clipboard.d.ts.map +1 -0
- package/dist/utils/clipboard.js +84 -0
- package/dist/utils/clipboard.js.map +1 -0
- package/dist/utils/deprecation.d.ts +4 -0
- package/dist/utils/deprecation.d.ts.map +1 -0
- package/dist/utils/deprecation.js +13 -0
- package/dist/utils/deprecation.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 +157 -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 +27 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/fs-watch.d.ts +5 -0
- package/dist/utils/fs-watch.d.ts.map +1 -0
- package/dist/utils/fs-watch.js +25 -0
- package/dist/utils/fs-watch.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 +195 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/html.d.ts +7 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +40 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/image-convert.d.ts +10 -0
- package/dist/utils/image-convert.d.ts.map +1 -0
- package/dist/utils/image-convert.js +45 -0
- package/dist/utils/image-convert.js.map +1 -0
- package/dist/utils/image-process.d.ts +18 -0
- package/dist/utils/image-process.d.ts.map +1 -0
- package/dist/utils/image-process.js +83 -0
- package/dist/utils/image-process.js.map +1 -0
- package/dist/utils/image-resize-core.d.ts +30 -0
- package/dist/utils/image-resize-core.d.ts.map +1 -0
- package/dist/utils/image-resize-core.js +124 -0
- package/dist/utils/image-resize-core.js.map +1 -0
- package/dist/utils/image-resize-worker.d.ts +2 -0
- package/dist/utils/image-resize-worker.d.ts.map +1 -0
- package/dist/utils/image-resize-worker.js +31 -0
- package/dist/utils/image-resize-worker.js.map +1 -0
- package/dist/utils/image-resize.d.ts +16 -0
- package/dist/utils/image-resize.d.ts.map +1 -0
- package/dist/utils/image-resize.js +97 -0
- package/dist/utils/image-resize.js.map +1 -0
- package/dist/utils/ion-user-agent.d.ts +2 -0
- package/dist/utils/ion-user-agent.d.ts.map +1 -0
- package/dist/utils/ion-user-agent.js +5 -0
- package/dist/utils/ion-user-agent.js.map +1 -0
- package/dist/utils/json.d.ts +3 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +7 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/management-http.d.ts +25 -0
- package/dist/utils/management-http.d.ts.map +1 -0
- package/dist/utils/management-http.js +54 -0
- package/dist/utils/management-http.js.map +1 -0
- package/dist/utils/mime.d.ts +3 -0
- package/dist/utils/mime.d.ts.map +1 -0
- package/dist/utils/mime.js +110 -0
- package/dist/utils/mime.js.map +1 -0
- package/dist/utils/open-browser.d.ts +9 -0
- package/dist/utils/open-browser.d.ts.map +1 -0
- package/dist/utils/open-browser.js +22 -0
- package/dist/utils/open-browser.js.map +1 -0
- package/dist/utils/paths.d.ts +34 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +114 -0
- package/dist/utils/paths.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 +34 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +216 -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/syntax-highlight.d.ts +13 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -0
- package/dist/utils/syntax-highlight.js +177 -0
- package/dist/utils/syntax-highlight.js.map +1 -0
- package/dist/utils/text.d.ts +8 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +9 -0
- package/dist/utils/text.js.map +1 -0
- package/dist/utils/tool-result-images.d.ts +19 -0
- package/dist/utils/tool-result-images.d.ts.map +1 -0
- package/dist/utils/tool-result-images.js +45 -0
- package/dist/utils/tool-result-images.js.map +1 -0
- package/dist/utils/tools-manager.d.ts +19 -0
- package/dist/utils/tools-manager.d.ts.map +1 -0
- package/dist/utils/tools-manager.js +382 -0
- package/dist/utils/tools-manager.js.map +1 -0
- package/dist/utils/version-check.d.ts +19 -0
- package/dist/utils/version-check.d.ts.map +1 -0
- package/dist/utils/version-check.js +79 -0
- package/dist/utils/version-check.js.map +1 -0
- package/dist/utils/windows-self-update.d.ts +3 -0
- package/dist/utils/windows-self-update.d.ts.map +1 -0
- package/dist/utils/windows-self-update.js +77 -0
- package/dist/utils/windows-self-update.js.map +1 -0
- package/docs/browser-extension.md +108 -0
- package/docs/compaction.md +444 -0
- package/docs/containerization.md +156 -0
- package/docs/custom-provider.md +777 -0
- package/docs/development.md +90 -0
- package/docs/docs.json +164 -0
- package/docs/environment-variables.md +101 -0
- package/docs/extensions.md +3033 -0
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/exy.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/index.md +85 -0
- package/docs/json.md +98 -0
- package/docs/keybindings.md +239 -0
- package/docs/llama-cpp.md +101 -0
- package/docs/models.md +574 -0
- package/docs/packages.md +228 -0
- package/docs/prompt-templates.md +96 -0
- package/docs/providers.md +321 -0
- package/docs/quickstart.md +168 -0
- package/docs/rpc.md +1618 -0
- package/docs/sdk.md +1226 -0
- package/docs/security.md +59 -0
- package/docs/session-format.md +450 -0
- package/docs/sessions.md +145 -0
- package/docs/settings.md +408 -0
- package/docs/shell-aliases.md +13 -0
- package/docs/skills.md +241 -0
- package/docs/terminal-setup.md +192 -0
- package/docs/termux.md +126 -0
- package/docs/themes.md +322 -0
- package/docs/tmux.md +63 -0
- package/docs/tui.md +961 -0
- package/docs/usage.md +327 -0
- package/docs/webfetch.md +119 -0
- package/docs/windows.md +39 -0
- package/examples/README.md +28 -0
- package/examples/extensions/README.md +213 -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/border-status-editor.ts +150 -0
- package/examples/extensions/built-in-tool-renderer.ts +249 -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 +117 -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 +611 -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 +405 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/dirty-repo-guard.ts +56 -0
- package/examples/extensions/doom-overlay/README.md +46 -0
- package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
- package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
- package/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
- package/examples/extensions/doom-overlay/doom-component.ts +132 -0
- package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
- package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
- package/examples/extensions/doom-overlay/index.ts +74 -0
- package/examples/extensions/doom-overlay/wad-finder.ts +55 -0
- package/examples/extensions/dynamic-resources/SKILL.md +8 -0
- package/examples/extensions/dynamic-resources/dynamic.json +81 -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/entry-renderer.ts +41 -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/git-merge-and-resolve.ts +115 -0
- package/examples/extensions/github-issue-autocomplete.ts +185 -0
- package/examples/extensions/gondolin/index.ts +531 -0
- package/examples/extensions/gondolin/package-lock.json +185 -0
- package/examples/extensions/gondolin/package.json +19 -0
- package/examples/extensions/handoff.ts +190 -0
- package/examples/extensions/hello.ts +26 -0
- package/examples/extensions/hidden-thinking-label.ts +53 -0
- package/examples/extensions/inline-bash.ts +94 -0
- package/examples/extensions/input-transform-streaming.ts +39 -0
- package/examples/extensions/input-transform.ts +43 -0
- package/examples/extensions/interactive-shell.ts +196 -0
- package/examples/extensions/kimi-deferred-tools.ts +61 -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 +57 -0
- package/examples/extensions/overlay-qa-tests.ts +1450 -0
- package/examples/extensions/overlay-test.ts +153 -0
- package/examples/extensions/permission-gate.ts +34 -0
- package/examples/extensions/pirate.ts +47 -0
- package/examples/extensions/plan-mode/README.md +66 -0
- package/examples/extensions/plan-mode/index.ts +390 -0
- package/examples/extensions/plan-mode/utils.ts +168 -0
- package/examples/extensions/preset.ts +436 -0
- package/examples/extensions/project-trust.ts +64 -0
- package/examples/extensions/prompt-customizer.ts +97 -0
- package/examples/extensions/protected-paths.ts +30 -0
- package/examples/extensions/provider-payload.ts +18 -0
- package/examples/extensions/qna.ts +118 -0
- package/examples/extensions/question.ts +278 -0
- package/examples/extensions/questionnaire.ts +440 -0
- package/examples/extensions/rainbow-editor.ts +88 -0
- package/examples/extensions/reload-runtime.ts +37 -0
- package/examples/extensions/rpc-demo.ts +118 -0
- package/examples/extensions/sandbox/index.ts +321 -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 +32 -0
- package/examples/extensions/structured-output.ts +65 -0
- package/examples/extensions/subagent/README.md +177 -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 +157 -0
- package/examples/extensions/subagent/index.ts +1038 -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 +199 -0
- package/examples/extensions/system-prompt-header.ts +17 -0
- package/examples/extensions/tic-tac-toe.ts +1008 -0
- package/examples/extensions/timed-confirm.ts +70 -0
- package/examples/extensions/titlebar-spinner.ts +58 -0
- package/examples/extensions/todo.ts +297 -0
- package/examples/extensions/tool-override.ts +144 -0
- package/examples/extensions/tools.ts +146 -0
- package/examples/extensions/trigger-compact.ts +50 -0
- package/examples/extensions/truncated-tool.ts +195 -0
- package/examples/extensions/widget-placement.ts +9 -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/extensions/working-indicator.ts +123 -0
- package/examples/extensions/working-message-test.ts +25 -0
- package/examples/plugins/ion-example-plugin/README.md +38 -0
- package/examples/plugins/ion-example-plugin/package.json +10 -0
- package/examples/plugins/ion-example-plugin/src/contract.ts +13 -0
- package/examples/plugins/ion-example-plugin/src/session.ts +23 -0
- package/examples/plugins/ion-example-plugin/src/tui.ts +31 -0
- package/examples/rpc-extension-ui.ts +641 -0
- package/examples/sdk/01-minimal.ts +26 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +70 -0
- package/examples/sdk/04-skills.ts +55 -0
- package/examples/sdk/05-tools.ts +48 -0
- package/examples/sdk/06-extensions.ts +94 -0
- package/examples/sdk/07-context-files.ts +42 -0
- package/examples/sdk/08-prompt-templates.ts +51 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +34 -0
- package/examples/sdk/10-settings.ts +53 -0
- package/examples/sdk/11-sessions.ts +52 -0
- package/examples/sdk/12-full-control.ts +74 -0
- package/examples/sdk/13-session-runtime.ts +67 -0
- package/examples/sdk/README.md +140 -0
- package/npm-shrinkwrap.json +1912 -0
- package/package.json +108 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webextract.d.ts","sourceRoot":"","sources":["../../../src/core/tools/webextract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAoB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAO/E,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAE/E,QAAA,MAAM,gBAAgB;;;;;EASpB,CAAC;AAEH,eAAO,MAAM,sCAAsC;;;CAKzC,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB;CAAG;AAkBrE,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjG,MAAM,CAaR;AAED,wBAAgB,8BAA8B,CAC7C,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,qBAAqB,GAC7B,cAAc,CAAC,OAAO,gBAAgB,EAAE,qBAAqB,CAAC,CAsGhE;AAED,wBAAgB,oBAAoB,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,qBAAqB,GAC7B,SAAS,CAAC,OAAO,gBAAgB,CAAC,CAEpC","sourcesContent":["import type { AgentTool } from \"@m4ike1/ion-agent-core\";\nimport { type Static, Type } from \"typebox\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\nimport type { WebDocument } from \"../webfetch/backend.ts\";\nimport { isFallbackEligible } from \"../webfetch/backend-firecrawl.ts\";\nimport { WEBFETCH_DEFAULT_WINDOW_CHARS, WebDocumentStore } from \"../webfetch/doc-store.ts\";\nimport { WebfetchError } from \"../webfetch/guardrails.ts\";\nimport { webextractRenderers } from \"./renderers/webfetch.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { resolveFetchBackends, type WebfetchToolOptions } from \"./webfetch.ts\";\n\nconst webextractSchema = Type.Object({\n\tref: Type.Optional(\n\t\tType.String({ description: \"web:// reference from a webfetch result or earlier webextract call\" }),\n\t),\n\turl: Type.Optional(Type.String({ description: \"Page URL to fetch directly (exactly one of ref or url)\" })),\n\toffsetChars: Type.Optional(Type.Number({ description: \"Character offset into the document (default 0)\" })),\n\tlengthChars: Type.Optional(\n\t\tType.Number({ description: `Characters to return (default ${WEBFETCH_DEFAULT_WINDOW_CHARS})` }),\n\t),\n});\n\nexport const webextractToolSystemPromptContribution = {\n\tsnippet: \"Read full page text from a web:// ref or URL (windowed)\",\n\tguidelines: [\n\t\t\"Use webextract to read webfetch results: it pages large documents with offsetChars/lengthChars instead of dumping whole pages\",\n\t],\n} as const;\n\nexport type WebextractToolInput = Static<typeof webextractSchema>;\n\nexport interface WebextractToolDetails {\n\tref: string;\n\ttotalChars: number;\n\toffsetChars: number;\n\tlengthChars: number;\n\tsource: \"firecrawl\" | \"undici\";\n\tfallbackNotice?: string;\n}\n\nexport interface WebextractToolOptions extends WebfetchToolOptions {}\n\nfunction validatedWindow(\n\toffsetChars: number | undefined,\n\tlengthChars: number | undefined,\n): {\n\toffsetChars: number;\n\tlengthChars: number;\n} {\n\tif (offsetChars !== undefined && (!Number.isFinite(offsetChars) || offsetChars < 0)) {\n\t\tthrow new Error(\"offsetChars must be a non-negative number\");\n\t}\n\tif (lengthChars !== undefined && (!Number.isFinite(lengthChars) || lengthChars <= 0)) {\n\t\tthrow new Error(\"lengthChars must be a positive number\");\n\t}\n\treturn { offsetChars: offsetChars ?? 0, lengthChars: lengthChars ?? WEBFETCH_DEFAULT_WINDOW_CHARS };\n}\n\nexport function formatExtractWindow(\n\ttitle: string,\n\turl: string,\n\twindow: { ref: string; totalChars: number; offsetChars: number; lengthChars: number; text: string },\n): string {\n\tconst end = window.offsetChars + window.lengthChars;\n\tconst lines = [\n\t\ttitle,\n\t\t`${url} (${window.ref})`,\n\t\t`[chars ${window.offsetChars}-${end} of ${window.totalChars}]`,\n\t\t\"\",\n\t\twindow.text,\n\t];\n\tif (end < window.totalChars) {\n\t\tlines.push(\"\", `[Use offsetChars=${end} to continue.]`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nexport function createWebextractToolDefinition(\n\t_cwd: string,\n\toptions?: WebextractToolOptions,\n): ToolDefinition<typeof webextractSchema, WebextractToolDetails> {\n\tconst { primary, fallback } = resolveFetchBackends(options);\n\tconst store = options?.store ?? new WebDocumentStore();\n\n\tasync function fetchDocument(\n\t\turl: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<{\n\t\tdoc: WebDocument;\n\t\tsource: \"firecrawl\" | \"undici\";\n\t\tfallbackNotice?: string;\n\t}> {\n\t\ttry {\n\t\t\tconst doc = await primary.fetch(url, { signal });\n\t\t\treturn { doc, source: primary.id };\n\t\t} catch (error) {\n\t\t\tif (!isFallbackEligible(error)) throw error;\n\t\t\t// The keyless-unavailable message is a multi-line remediation hint; keep the\n\t\t\t// per-page notice short and point at the full guidance instead.\n\t\t\tconst reason =\n\t\t\t\terror instanceof WebfetchError && error.code === \"unavailable\"\n\t\t\t\t\t? \"keyless tier refused this network; set firecrawlApiKey or FIRECRAWL_API_KEY\"\n\t\t\t\t\t: error instanceof Error\n\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t: String(error);\n\t\t\tconst doc = await fallback.fetch(url, { signal });\n\t\t\treturn { doc, source: fallback.id, fallbackNotice: `Firecrawl unavailable (${reason}); used direct fetch.` };\n\t\t}\n\t}\n\n\treturn {\n\t\tname: \"webextract\",\n\t\tlabel: \"webextract\",\n\t\tdescription: `Read the full text of a fetched web page, windowed by character offset so large pages never flood context. Provide exactly one of ref (a web:// reference from webfetch) or url (fetched on demand through Firecrawl with direct-fetch fallback). First read of a search-result ref fetches the page; later reads page from the stored document.`,\n\t\tpromptSnippet: webextractToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...webextractToolSystemPromptContribution.guidelines],\n\t\tparameters: webextractSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{\n\t\t\t\tref,\n\t\t\t\turl,\n\t\t\t\toffsetChars,\n\t\t\t\tlengthChars,\n\t\t\t}: { ref?: string; url?: string; offsetChars?: number; lengthChars?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\t_ctx?: ExtensionContext,\n\t\t) {\n\t\t\tif ((ref === undefined) === (url === undefined)) {\n\t\t\t\tthrow new Error(\"Provide exactly one of ref or url\");\n\t\t\t}\n\t\t\tconst window = validatedWindow(offsetChars, lengthChars);\n\t\t\tlet effectiveRef = ref;\n\t\t\tlet source: \"firecrawl\" | \"undici\" | undefined;\n\t\t\tlet fallbackNotice: string | undefined;\n\t\t\tif (url !== undefined) {\n\t\t\t\tif (!url.trim()) {\n\t\t\t\t\tthrow new Error(\"URL must not be empty\");\n\t\t\t\t}\n\t\t\t\tconst fetched = await fetchDocument(url, signal);\n\t\t\t\tsource = fetched.source;\n\t\t\t\tfallbackNotice = fetched.fallbackNotice;\n\t\t\t\teffectiveRef = store.store(fetched.doc, fetched.source);\n\t\t\t} else {\n\t\t\t\tconst stored = store.get(effectiveRef as string);\n\t\t\t\tif (!stored) {\n\t\t\t\t\tthrow new Error(`Unknown web reference: ${effectiveRef}`);\n\t\t\t\t}\n\t\t\t\tsource = stored.source;\n\t\t\t\tif (!stored.complete) {\n\t\t\t\t\tconst fetched = await fetchDocument(stored.doc.url, signal);\n\t\t\t\t\tstore.update(stored.ref, fetched.doc, fetched.source);\n\t\t\t\t\tsource = fetched.source;\n\t\t\t\t\tfallbackNotice = fetched.fallbackNotice;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst stored = store.get(effectiveRef as string);\n\t\t\tif (!stored) {\n\t\t\t\tthrow new Error(`Unknown web reference: ${effectiveRef}`);\n\t\t\t}\n\t\t\tif (window.offsetChars > stored.doc.markdown.length) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Offset ${window.offsetChars} is beyond end of document (${stored.doc.markdown.length} chars total)`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst extracted = store.extract(stored.ref, window);\n\t\t\tconst details: WebextractToolDetails = {\n\t\t\t\tref: stored.ref,\n\t\t\t\ttotalChars: extracted.totalChars,\n\t\t\t\toffsetChars: extracted.offsetChars,\n\t\t\t\tlengthChars: extracted.lengthChars,\n\t\t\t\tsource,\n\t\t\t};\n\t\t\tif (fallbackNotice !== undefined) details.fallbackNotice = fallbackNotice;\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: formatExtractWindow(stored.doc.title, stored.doc.url, extracted) }],\n\t\t\t\tdetails,\n\t\t\t};\n\t\t},\n\t\t...webextractRenderers,\n\t};\n}\n\nexport function createWebextractTool(\n\t_cwd: string,\n\toptions?: WebextractToolOptions,\n): AgentTool<typeof webextractSchema> {\n\treturn wrapToolDefinition(createWebextractToolDefinition(_cwd, options));\n}\n"]}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import { isFallbackEligible } from "../webfetch/backend-firecrawl.js";
|
|
3
|
+
import { WEBFETCH_DEFAULT_WINDOW_CHARS, WebDocumentStore } from "../webfetch/doc-store.js";
|
|
4
|
+
import { WebfetchError } from "../webfetch/guardrails.js";
|
|
5
|
+
import { webextractRenderers } from "./renderers/webfetch.js";
|
|
6
|
+
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
7
|
+
import { resolveFetchBackends } from "./webfetch.js";
|
|
8
|
+
const webextractSchema = Type.Object({
|
|
9
|
+
ref: Type.Optional(Type.String({ description: "web:// reference from a webfetch result or earlier webextract call" })),
|
|
10
|
+
url: Type.Optional(Type.String({ description: "Page URL to fetch directly (exactly one of ref or url)" })),
|
|
11
|
+
offsetChars: Type.Optional(Type.Number({ description: "Character offset into the document (default 0)" })),
|
|
12
|
+
lengthChars: Type.Optional(Type.Number({ description: `Characters to return (default ${WEBFETCH_DEFAULT_WINDOW_CHARS})` })),
|
|
13
|
+
});
|
|
14
|
+
export const webextractToolSystemPromptContribution = {
|
|
15
|
+
snippet: "Read full page text from a web:// ref or URL (windowed)",
|
|
16
|
+
guidelines: [
|
|
17
|
+
"Use webextract to read webfetch results: it pages large documents with offsetChars/lengthChars instead of dumping whole pages",
|
|
18
|
+
],
|
|
19
|
+
};
|
|
20
|
+
function validatedWindow(offsetChars, lengthChars) {
|
|
21
|
+
if (offsetChars !== undefined && (!Number.isFinite(offsetChars) || offsetChars < 0)) {
|
|
22
|
+
throw new Error("offsetChars must be a non-negative number");
|
|
23
|
+
}
|
|
24
|
+
if (lengthChars !== undefined && (!Number.isFinite(lengthChars) || lengthChars <= 0)) {
|
|
25
|
+
throw new Error("lengthChars must be a positive number");
|
|
26
|
+
}
|
|
27
|
+
return { offsetChars: offsetChars ?? 0, lengthChars: lengthChars ?? WEBFETCH_DEFAULT_WINDOW_CHARS };
|
|
28
|
+
}
|
|
29
|
+
export function formatExtractWindow(title, url, window) {
|
|
30
|
+
const end = window.offsetChars + window.lengthChars;
|
|
31
|
+
const lines = [
|
|
32
|
+
title,
|
|
33
|
+
`${url} (${window.ref})`,
|
|
34
|
+
`[chars ${window.offsetChars}-${end} of ${window.totalChars}]`,
|
|
35
|
+
"",
|
|
36
|
+
window.text,
|
|
37
|
+
];
|
|
38
|
+
if (end < window.totalChars) {
|
|
39
|
+
lines.push("", `[Use offsetChars=${end} to continue.]`);
|
|
40
|
+
}
|
|
41
|
+
return lines.join("\n");
|
|
42
|
+
}
|
|
43
|
+
export function createWebextractToolDefinition(_cwd, options) {
|
|
44
|
+
const { primary, fallback } = resolveFetchBackends(options);
|
|
45
|
+
const store = options?.store ?? new WebDocumentStore();
|
|
46
|
+
async function fetchDocument(url, signal) {
|
|
47
|
+
try {
|
|
48
|
+
const doc = await primary.fetch(url, { signal });
|
|
49
|
+
return { doc, source: primary.id };
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (!isFallbackEligible(error))
|
|
53
|
+
throw error;
|
|
54
|
+
// The keyless-unavailable message is a multi-line remediation hint; keep the
|
|
55
|
+
// per-page notice short and point at the full guidance instead.
|
|
56
|
+
const reason = error instanceof WebfetchError && error.code === "unavailable"
|
|
57
|
+
? "keyless tier refused this network; set firecrawlApiKey or FIRECRAWL_API_KEY"
|
|
58
|
+
: error instanceof Error
|
|
59
|
+
? error.message
|
|
60
|
+
: String(error);
|
|
61
|
+
const doc = await fallback.fetch(url, { signal });
|
|
62
|
+
return { doc, source: fallback.id, fallbackNotice: `Firecrawl unavailable (${reason}); used direct fetch.` };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
name: "webextract",
|
|
67
|
+
label: "webextract",
|
|
68
|
+
description: `Read the full text of a fetched web page, windowed by character offset so large pages never flood context. Provide exactly one of ref (a web:// reference from webfetch) or url (fetched on demand through Firecrawl with direct-fetch fallback). First read of a search-result ref fetches the page; later reads page from the stored document.`,
|
|
69
|
+
promptSnippet: webextractToolSystemPromptContribution.snippet,
|
|
70
|
+
promptGuidelines: [...webextractToolSystemPromptContribution.guidelines],
|
|
71
|
+
parameters: webextractSchema,
|
|
72
|
+
async execute(_toolCallId, { ref, url, offsetChars, lengthChars, }, signal, _onUpdate, _ctx) {
|
|
73
|
+
if ((ref === undefined) === (url === undefined)) {
|
|
74
|
+
throw new Error("Provide exactly one of ref or url");
|
|
75
|
+
}
|
|
76
|
+
const window = validatedWindow(offsetChars, lengthChars);
|
|
77
|
+
let effectiveRef = ref;
|
|
78
|
+
let source;
|
|
79
|
+
let fallbackNotice;
|
|
80
|
+
if (url !== undefined) {
|
|
81
|
+
if (!url.trim()) {
|
|
82
|
+
throw new Error("URL must not be empty");
|
|
83
|
+
}
|
|
84
|
+
const fetched = await fetchDocument(url, signal);
|
|
85
|
+
source = fetched.source;
|
|
86
|
+
fallbackNotice = fetched.fallbackNotice;
|
|
87
|
+
effectiveRef = store.store(fetched.doc, fetched.source);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const stored = store.get(effectiveRef);
|
|
91
|
+
if (!stored) {
|
|
92
|
+
throw new Error(`Unknown web reference: ${effectiveRef}`);
|
|
93
|
+
}
|
|
94
|
+
source = stored.source;
|
|
95
|
+
if (!stored.complete) {
|
|
96
|
+
const fetched = await fetchDocument(stored.doc.url, signal);
|
|
97
|
+
store.update(stored.ref, fetched.doc, fetched.source);
|
|
98
|
+
source = fetched.source;
|
|
99
|
+
fallbackNotice = fetched.fallbackNotice;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const stored = store.get(effectiveRef);
|
|
103
|
+
if (!stored) {
|
|
104
|
+
throw new Error(`Unknown web reference: ${effectiveRef}`);
|
|
105
|
+
}
|
|
106
|
+
if (window.offsetChars > stored.doc.markdown.length) {
|
|
107
|
+
throw new Error(`Offset ${window.offsetChars} is beyond end of document (${stored.doc.markdown.length} chars total)`);
|
|
108
|
+
}
|
|
109
|
+
const extracted = store.extract(stored.ref, window);
|
|
110
|
+
const details = {
|
|
111
|
+
ref: stored.ref,
|
|
112
|
+
totalChars: extracted.totalChars,
|
|
113
|
+
offsetChars: extracted.offsetChars,
|
|
114
|
+
lengthChars: extracted.lengthChars,
|
|
115
|
+
source,
|
|
116
|
+
};
|
|
117
|
+
if (fallbackNotice !== undefined)
|
|
118
|
+
details.fallbackNotice = fallbackNotice;
|
|
119
|
+
return {
|
|
120
|
+
content: [{ type: "text", text: formatExtractWindow(stored.doc.title, stored.doc.url, extracted) }],
|
|
121
|
+
details,
|
|
122
|
+
};
|
|
123
|
+
},
|
|
124
|
+
...webextractRenderers,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export function createWebextractTool(_cwd, options) {
|
|
128
|
+
return wrapToolDefinition(createWebextractToolDefinition(_cwd, options));
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=webextract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webextract.js","sourceRoot":"","sources":["../../../src/core/tools/webextract.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@m4ike1/ion-agent-core\";\nimport { type Static, Type } from \"typebox\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\nimport type { WebDocument } from \"../webfetch/backend.ts\";\nimport { isFallbackEligible } from \"../webfetch/backend-firecrawl.ts\";\nimport { WEBFETCH_DEFAULT_WINDOW_CHARS, WebDocumentStore } from \"../webfetch/doc-store.ts\";\nimport { WebfetchError } from \"../webfetch/guardrails.ts\";\nimport { webextractRenderers } from \"./renderers/webfetch.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { resolveFetchBackends, type WebfetchToolOptions } from \"./webfetch.ts\";\n\nconst webextractSchema = Type.Object({\n\tref: Type.Optional(\n\t\tType.String({ description: \"web:// reference from a webfetch result or earlier webextract call\" }),\n\t),\n\turl: Type.Optional(Type.String({ description: \"Page URL to fetch directly (exactly one of ref or url)\" })),\n\toffsetChars: Type.Optional(Type.Number({ description: \"Character offset into the document (default 0)\" })),\n\tlengthChars: Type.Optional(\n\t\tType.Number({ description: `Characters to return (default ${WEBFETCH_DEFAULT_WINDOW_CHARS})` }),\n\t),\n});\n\nexport const webextractToolSystemPromptContribution = {\n\tsnippet: \"Read full page text from a web:// ref or URL (windowed)\",\n\tguidelines: [\n\t\t\"Use webextract to read webfetch results: it pages large documents with offsetChars/lengthChars instead of dumping whole pages\",\n\t],\n} as const;\n\nexport type WebextractToolInput = Static<typeof webextractSchema>;\n\nexport interface WebextractToolDetails {\n\tref: string;\n\ttotalChars: number;\n\toffsetChars: number;\n\tlengthChars: number;\n\tsource: \"firecrawl\" | \"undici\";\n\tfallbackNotice?: string;\n}\n\nexport interface WebextractToolOptions extends WebfetchToolOptions {}\n\nfunction validatedWindow(\n\toffsetChars: number | undefined,\n\tlengthChars: number | undefined,\n): {\n\toffsetChars: number;\n\tlengthChars: number;\n} {\n\tif (offsetChars !== undefined && (!Number.isFinite(offsetChars) || offsetChars < 0)) {\n\t\tthrow new Error(\"offsetChars must be a non-negative number\");\n\t}\n\tif (lengthChars !== undefined && (!Number.isFinite(lengthChars) || lengthChars <= 0)) {\n\t\tthrow new Error(\"lengthChars must be a positive number\");\n\t}\n\treturn { offsetChars: offsetChars ?? 0, lengthChars: lengthChars ?? WEBFETCH_DEFAULT_WINDOW_CHARS };\n}\n\nexport function formatExtractWindow(\n\ttitle: string,\n\turl: string,\n\twindow: { ref: string; totalChars: number; offsetChars: number; lengthChars: number; text: string },\n): string {\n\tconst end = window.offsetChars + window.lengthChars;\n\tconst lines = [\n\t\ttitle,\n\t\t`${url} (${window.ref})`,\n\t\t`[chars ${window.offsetChars}-${end} of ${window.totalChars}]`,\n\t\t\"\",\n\t\twindow.text,\n\t];\n\tif (end < window.totalChars) {\n\t\tlines.push(\"\", `[Use offsetChars=${end} to continue.]`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nexport function createWebextractToolDefinition(\n\t_cwd: string,\n\toptions?: WebextractToolOptions,\n): ToolDefinition<typeof webextractSchema, WebextractToolDetails> {\n\tconst { primary, fallback } = resolveFetchBackends(options);\n\tconst store = options?.store ?? new WebDocumentStore();\n\n\tasync function fetchDocument(\n\t\turl: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<{\n\t\tdoc: WebDocument;\n\t\tsource: \"firecrawl\" | \"undici\";\n\t\tfallbackNotice?: string;\n\t}> {\n\t\ttry {\n\t\t\tconst doc = await primary.fetch(url, { signal });\n\t\t\treturn { doc, source: primary.id };\n\t\t} catch (error) {\n\t\t\tif (!isFallbackEligible(error)) throw error;\n\t\t\t// The keyless-unavailable message is a multi-line remediation hint; keep the\n\t\t\t// per-page notice short and point at the full guidance instead.\n\t\t\tconst reason =\n\t\t\t\terror instanceof WebfetchError && error.code === \"unavailable\"\n\t\t\t\t\t? \"keyless tier refused this network; set firecrawlApiKey or FIRECRAWL_API_KEY\"\n\t\t\t\t\t: error instanceof Error\n\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t: String(error);\n\t\t\tconst doc = await fallback.fetch(url, { signal });\n\t\t\treturn { doc, source: fallback.id, fallbackNotice: `Firecrawl unavailable (${reason}); used direct fetch.` };\n\t\t}\n\t}\n\n\treturn {\n\t\tname: \"webextract\",\n\t\tlabel: \"webextract\",\n\t\tdescription: `Read the full text of a fetched web page, windowed by character offset so large pages never flood context. Provide exactly one of ref (a web:// reference from webfetch) or url (fetched on demand through Firecrawl with direct-fetch fallback). First read of a search-result ref fetches the page; later reads page from the stored document.`,\n\t\tpromptSnippet: webextractToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...webextractToolSystemPromptContribution.guidelines],\n\t\tparameters: webextractSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{\n\t\t\t\tref,\n\t\t\t\turl,\n\t\t\t\toffsetChars,\n\t\t\t\tlengthChars,\n\t\t\t}: { ref?: string; url?: string; offsetChars?: number; lengthChars?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\t_ctx?: ExtensionContext,\n\t\t) {\n\t\t\tif ((ref === undefined) === (url === undefined)) {\n\t\t\t\tthrow new Error(\"Provide exactly one of ref or url\");\n\t\t\t}\n\t\t\tconst window = validatedWindow(offsetChars, lengthChars);\n\t\t\tlet effectiveRef = ref;\n\t\t\tlet source: \"firecrawl\" | \"undici\" | undefined;\n\t\t\tlet fallbackNotice: string | undefined;\n\t\t\tif (url !== undefined) {\n\t\t\t\tif (!url.trim()) {\n\t\t\t\t\tthrow new Error(\"URL must not be empty\");\n\t\t\t\t}\n\t\t\t\tconst fetched = await fetchDocument(url, signal);\n\t\t\t\tsource = fetched.source;\n\t\t\t\tfallbackNotice = fetched.fallbackNotice;\n\t\t\t\teffectiveRef = store.store(fetched.doc, fetched.source);\n\t\t\t} else {\n\t\t\t\tconst stored = store.get(effectiveRef as string);\n\t\t\t\tif (!stored) {\n\t\t\t\t\tthrow new Error(`Unknown web reference: ${effectiveRef}`);\n\t\t\t\t}\n\t\t\t\tsource = stored.source;\n\t\t\t\tif (!stored.complete) {\n\t\t\t\t\tconst fetched = await fetchDocument(stored.doc.url, signal);\n\t\t\t\t\tstore.update(stored.ref, fetched.doc, fetched.source);\n\t\t\t\t\tsource = fetched.source;\n\t\t\t\t\tfallbackNotice = fetched.fallbackNotice;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst stored = store.get(effectiveRef as string);\n\t\t\tif (!stored) {\n\t\t\t\tthrow new Error(`Unknown web reference: ${effectiveRef}`);\n\t\t\t}\n\t\t\tif (window.offsetChars > stored.doc.markdown.length) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Offset ${window.offsetChars} is beyond end of document (${stored.doc.markdown.length} chars total)`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst extracted = store.extract(stored.ref, window);\n\t\t\tconst details: WebextractToolDetails = {\n\t\t\t\tref: stored.ref,\n\t\t\t\ttotalChars: extracted.totalChars,\n\t\t\t\toffsetChars: extracted.offsetChars,\n\t\t\t\tlengthChars: extracted.lengthChars,\n\t\t\t\tsource,\n\t\t\t};\n\t\t\tif (fallbackNotice !== undefined) details.fallbackNotice = fallbackNotice;\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: formatExtractWindow(stored.doc.title, stored.doc.url, extracted) }],\n\t\t\t\tdetails,\n\t\t\t};\n\t\t},\n\t\t...webextractRenderers,\n\t};\n}\n\nexport function createWebextractTool(\n\t_cwd: string,\n\toptions?: WebextractToolOptions,\n): AgentTool<typeof webextractSchema> {\n\treturn wrapToolDefinition(createWebextractToolDefinition(_cwd, options));\n}\n"]}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { AgentTool } from "@m4ike1/ion-agent-core";
|
|
2
|
+
import { type Static, Type } from "typebox";
|
|
3
|
+
import type { ToolDefinition } from "../extensions/types.ts";
|
|
4
|
+
import type { WebFetchBackend, WebSearchBackend, WebSearchResult } from "../webfetch/backend.ts";
|
|
5
|
+
import { WebDocumentStore } from "../webfetch/doc-store.ts";
|
|
6
|
+
import { type ResolvedSearchIntent } from "../webfetch/search-intent.ts";
|
|
7
|
+
export type { WebDocument, WebFetchBackend, WebSearchBackend, WebSearchResult } from "../webfetch/backend.ts";
|
|
8
|
+
export { type ExtractWindow, type StoredWebDocument, WEBFETCH_DEFAULT_WINDOW_CHARS, type WebDocumentSource, WebDocumentStore, } from "../webfetch/doc-store.ts";
|
|
9
|
+
export { parseRecency, type ResolvedSearchIntent, resolveSearchIntent, SEARCH_DEFAULT_WEB_RESULTS, SEARCH_MAX_PER_SOURCE, type SearchFilters, type SearchIntent, SearchIntentError, type SearchResultCounts, totalRequestedResults, } from "../webfetch/search-intent.ts";
|
|
10
|
+
export { type ParsedSearchQuery, parseSearchQueryTags } from "../webfetch/search-tags.ts";
|
|
11
|
+
declare const webfetchSchema: Type.TObject<{
|
|
12
|
+
query: Type.TString;
|
|
13
|
+
results: Type.TOptional<Type.TObject<{
|
|
14
|
+
web: Type.TOptional<Type.TNumber>;
|
|
15
|
+
images: Type.TOptional<Type.TNumber>;
|
|
16
|
+
news: Type.TOptional<Type.TNumber>;
|
|
17
|
+
}>>;
|
|
18
|
+
filters: Type.TOptional<Type.TObject<{
|
|
19
|
+
domains: Type.TOptional<Type.TArray<Type.TString>>;
|
|
20
|
+
recency: Type.TOptional<Type.TString>;
|
|
21
|
+
language: Type.TOptional<Type.TString>;
|
|
22
|
+
}>>;
|
|
23
|
+
limit: Type.TOptional<Type.TNumber>;
|
|
24
|
+
}>;
|
|
25
|
+
export declare const webfetchToolSystemPromptContribution: {
|
|
26
|
+
readonly snippet: "Search the web (results stored as web:// refs, full text via webextract)";
|
|
27
|
+
readonly guidelines: readonly ["Use webfetch instead of curl for web research: results are stored as web:// refs, then read full text on demand with webextract instead of pasting whole pages", "Pass results/filters for structured control (per-source counts, domains, recency). Tag sugar like [images=3] [news=5] [recent=7d] works only when those args are omitted.", "Naming a source replaces the default web-only request: results={images:3} returns images only.", "Image results and recency/domain filters need Firecrawl; if it is unavailable, ask for plain web results without filters."];
|
|
28
|
+
};
|
|
29
|
+
export type WebfetchToolInput = Static<typeof webfetchSchema>;
|
|
30
|
+
export interface WebfetchToolDetails {
|
|
31
|
+
refs: string[];
|
|
32
|
+
backend: "firecrawl" | "exa" | "undici";
|
|
33
|
+
warning?: string;
|
|
34
|
+
creditsUsed?: number;
|
|
35
|
+
/** Set when an earlier backend in the chain failed and a later one answered. */
|
|
36
|
+
backendNotice?: string;
|
|
37
|
+
/** Per-source counts actually requested after tag sugar and clamping. */
|
|
38
|
+
requested?: {
|
|
39
|
+
web?: number;
|
|
40
|
+
images?: number;
|
|
41
|
+
news?: number;
|
|
42
|
+
};
|
|
43
|
+
/** Tag sugar that was recognized, e.g. `[images=3]`. */
|
|
44
|
+
appliedTags?: string[];
|
|
45
|
+
/** Tag sugar that looked like a directive but could not be applied. */
|
|
46
|
+
tagWarnings?: string[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Pluggable backends for the web tools.
|
|
50
|
+
* Override these to test without network or to front a different search provider.
|
|
51
|
+
*/
|
|
52
|
+
export interface WebOperations {
|
|
53
|
+
/** Search backend. Default: the ordered chain Firecrawl -> Exa. */
|
|
54
|
+
searchBackend?: WebSearchBackend;
|
|
55
|
+
/** Extra search backends tried after `searchBackend` fails. Default: Exa. */
|
|
56
|
+
fallbackSearchBackends?: WebSearchBackend[];
|
|
57
|
+
/** Primary fetch backend. Default: Firecrawl. */
|
|
58
|
+
fetchBackend?: WebFetchBackend;
|
|
59
|
+
/** Direct-fetch fallback used on Firecrawl transport/auth failures. Default: undici. */
|
|
60
|
+
fallbackBackend?: WebFetchBackend;
|
|
61
|
+
/** Shared session document store. Default: a fresh store per tool instance. */
|
|
62
|
+
store?: WebDocumentStore;
|
|
63
|
+
}
|
|
64
|
+
export interface WebfetchToolOptions extends WebOperations {
|
|
65
|
+
/** Firecrawl API key. Default: `FIRECRAWL_API_KEY` env. Omitted entirely when unset (keyless tier). */
|
|
66
|
+
apiKey?: string;
|
|
67
|
+
/** Exa API key. Default: `EXA_API_KEY` env. Unset uses the keyless hosted MCP search tier. */
|
|
68
|
+
exaApiKey?: string;
|
|
69
|
+
}
|
|
70
|
+
export declare function resolveWebApiKey(explicitApiKey?: string): string | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Build the search intent from the structured arguments, falling back to tag
|
|
73
|
+
* sugar in the query when `results`/`filters` are absent. An explicit structured
|
|
74
|
+
* call always wins; sugar is only a convenience for terse queries.
|
|
75
|
+
*/
|
|
76
|
+
export declare function buildSearchIntent(input: {
|
|
77
|
+
query: string;
|
|
78
|
+
results?: {
|
|
79
|
+
web?: number;
|
|
80
|
+
images?: number;
|
|
81
|
+
news?: number;
|
|
82
|
+
};
|
|
83
|
+
filters?: {
|
|
84
|
+
domains?: string[];
|
|
85
|
+
recency?: string;
|
|
86
|
+
language?: string;
|
|
87
|
+
};
|
|
88
|
+
limit?: number;
|
|
89
|
+
}): {
|
|
90
|
+
intent: ResolvedSearchIntent;
|
|
91
|
+
appliedTags: string[];
|
|
92
|
+
warnings: string[];
|
|
93
|
+
};
|
|
94
|
+
export declare function formatSearchResults(query: string, hits: Array<{
|
|
95
|
+
result: WebSearchResult;
|
|
96
|
+
ref: string;
|
|
97
|
+
}>): string;
|
|
98
|
+
export declare function createWebfetchToolDefinition(_cwd: string, options?: WebfetchToolOptions): ToolDefinition<typeof webfetchSchema, WebfetchToolDetails>;
|
|
99
|
+
export declare function resolveFetchBackends(options?: WebfetchToolOptions): {
|
|
100
|
+
primary: WebFetchBackend;
|
|
101
|
+
fallback: WebFetchBackend;
|
|
102
|
+
};
|
|
103
|
+
export declare function createWebfetchTool(_cwd: string, options?: WebfetchToolOptions): AgentTool<typeof webfetchSchema>;
|
|
104
|
+
//# sourceMappingURL=webfetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webfetch.d.ts","sourceRoot":"","sources":["../../../src/core/tools/webfetch.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@m4ike1/ion-agent-core\";\nimport { type Static, Type } from \"typebox\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\nimport type { WebDocument, WebFetchBackend, WebSearchBackend, WebSearchResult } from \"../webfetch/backend.ts\";\nimport { createExaBackend, isExaFallbackEligible, resolveExaApiKey } from \"../webfetch/backend-exa.ts\";\nimport {\n\tcreateFirecrawlBackend,\n\ttype FirecrawlBackend,\n\tisFallbackEligible,\n\tresolveFirecrawlApiKey,\n} from \"../webfetch/backend-firecrawl.ts\";\nimport { createUndiciBackend } from \"../webfetch/backend-undici.ts\";\nimport { WebDocumentStore } from \"../webfetch/doc-store.ts\";\nimport { WebfetchError } from \"../webfetch/guardrails.ts\";\nimport { type ResolvedSearchIntent, resolveSearchIntent, totalRequestedResults } from \"../webfetch/search-intent.ts\";\nimport { parseSearchQueryTags } from \"../webfetch/search-tags.ts\";\nimport { webfetchRenderers } from \"./renderers/webfetch.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nexport type { WebDocument, WebFetchBackend, WebSearchBackend, WebSearchResult } from \"../webfetch/backend.ts\";\nexport {\n\ttype ExtractWindow,\n\ttype StoredWebDocument,\n\tWEBFETCH_DEFAULT_WINDOW_CHARS,\n\ttype WebDocumentSource,\n\tWebDocumentStore,\n} from \"../webfetch/doc-store.ts\";\nexport {\n\tparseRecency,\n\ttype ResolvedSearchIntent,\n\tresolveSearchIntent,\n\tSEARCH_DEFAULT_WEB_RESULTS,\n\tSEARCH_MAX_PER_SOURCE,\n\ttype SearchFilters,\n\ttype SearchIntent,\n\tSearchIntentError,\n\ttype SearchResultCounts,\n\ttotalRequestedResults,\n} from \"../webfetch/search-intent.ts\";\nexport { type ParsedSearchQuery, parseSearchQueryTags } from \"../webfetch/search-tags.ts\";\n\nconst resultCountsSchema = Type.Object({\n\tweb: Type.Optional(Type.Number({ description: \"Web page results (1-100, default 5 when results is omitted)\" })),\n\timages: Type.Optional(Type.Number({ description: \"Image results (1-100); Firecrawl only\" })),\n\tnews: Type.Optional(Type.Number({ description: \"News results (1-100)\" })),\n});\n\nconst searchFiltersSchema = Type.Object({\n\tdomains: Type.Optional(\n\t\tType.Array(Type.String(), { description: \"Restrict results to these domains or domain prefixes\" }),\n\t),\n\trecency: Type.Optional(Type.String({ description: \"Maximum result age, e.g. 24h, 7d, 2w, 1m\" })),\n\tlanguage: Type.Optional(Type.String({ description: \"Two-letter language/country hint\" })),\n});\n\nconst webfetchSchema = Type.Object({\n\tquery: Type.String({\n\t\tdescription:\n\t\t\t\"Web search query. Tag sugar is accepted when the structured args below are omitted: [images=3] [news=5] [recent=7d] [domains=openai.com] [img] your query\",\n\t}),\n\tresults: Type.Optional(resultCountsSchema),\n\tfilters: Type.Optional(searchFiltersSchema),\n\tlimit: Type.Optional(Type.Number({ description: \"Cap on total results across all sources (1-100)\" })),\n});\n\nexport const webfetchToolSystemPromptContribution = {\n\tsnippet: \"Search the web (results stored as web:// refs, full text via webextract)\",\n\tguidelines: [\n\t\t\"Use webfetch instead of curl for web research: results are stored as web:// refs, then read full text on demand with webextract instead of pasting whole pages\",\n\t\t\"Pass results/filters for structured control (per-source counts, domains, recency). Tag sugar like [images=3] [news=5] [recent=7d] works only when those args are omitted.\",\n\t\t\"Naming a source replaces the default web-only request: results={images:3} returns images only.\",\n\t\t\"Image results and recency/domain filters need Firecrawl; if it is unavailable, ask for plain web results without filters.\",\n\t],\n} as const;\n\nexport type WebfetchToolInput = Static<typeof webfetchSchema>;\n\nconst DEFAULT_LIMIT = 5;\nconst MAX_LIMIT = 100;\n\nexport interface WebfetchToolDetails {\n\trefs: string[];\n\tbackend: \"firecrawl\" | \"exa\" | \"undici\";\n\twarning?: string;\n\tcreditsUsed?: number;\n\t/** Set when an earlier backend in the chain failed and a later one answered. */\n\tbackendNotice?: string;\n\t/** Per-source counts actually requested after tag sugar and clamping. */\n\trequested?: { web?: number; images?: number; news?: number };\n\t/** Tag sugar that was recognized, e.g. `[images=3]`. */\n\tappliedTags?: string[];\n\t/** Tag sugar that looked like a directive but could not be applied. */\n\ttagWarnings?: string[];\n}\n\n/**\n * Pluggable backends for the web tools.\n * Override these to test without network or to front a different search provider.\n */\nexport interface WebOperations {\n\t/** Search backend. Default: the ordered chain Firecrawl -> Exa. */\n\tsearchBackend?: WebSearchBackend;\n\t/** Extra search backends tried after `searchBackend` fails. Default: Exa. */\n\tfallbackSearchBackends?: WebSearchBackend[];\n\t/** Primary fetch backend. Default: Firecrawl. */\n\tfetchBackend?: WebFetchBackend;\n\t/** Direct-fetch fallback used on Firecrawl transport/auth failures. Default: undici. */\n\tfallbackBackend?: WebFetchBackend;\n\t/** Shared session document store. Default: a fresh store per tool instance. */\n\tstore?: WebDocumentStore;\n}\n\nexport interface WebfetchToolOptions extends WebOperations {\n\t/** Firecrawl API key. Default: `FIRECRAWL_API_KEY` env. Omitted entirely when unset (keyless tier). */\n\tapiKey?: string;\n\t/** Exa API key. Default: `EXA_API_KEY` env. Unset uses the keyless hosted MCP search tier. */\n\texaApiKey?: string;\n}\n\nexport function resolveWebApiKey(explicitApiKey?: string): string | undefined {\n\treturn resolveFirecrawlApiKey(explicitApiKey);\n}\n\nfunction clampToolLimit(limit: number | undefined): number {\n\tif (limit === undefined || !Number.isFinite(limit)) return DEFAULT_LIMIT;\n\treturn Math.min(MAX_LIMIT, Math.max(1, Math.floor(limit)));\n}\n\nfunction resolveSearchBackends(options?: WebfetchToolOptions): WebSearchBackend[] {\n\tif (options?.searchBackend) {\n\t\treturn [options.searchBackend, ...(options.fallbackSearchBackends ?? [])];\n\t}\n\treturn [\n\t\tcreateFirecrawlBackend({ apiKey: resolveWebApiKey(options?.apiKey) }),\n\t\tcreateExaBackend({ apiKey: resolveExaApiKey(options?.exaApiKey) }),\n\t];\n}\n\n/**\n * A search backend is skipped for auth/quota/transport/timeout/empty failures\n * and keyless-tier refusals. The `unavailable` code is matched structurally so a\n * backend compiled in a different module graph still counts.\n */\nfunction isSearchFallbackEligible(error: unknown): boolean {\n\tif (isFallbackEligible(error) || isExaFallbackEligible(error)) return true;\n\treturn error instanceof Error && \"code\" in error && (error as { code?: unknown }).code === \"unavailable\";\n}\n\n/**\n * Try each search backend in order. A backend is only skipped when it reports a\n * fallback-eligible failure — a bad request still surfaces, and results are\n * never merged across backends.\n */\nasync function searchWithFallback(\n\tbackends: WebSearchBackend[],\n\tintent: ResolvedSearchIntent,\n\tsearchOptions: { limit: number; signal?: AbortSignal },\n): Promise<{ backend: WebSearchBackend; results: WebSearchResult[]; skipped: string[] }> {\n\tconst skipped: string[] = [];\n\tlet lastError: unknown;\n\tfor (const backend of backends) {\n\t\ttry {\n\t\t\tconst results = await backend.search(intent, searchOptions);\n\t\t\treturn { backend, results, skipped };\n\t\t} catch (error) {\n\t\t\tif (!isSearchFallbackEligible(error)) throw error;\n\t\t\tlastError = error;\n\t\t\tskipped.push(`${backend.id}: ${error instanceof Error ? error.message : String(error)}`);\n\t\t}\n\t}\n\tthrow lastError instanceof Error\n\t\t? lastError\n\t\t: new WebfetchError(\"No web search backend is available\", \"unavailable\");\n}\n\n/**\n * Build the search intent from the structured arguments, falling back to tag\n * sugar in the query when `results`/`filters` are absent. An explicit structured\n * call always wins; sugar is only a convenience for terse queries.\n */\nexport function buildSearchIntent(input: {\n\tquery: string;\n\tresults?: { web?: number; images?: number; news?: number };\n\tfilters?: { domains?: string[]; recency?: string; language?: string };\n\tlimit?: number;\n}): { intent: ResolvedSearchIntent; appliedTags: string[]; warnings: string[] } {\n\tconst structured = input.results !== undefined || input.filters !== undefined;\n\tlet query = input.query;\n\tlet results = input.results;\n\tlet filters = input.filters;\n\tlet appliedTags: string[] = [];\n\tlet warnings: string[] = [];\n\n\tif (!structured) {\n\t\tconst parsed = parseSearchQueryTags(input.query);\n\t\tquery = parsed.intent.query;\n\t\tresults = parsed.intent.results;\n\t\tfilters = parsed.intent.filters;\n\t\tappliedTags = parsed.appliedTags;\n\t\twarnings = parsed.warnings;\n\t}\n\n\tconst resolved = resolveSearchIntent({ query, results, filters });\n\t// `limit` is a total across sources: scale the requested counts down together\n\t// rather than truncating one modality after the backend answered.\n\tconst requestedTotal = totalRequestedResults(resolved);\n\tif (input.limit !== undefined && Number.isFinite(input.limit) && input.limit < requestedTotal) {\n\t\tconst cap = Math.max(1, Math.floor(input.limit));\n\t\tconst scale = cap / requestedTotal;\n\t\tconst scaled: Record<string, number> = {};\n\t\tlet assigned = 0;\n\t\tconst sources = Object.keys(resolved.results) as Array<\"web\" | \"images\" | \"news\">;\n\t\tfor (const [index, source] of sources.entries()) {\n\t\t\tconst count = resolved.results[source] ?? 0;\n\t\t\tconst share =\n\t\t\t\tindex === sources.length - 1 ? Math.max(0, cap - assigned) : Math.max(1, Math.floor(count * scale));\n\t\t\tscaled[source] = Math.min(count, share);\n\t\t\tassigned += scaled[source];\n\t\t}\n\t\tresolved.results = { ...resolved.results, ...scaled };\n\t\twarnings = [...warnings, `limit ${cap} reduced the requested ${requestedTotal} results per source`];\n\t}\n\treturn { intent: resolved, appliedTags, warnings };\n}\n\nfunction readFirecrawlMeta(backend: WebSearchBackend): { warning?: string; creditsUsed?: number } {\n\tif (!(\"lastMeta\" in backend)) return {};\n\tconst meta = (backend as FirecrawlBackend).lastMeta;\n\tconst result: { warning?: string; creditsUsed?: number } = {};\n\tif (meta?.warning !== undefined) result.warning = meta.warning;\n\tif (meta?.creditsUsed !== undefined) result.creditsUsed = meta.creditsUsed;\n\treturn result;\n}\n\nexport function formatSearchResults(query: string, hits: Array<{ result: WebSearchResult; ref: string }>): string {\n\tconst lines = hits.map(\n\t\t({ result, ref }, index) =>\n\t\t\t`${index + 1}. ${result.title}\\n ${result.url} (${ref})${result.snippet ? `\\n ${result.snippet}` : \"\"}`,\n\t);\n\treturn [\n\t\t`Search results for \"${query}\":`,\n\t\t...lines,\n\t\t\"\",\n\t\t\"Full text is not included. Use webextract with a web:// ref to read a result.\",\n\t].join(\"\\n\");\n}\n\nexport function createWebfetchToolDefinition(\n\t_cwd: string,\n\toptions?: WebfetchToolOptions,\n): ToolDefinition<typeof webfetchSchema, WebfetchToolDetails> {\n\tconst backends = resolveSearchBackends(options);\n\tconst store = options?.store ?? new WebDocumentStore();\n\treturn {\n\t\tname: \"webfetch\",\n\t\tlabel: \"webfetch\",\n\t\tdescription: `Search the web for a query. Returns titles, URLs, and snippets; each web result is stored as a web:// ref for on-demand full text via webextract. Control modality and cardinality with results: {web, images, news} (counts are per source), and filters: {domains, recency, language}. Tag sugar works when those are omitted: [images=3] [news=5] [recent=7d] [domains=openai.com] [img] query. Search tries Firecrawl first (keyless tier without a key, and the only source of image results), then Exa (REST with an API key, or the keyless hosted tier) when Firecrawl is unavailable.`,\n\t\tpromptSnippet: webfetchToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...webfetchToolSystemPromptContribution.guidelines],\n\t\tparameters: webfetchSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ query, results, filters, limit }: WebfetchToolInput,\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\t_ctx?: ExtensionContext,\n\t\t) {\n\t\t\tif (!query?.trim()) {\n\t\t\t\tthrow new Error(\"Search query must not be empty\");\n\t\t\t}\n\t\t\tconst built = buildSearchIntent({ query, results, filters, limit });\n\t\t\tconst intent = built.intent;\n\t\t\tconst effectiveLimit = clampToolLimit(limit);\n\t\t\tconst {\n\t\t\t\tbackend,\n\t\t\t\tresults: hits,\n\t\t\t\tskipped,\n\t\t\t} = await searchWithFallback(backends, intent, {\n\t\t\t\tlimit: effectiveLimit,\n\t\t\t\tsignal,\n\t\t\t});\n\t\t\tconst meta = readFirecrawlMeta(backend);\n\t\t\tconst backendNotice = skipped.length > 0 ? `Search backend fallback: ${skipped.join(\"; \")}` : undefined;\n\t\t\tconst requested = {\n\t\t\t\t...(intent.results.images !== undefined ? { images: intent.results.images } : {}),\n\t\t\t\t...(intent.results.news !== undefined ? { news: intent.results.news } : {}),\n\t\t\t\t...(intent.results.web !== undefined ? { web: intent.results.web } : {}),\n\t\t\t};\n\t\t\tconst extraDetails = {\n\t\t\t\trequested,\n\t\t\t\t...(built.appliedTags.length > 0 ? { appliedTags: built.appliedTags } : {}),\n\t\t\t\t...(built.warnings.length > 0 ? { tagWarnings: built.warnings } : {}),\n\t\t\t};\n\t\t\tif (hits.length === 0) {\n\t\t\t\tconst details: WebfetchToolDetails = {\n\t\t\t\t\trefs: [],\n\t\t\t\t\tbackend: backend.id,\n\t\t\t\t\t...meta,\n\t\t\t\t\tbackendNotice,\n\t\t\t\t\t...extraDetails,\n\t\t\t\t};\n\t\t\t\t// Zero results after a backend was skipped is not the same as \"nothing\n\t\t\t\t// matched\": say which backend could not serve the request.\n\t\t\t\tconst text = backendNotice\n\t\t\t\t\t? `No results found for \"${intent.query}\". ${backendNotice}`\n\t\t\t\t\t: `No results found for \"${intent.query}\"`;\n\t\t\t\treturn { content: [{ type: \"text\", text }], details };\n\t\t\t}\n\t\t\tconst stored = hits.slice(0, effectiveLimit).map((result) => ({\n\t\t\t\tresult,\n\t\t\t\tref: store.store(resultToDocument(result), backend.id === \"undici\" ? \"undici\" : \"firecrawl\", false),\n\t\t\t}));\n\t\t\tconst details: WebfetchToolDetails = {\n\t\t\t\trefs: stored.map((hit) => hit.ref),\n\t\t\t\tbackend: backend.id,\n\t\t\t\t...meta,\n\t\t\t\tbackendNotice,\n\t\t\t\t...extraDetails,\n\t\t\t};\n\t\t\treturn { content: [{ type: \"text\", text: formatSearchResults(intent.query, stored) }], details };\n\t\t},\n\t\t...webfetchRenderers,\n\t};\n}\n\nfunction resultToDocument(result: WebSearchResult): WebDocument {\n\treturn { url: result.url, title: result.title, markdown: result.snippet, fetchedAt: new Date().toISOString() };\n}\n\nexport function resolveFetchBackends(options?: WebfetchToolOptions): {\n\tprimary: WebFetchBackend;\n\tfallback: WebFetchBackend;\n} {\n\treturn {\n\t\tprimary: options?.fetchBackend ?? createFirecrawlBackend({ apiKey: resolveWebApiKey(options?.apiKey) }),\n\t\tfallback: options?.fallbackBackend ?? createUndiciBackend(),\n\t};\n}\n\nexport function createWebfetchTool(_cwd: string, options?: WebfetchToolOptions): AgentTool<typeof webfetchSchema> {\n\treturn wrapToolDefinition(createWebfetchToolDefinition(_cwd, options));\n}\n"]}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import { createExaBackend, isExaFallbackEligible, resolveExaApiKey } from "../webfetch/backend-exa.js";
|
|
3
|
+
import { createFirecrawlBackend, isFallbackEligible, resolveFirecrawlApiKey, } from "../webfetch/backend-firecrawl.js";
|
|
4
|
+
import { createUndiciBackend } from "../webfetch/backend-undici.js";
|
|
5
|
+
import { WebDocumentStore } from "../webfetch/doc-store.js";
|
|
6
|
+
import { WebfetchError } from "../webfetch/guardrails.js";
|
|
7
|
+
import { resolveSearchIntent, totalRequestedResults } from "../webfetch/search-intent.js";
|
|
8
|
+
import { parseSearchQueryTags } from "../webfetch/search-tags.js";
|
|
9
|
+
import { webfetchRenderers } from "./renderers/webfetch.js";
|
|
10
|
+
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
11
|
+
export { WEBFETCH_DEFAULT_WINDOW_CHARS, WebDocumentStore, } from "../webfetch/doc-store.js";
|
|
12
|
+
export { parseRecency, resolveSearchIntent, SEARCH_DEFAULT_WEB_RESULTS, SEARCH_MAX_PER_SOURCE, SearchIntentError, totalRequestedResults, } from "../webfetch/search-intent.js";
|
|
13
|
+
export { parseSearchQueryTags } from "../webfetch/search-tags.js";
|
|
14
|
+
const resultCountsSchema = Type.Object({
|
|
15
|
+
web: Type.Optional(Type.Number({ description: "Web page results (1-100, default 5 when results is omitted)" })),
|
|
16
|
+
images: Type.Optional(Type.Number({ description: "Image results (1-100); Firecrawl only" })),
|
|
17
|
+
news: Type.Optional(Type.Number({ description: "News results (1-100)" })),
|
|
18
|
+
});
|
|
19
|
+
const searchFiltersSchema = Type.Object({
|
|
20
|
+
domains: Type.Optional(Type.Array(Type.String(), { description: "Restrict results to these domains or domain prefixes" })),
|
|
21
|
+
recency: Type.Optional(Type.String({ description: "Maximum result age, e.g. 24h, 7d, 2w, 1m" })),
|
|
22
|
+
language: Type.Optional(Type.String({ description: "Two-letter language/country hint" })),
|
|
23
|
+
});
|
|
24
|
+
const webfetchSchema = Type.Object({
|
|
25
|
+
query: Type.String({
|
|
26
|
+
description: "Web search query. Tag sugar is accepted when the structured args below are omitted: [images=3] [news=5] [recent=7d] [domains=openai.com] [img] your query",
|
|
27
|
+
}),
|
|
28
|
+
results: Type.Optional(resultCountsSchema),
|
|
29
|
+
filters: Type.Optional(searchFiltersSchema),
|
|
30
|
+
limit: Type.Optional(Type.Number({ description: "Cap on total results across all sources (1-100)" })),
|
|
31
|
+
});
|
|
32
|
+
export const webfetchToolSystemPromptContribution = {
|
|
33
|
+
snippet: "Search the web (results stored as web:// refs, full text via webextract)",
|
|
34
|
+
guidelines: [
|
|
35
|
+
"Use webfetch instead of curl for web research: results are stored as web:// refs, then read full text on demand with webextract instead of pasting whole pages",
|
|
36
|
+
"Pass results/filters for structured control (per-source counts, domains, recency). Tag sugar like [images=3] [news=5] [recent=7d] works only when those args are omitted.",
|
|
37
|
+
"Naming a source replaces the default web-only request: results={images:3} returns images only.",
|
|
38
|
+
"Image results and recency/domain filters need Firecrawl; if it is unavailable, ask for plain web results without filters.",
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
const DEFAULT_LIMIT = 5;
|
|
42
|
+
const MAX_LIMIT = 100;
|
|
43
|
+
export function resolveWebApiKey(explicitApiKey) {
|
|
44
|
+
return resolveFirecrawlApiKey(explicitApiKey);
|
|
45
|
+
}
|
|
46
|
+
function clampToolLimit(limit) {
|
|
47
|
+
if (limit === undefined || !Number.isFinite(limit))
|
|
48
|
+
return DEFAULT_LIMIT;
|
|
49
|
+
return Math.min(MAX_LIMIT, Math.max(1, Math.floor(limit)));
|
|
50
|
+
}
|
|
51
|
+
function resolveSearchBackends(options) {
|
|
52
|
+
if (options?.searchBackend) {
|
|
53
|
+
return [options.searchBackend, ...(options.fallbackSearchBackends ?? [])];
|
|
54
|
+
}
|
|
55
|
+
return [
|
|
56
|
+
createFirecrawlBackend({ apiKey: resolveWebApiKey(options?.apiKey) }),
|
|
57
|
+
createExaBackend({ apiKey: resolveExaApiKey(options?.exaApiKey) }),
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A search backend is skipped for auth/quota/transport/timeout/empty failures
|
|
62
|
+
* and keyless-tier refusals. The `unavailable` code is matched structurally so a
|
|
63
|
+
* backend compiled in a different module graph still counts.
|
|
64
|
+
*/
|
|
65
|
+
function isSearchFallbackEligible(error) {
|
|
66
|
+
if (isFallbackEligible(error) || isExaFallbackEligible(error))
|
|
67
|
+
return true;
|
|
68
|
+
return error instanceof Error && "code" in error && error.code === "unavailable";
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Try each search backend in order. A backend is only skipped when it reports a
|
|
72
|
+
* fallback-eligible failure — a bad request still surfaces, and results are
|
|
73
|
+
* never merged across backends.
|
|
74
|
+
*/
|
|
75
|
+
async function searchWithFallback(backends, intent, searchOptions) {
|
|
76
|
+
const skipped = [];
|
|
77
|
+
let lastError;
|
|
78
|
+
for (const backend of backends) {
|
|
79
|
+
try {
|
|
80
|
+
const results = await backend.search(intent, searchOptions);
|
|
81
|
+
return { backend, results, skipped };
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (!isSearchFallbackEligible(error))
|
|
85
|
+
throw error;
|
|
86
|
+
lastError = error;
|
|
87
|
+
skipped.push(`${backend.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
throw lastError instanceof Error
|
|
91
|
+
? lastError
|
|
92
|
+
: new WebfetchError("No web search backend is available", "unavailable");
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Build the search intent from the structured arguments, falling back to tag
|
|
96
|
+
* sugar in the query when `results`/`filters` are absent. An explicit structured
|
|
97
|
+
* call always wins; sugar is only a convenience for terse queries.
|
|
98
|
+
*/
|
|
99
|
+
export function buildSearchIntent(input) {
|
|
100
|
+
const structured = input.results !== undefined || input.filters !== undefined;
|
|
101
|
+
let query = input.query;
|
|
102
|
+
let results = input.results;
|
|
103
|
+
let filters = input.filters;
|
|
104
|
+
let appliedTags = [];
|
|
105
|
+
let warnings = [];
|
|
106
|
+
if (!structured) {
|
|
107
|
+
const parsed = parseSearchQueryTags(input.query);
|
|
108
|
+
query = parsed.intent.query;
|
|
109
|
+
results = parsed.intent.results;
|
|
110
|
+
filters = parsed.intent.filters;
|
|
111
|
+
appliedTags = parsed.appliedTags;
|
|
112
|
+
warnings = parsed.warnings;
|
|
113
|
+
}
|
|
114
|
+
const resolved = resolveSearchIntent({ query, results, filters });
|
|
115
|
+
// `limit` is a total across sources: scale the requested counts down together
|
|
116
|
+
// rather than truncating one modality after the backend answered.
|
|
117
|
+
const requestedTotal = totalRequestedResults(resolved);
|
|
118
|
+
if (input.limit !== undefined && Number.isFinite(input.limit) && input.limit < requestedTotal) {
|
|
119
|
+
const cap = Math.max(1, Math.floor(input.limit));
|
|
120
|
+
const scale = cap / requestedTotal;
|
|
121
|
+
const scaled = {};
|
|
122
|
+
let assigned = 0;
|
|
123
|
+
const sources = Object.keys(resolved.results);
|
|
124
|
+
for (const [index, source] of sources.entries()) {
|
|
125
|
+
const count = resolved.results[source] ?? 0;
|
|
126
|
+
const share = index === sources.length - 1 ? Math.max(0, cap - assigned) : Math.max(1, Math.floor(count * scale));
|
|
127
|
+
scaled[source] = Math.min(count, share);
|
|
128
|
+
assigned += scaled[source];
|
|
129
|
+
}
|
|
130
|
+
resolved.results = { ...resolved.results, ...scaled };
|
|
131
|
+
warnings = [...warnings, `limit ${cap} reduced the requested ${requestedTotal} results per source`];
|
|
132
|
+
}
|
|
133
|
+
return { intent: resolved, appliedTags, warnings };
|
|
134
|
+
}
|
|
135
|
+
function readFirecrawlMeta(backend) {
|
|
136
|
+
if (!("lastMeta" in backend))
|
|
137
|
+
return {};
|
|
138
|
+
const meta = backend.lastMeta;
|
|
139
|
+
const result = {};
|
|
140
|
+
if (meta?.warning !== undefined)
|
|
141
|
+
result.warning = meta.warning;
|
|
142
|
+
if (meta?.creditsUsed !== undefined)
|
|
143
|
+
result.creditsUsed = meta.creditsUsed;
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
export function formatSearchResults(query, hits) {
|
|
147
|
+
const lines = hits.map(({ result, ref }, index) => `${index + 1}. ${result.title}\n ${result.url} (${ref})${result.snippet ? `\n ${result.snippet}` : ""}`);
|
|
148
|
+
return [
|
|
149
|
+
`Search results for "${query}":`,
|
|
150
|
+
...lines,
|
|
151
|
+
"",
|
|
152
|
+
"Full text is not included. Use webextract with a web:// ref to read a result.",
|
|
153
|
+
].join("\n");
|
|
154
|
+
}
|
|
155
|
+
export function createWebfetchToolDefinition(_cwd, options) {
|
|
156
|
+
const backends = resolveSearchBackends(options);
|
|
157
|
+
const store = options?.store ?? new WebDocumentStore();
|
|
158
|
+
return {
|
|
159
|
+
name: "webfetch",
|
|
160
|
+
label: "webfetch",
|
|
161
|
+
description: `Search the web for a query. Returns titles, URLs, and snippets; each web result is stored as a web:// ref for on-demand full text via webextract. Control modality and cardinality with results: {web, images, news} (counts are per source), and filters: {domains, recency, language}. Tag sugar works when those are omitted: [images=3] [news=5] [recent=7d] [domains=openai.com] [img] query. Search tries Firecrawl first (keyless tier without a key, and the only source of image results), then Exa (REST with an API key, or the keyless hosted tier) when Firecrawl is unavailable.`,
|
|
162
|
+
promptSnippet: webfetchToolSystemPromptContribution.snippet,
|
|
163
|
+
promptGuidelines: [...webfetchToolSystemPromptContribution.guidelines],
|
|
164
|
+
parameters: webfetchSchema,
|
|
165
|
+
async execute(_toolCallId, { query, results, filters, limit }, signal, _onUpdate, _ctx) {
|
|
166
|
+
if (!query?.trim()) {
|
|
167
|
+
throw new Error("Search query must not be empty");
|
|
168
|
+
}
|
|
169
|
+
const built = buildSearchIntent({ query, results, filters, limit });
|
|
170
|
+
const intent = built.intent;
|
|
171
|
+
const effectiveLimit = clampToolLimit(limit);
|
|
172
|
+
const { backend, results: hits, skipped, } = await searchWithFallback(backends, intent, {
|
|
173
|
+
limit: effectiveLimit,
|
|
174
|
+
signal,
|
|
175
|
+
});
|
|
176
|
+
const meta = readFirecrawlMeta(backend);
|
|
177
|
+
const backendNotice = skipped.length > 0 ? `Search backend fallback: ${skipped.join("; ")}` : undefined;
|
|
178
|
+
const requested = {
|
|
179
|
+
...(intent.results.images !== undefined ? { images: intent.results.images } : {}),
|
|
180
|
+
...(intent.results.news !== undefined ? { news: intent.results.news } : {}),
|
|
181
|
+
...(intent.results.web !== undefined ? { web: intent.results.web } : {}),
|
|
182
|
+
};
|
|
183
|
+
const extraDetails = {
|
|
184
|
+
requested,
|
|
185
|
+
...(built.appliedTags.length > 0 ? { appliedTags: built.appliedTags } : {}),
|
|
186
|
+
...(built.warnings.length > 0 ? { tagWarnings: built.warnings } : {}),
|
|
187
|
+
};
|
|
188
|
+
if (hits.length === 0) {
|
|
189
|
+
const details = {
|
|
190
|
+
refs: [],
|
|
191
|
+
backend: backend.id,
|
|
192
|
+
...meta,
|
|
193
|
+
backendNotice,
|
|
194
|
+
...extraDetails,
|
|
195
|
+
};
|
|
196
|
+
// Zero results after a backend was skipped is not the same as "nothing
|
|
197
|
+
// matched": say which backend could not serve the request.
|
|
198
|
+
const text = backendNotice
|
|
199
|
+
? `No results found for "${intent.query}". ${backendNotice}`
|
|
200
|
+
: `No results found for "${intent.query}"`;
|
|
201
|
+
return { content: [{ type: "text", text }], details };
|
|
202
|
+
}
|
|
203
|
+
const stored = hits.slice(0, effectiveLimit).map((result) => ({
|
|
204
|
+
result,
|
|
205
|
+
ref: store.store(resultToDocument(result), backend.id === "undici" ? "undici" : "firecrawl", false),
|
|
206
|
+
}));
|
|
207
|
+
const details = {
|
|
208
|
+
refs: stored.map((hit) => hit.ref),
|
|
209
|
+
backend: backend.id,
|
|
210
|
+
...meta,
|
|
211
|
+
backendNotice,
|
|
212
|
+
...extraDetails,
|
|
213
|
+
};
|
|
214
|
+
return { content: [{ type: "text", text: formatSearchResults(intent.query, stored) }], details };
|
|
215
|
+
},
|
|
216
|
+
...webfetchRenderers,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function resultToDocument(result) {
|
|
220
|
+
return { url: result.url, title: result.title, markdown: result.snippet, fetchedAt: new Date().toISOString() };
|
|
221
|
+
}
|
|
222
|
+
export function resolveFetchBackends(options) {
|
|
223
|
+
return {
|
|
224
|
+
primary: options?.fetchBackend ?? createFirecrawlBackend({ apiKey: resolveWebApiKey(options?.apiKey) }),
|
|
225
|
+
fallback: options?.fallbackBackend ?? createUndiciBackend(),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
export function createWebfetchTool(_cwd, options) {
|
|
229
|
+
return wrapToolDefinition(createWebfetchToolDefinition(_cwd, options));
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=webfetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webfetch.js","sourceRoot":"","sources":["../../../src/core/tools/webfetch.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACvG,OAAO,EACN,sBAAsB,EAEtB,kBAAkB,EAClB,sBAAsB,GACtB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAA6B,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrH,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGlE,OAAO,EAGN,6BAA6B,EAE7B,gBAAgB,GAChB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,YAAY,EAEZ,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EAGrB,iBAAiB,EAEjB,qBAAqB,GACrB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAA0B,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAE1F,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC;IACtC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,6DAA6D,EAAE,CAAC,CAAC;IAC/G,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC,CAAC;IAC5F,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,sBAAsB,EAAE,CAAC,CAAC;CACzE,CAAC,CAAC;AAEH,MAAM,mBAAmB,GAAG,IAAI,CAAC,MAAM,CAAC;IACvC,OAAO,EAAE,IAAI,CAAC,QAAQ,CACrB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC,CAClG;IACD,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,0CAA0C,EAAE,CAAC,CAAC;IAChG,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC,CAAC;CACzF,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC;IAClC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC;QAClB,WAAW,EACV,2JAA2J;KAC5J,CAAC;IACF,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IAC1C,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IAC3C,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,iDAAiD,EAAE,CAAC,CAAC;CACrG,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,oCAAoC,GAAG;IACnD,OAAO,EAAE,0EAA0E;IACnF,UAAU,EAAE;QACX,gKAAgK;QAChK,2KAA2K;QAC3K,gGAAgG;QAChG,2HAA2H;KAC3H;CACQ,CAAC;AAIX,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,SAAS,GAAG,GAAG,CAAC;AAyCtB,MAAM,UAAU,gBAAgB,CAAC,cAAuB,EAAsB;IAC7E,OAAO,sBAAsB,CAAC,cAAc,CAAC,CAAC;AAAA,CAC9C;AAED,SAAS,cAAc,CAAC,KAAyB,EAAU;IAC1D,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,aAAa,CAAC;IACzE,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAAA,CAC3D;AAED,SAAS,qBAAqB,CAAC,OAA6B,EAAsB;IACjF,IAAI,OAAO,EAAE,aAAa,EAAE,CAAC;QAC5B,OAAO,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO;QACN,sBAAsB,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;QACrE,gBAAgB,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;KAClE,CAAC;AAAA,CACF;AAED;;;;GAIG;AACH,SAAS,wBAAwB,CAAC,KAAc,EAAW;IAC1D,IAAI,kBAAkB,CAAC,KAAK,CAAC,IAAI,qBAAqB,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3E,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAK,KAA4B,CAAC,IAAI,KAAK,aAAa,CAAC;AAAA,CACzG;AAED;;;;GAIG;AACH,KAAK,UAAU,kBAAkB,CAChC,QAA4B,EAC5B,MAA4B,EAC5B,aAAsD,EACkC;IACxF,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,SAAkB,CAAC;IACvB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAChC,IAAI,CAAC;YACJ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YAC5D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC;YAClD,SAAS,GAAG,KAAK,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,EAAE,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1F,CAAC;IACF,CAAC;IACD,MAAM,SAAS,YAAY,KAAK;QAC/B,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,aAAa,CAAC,oCAAoC,EAAE,aAAa,CAAC,CAAC;AAAA,CAC1E;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAKjC,EAA+E;IAC/E,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC;IAC9E,IAAI,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACxB,IAAI,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC5B,IAAI,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC5B,IAAI,WAAW,GAAa,EAAE,CAAC;IAC/B,IAAI,QAAQ,GAAa,EAAE,CAAC;IAE5B,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACjD,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;QAC5B,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;QAChC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;QAChC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QACjC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC5B,CAAC;IAED,MAAM,QAAQ,GAAG,mBAAmB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAClE,8EAA8E;IAC9E,kEAAkE;IAClE,MAAM,cAAc,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,cAAc,EAAE,CAAC;QAC/F,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,GAAG,GAAG,cAAc,CAAC;QACnC,MAAM,MAAM,GAA2B,EAAE,CAAC;QAC1C,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAqC,CAAC;QAClF,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC5C,MAAM,KAAK,GACV,KAAK,KAAK,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;YACrG,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACxC,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QACD,QAAQ,CAAC,OAAO,GAAG,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC;QACtD,QAAQ,GAAG,CAAC,GAAG,QAAQ,EAAE,SAAS,GAAG,0BAA0B,cAAc,qBAAqB,CAAC,CAAC;IACrG,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;AAAA,CACnD;AAED,SAAS,iBAAiB,CAAC,OAAyB,EAA8C;IACjG,IAAI,CAAC,CAAC,UAAU,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,MAAM,IAAI,GAAI,OAA4B,CAAC,QAAQ,CAAC;IACpD,MAAM,MAAM,GAA+C,EAAE,CAAC;IAC9D,IAAI,IAAI,EAAE,OAAO,KAAK,SAAS;QAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC/D,IAAI,IAAI,EAAE,WAAW,KAAK,SAAS;QAAE,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;IAC3E,OAAO,MAAM,CAAC;AAAA,CACd;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,IAAqD,EAAU;IACjH,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACrB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,CAC1B,GAAG,KAAK,GAAG,CAAC,KAAK,MAAM,CAAC,KAAK,QAAQ,MAAM,CAAC,GAAG,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAC5G,CAAC;IACF,OAAO;QACN,uBAAuB,KAAK,IAAI;QAChC,GAAG,KAAK;QACR,EAAE;QACF,+EAA+E;KAC/E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CACb;AAED,MAAM,UAAU,4BAA4B,CAC3C,IAAY,EACZ,OAA6B,EACgC;IAC7D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,IAAI,gBAAgB,EAAE,CAAC;IACvD,OAAO;QACN,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,gkBAAgkB;QAC7kB,aAAa,EAAE,oCAAoC,CAAC,OAAO;QAC3D,gBAAgB,EAAE,CAAC,GAAG,oCAAoC,CAAC,UAAU,CAAC;QACtE,UAAU,EAAE,cAAc;QAC1B,KAAK,CAAC,OAAO,CACZ,WAAW,EACX,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAqB,EACrD,MAAoB,EACpB,SAAU,EACV,IAAuB,EACtB;YACD,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;YACnD,CAAC;YACD,MAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACpE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC5B,MAAM,cAAc,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;YAC7C,MAAM,EACL,OAAO,EACP,OAAO,EAAE,IAAI,EACb,OAAO,GACP,GAAG,MAAM,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE;gBAC9C,KAAK,EAAE,cAAc;gBACrB,MAAM;aACN,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YACxC,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,4BAA4B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;YACxG,MAAM,SAAS,GAAG;gBACjB,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjF,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3E,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxE,CAAC;YACF,MAAM,YAAY,GAAG;gBACpB,SAAS;gBACT,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3E,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACrE,CAAC;YACF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,MAAM,OAAO,GAAwB;oBACpC,IAAI,EAAE,EAAE;oBACR,OAAO,EAAE,OAAO,CAAC,EAAE;oBACnB,GAAG,IAAI;oBACP,aAAa;oBACb,GAAG,YAAY;iBACf,CAAC;gBACF,uEAAuE;gBACvE,2DAA2D;gBAC3D,MAAM,IAAI,GAAG,aAAa;oBACzB,CAAC,CAAC,yBAAyB,MAAM,CAAC,KAAK,MAAM,aAAa,EAAE;oBAC5D,CAAC,CAAC,yBAAyB,MAAM,CAAC,KAAK,GAAG,CAAC;gBAC5C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;YACvD,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBAC7D,MAAM;gBACN,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC;aACnG,CAAC,CAAC,CAAC;YACJ,MAAM,OAAO,GAAwB;gBACpC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC;gBAClC,OAAO,EAAE,OAAO,CAAC,EAAE;gBACnB,GAAG,IAAI;gBACP,aAAa;gBACb,GAAG,YAAY;aACf,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;QAAA,CACjG;QACD,GAAG,iBAAiB;KACpB,CAAC;AAAA,CACF;AAED,SAAS,gBAAgB,CAAC,MAAuB,EAAe;IAC/D,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;AAAA,CAC/G;AAED,MAAM,UAAU,oBAAoB,CAAC,OAA6B,EAGhE;IACD,OAAO;QACN,OAAO,EAAE,OAAO,EAAE,YAAY,IAAI,sBAAsB,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;QACvG,QAAQ,EAAE,OAAO,EAAE,eAAe,IAAI,mBAAmB,EAAE;KAC3D,CAAC;AAAA,CACF;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,OAA6B,EAAoC;IACjH,OAAO,kBAAkB,CAAC,4BAA4B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAAA,CACvE","sourcesContent":["import type { AgentTool } from \"@m4ike1/ion-agent-core\";\nimport { type Static, Type } from \"typebox\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\nimport type { WebDocument, WebFetchBackend, WebSearchBackend, WebSearchResult } from \"../webfetch/backend.ts\";\nimport { createExaBackend, isExaFallbackEligible, resolveExaApiKey } from \"../webfetch/backend-exa.ts\";\nimport {\n\tcreateFirecrawlBackend,\n\ttype FirecrawlBackend,\n\tisFallbackEligible,\n\tresolveFirecrawlApiKey,\n} from \"../webfetch/backend-firecrawl.ts\";\nimport { createUndiciBackend } from \"../webfetch/backend-undici.ts\";\nimport { WebDocumentStore } from \"../webfetch/doc-store.ts\";\nimport { WebfetchError } from \"../webfetch/guardrails.ts\";\nimport { type ResolvedSearchIntent, resolveSearchIntent, totalRequestedResults } from \"../webfetch/search-intent.ts\";\nimport { parseSearchQueryTags } from \"../webfetch/search-tags.ts\";\nimport { webfetchRenderers } from \"./renderers/webfetch.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nexport type { WebDocument, WebFetchBackend, WebSearchBackend, WebSearchResult } from \"../webfetch/backend.ts\";\nexport {\n\ttype ExtractWindow,\n\ttype StoredWebDocument,\n\tWEBFETCH_DEFAULT_WINDOW_CHARS,\n\ttype WebDocumentSource,\n\tWebDocumentStore,\n} from \"../webfetch/doc-store.ts\";\nexport {\n\tparseRecency,\n\ttype ResolvedSearchIntent,\n\tresolveSearchIntent,\n\tSEARCH_DEFAULT_WEB_RESULTS,\n\tSEARCH_MAX_PER_SOURCE,\n\ttype SearchFilters,\n\ttype SearchIntent,\n\tSearchIntentError,\n\ttype SearchResultCounts,\n\ttotalRequestedResults,\n} from \"../webfetch/search-intent.ts\";\nexport { type ParsedSearchQuery, parseSearchQueryTags } from \"../webfetch/search-tags.ts\";\n\nconst resultCountsSchema = Type.Object({\n\tweb: Type.Optional(Type.Number({ description: \"Web page results (1-100, default 5 when results is omitted)\" })),\n\timages: Type.Optional(Type.Number({ description: \"Image results (1-100); Firecrawl only\" })),\n\tnews: Type.Optional(Type.Number({ description: \"News results (1-100)\" })),\n});\n\nconst searchFiltersSchema = Type.Object({\n\tdomains: Type.Optional(\n\t\tType.Array(Type.String(), { description: \"Restrict results to these domains or domain prefixes\" }),\n\t),\n\trecency: Type.Optional(Type.String({ description: \"Maximum result age, e.g. 24h, 7d, 2w, 1m\" })),\n\tlanguage: Type.Optional(Type.String({ description: \"Two-letter language/country hint\" })),\n});\n\nconst webfetchSchema = Type.Object({\n\tquery: Type.String({\n\t\tdescription:\n\t\t\t\"Web search query. Tag sugar is accepted when the structured args below are omitted: [images=3] [news=5] [recent=7d] [domains=openai.com] [img] your query\",\n\t}),\n\tresults: Type.Optional(resultCountsSchema),\n\tfilters: Type.Optional(searchFiltersSchema),\n\tlimit: Type.Optional(Type.Number({ description: \"Cap on total results across all sources (1-100)\" })),\n});\n\nexport const webfetchToolSystemPromptContribution = {\n\tsnippet: \"Search the web (results stored as web:// refs, full text via webextract)\",\n\tguidelines: [\n\t\t\"Use webfetch instead of curl for web research: results are stored as web:// refs, then read full text on demand with webextract instead of pasting whole pages\",\n\t\t\"Pass results/filters for structured control (per-source counts, domains, recency). Tag sugar like [images=3] [news=5] [recent=7d] works only when those args are omitted.\",\n\t\t\"Naming a source replaces the default web-only request: results={images:3} returns images only.\",\n\t\t\"Image results and recency/domain filters need Firecrawl; if it is unavailable, ask for plain web results without filters.\",\n\t],\n} as const;\n\nexport type WebfetchToolInput = Static<typeof webfetchSchema>;\n\nconst DEFAULT_LIMIT = 5;\nconst MAX_LIMIT = 100;\n\nexport interface WebfetchToolDetails {\n\trefs: string[];\n\tbackend: \"firecrawl\" | \"exa\" | \"undici\";\n\twarning?: string;\n\tcreditsUsed?: number;\n\t/** Set when an earlier backend in the chain failed and a later one answered. */\n\tbackendNotice?: string;\n\t/** Per-source counts actually requested after tag sugar and clamping. */\n\trequested?: { web?: number; images?: number; news?: number };\n\t/** Tag sugar that was recognized, e.g. `[images=3]`. */\n\tappliedTags?: string[];\n\t/** Tag sugar that looked like a directive but could not be applied. */\n\ttagWarnings?: string[];\n}\n\n/**\n * Pluggable backends for the web tools.\n * Override these to test without network or to front a different search provider.\n */\nexport interface WebOperations {\n\t/** Search backend. Default: the ordered chain Firecrawl -> Exa. */\n\tsearchBackend?: WebSearchBackend;\n\t/** Extra search backends tried after `searchBackend` fails. Default: Exa. */\n\tfallbackSearchBackends?: WebSearchBackend[];\n\t/** Primary fetch backend. Default: Firecrawl. */\n\tfetchBackend?: WebFetchBackend;\n\t/** Direct-fetch fallback used on Firecrawl transport/auth failures. Default: undici. */\n\tfallbackBackend?: WebFetchBackend;\n\t/** Shared session document store. Default: a fresh store per tool instance. */\n\tstore?: WebDocumentStore;\n}\n\nexport interface WebfetchToolOptions extends WebOperations {\n\t/** Firecrawl API key. Default: `FIRECRAWL_API_KEY` env. Omitted entirely when unset (keyless tier). */\n\tapiKey?: string;\n\t/** Exa API key. Default: `EXA_API_KEY` env. Unset uses the keyless hosted MCP search tier. */\n\texaApiKey?: string;\n}\n\nexport function resolveWebApiKey(explicitApiKey?: string): string | undefined {\n\treturn resolveFirecrawlApiKey(explicitApiKey);\n}\n\nfunction clampToolLimit(limit: number | undefined): number {\n\tif (limit === undefined || !Number.isFinite(limit)) return DEFAULT_LIMIT;\n\treturn Math.min(MAX_LIMIT, Math.max(1, Math.floor(limit)));\n}\n\nfunction resolveSearchBackends(options?: WebfetchToolOptions): WebSearchBackend[] {\n\tif (options?.searchBackend) {\n\t\treturn [options.searchBackend, ...(options.fallbackSearchBackends ?? [])];\n\t}\n\treturn [\n\t\tcreateFirecrawlBackend({ apiKey: resolveWebApiKey(options?.apiKey) }),\n\t\tcreateExaBackend({ apiKey: resolveExaApiKey(options?.exaApiKey) }),\n\t];\n}\n\n/**\n * A search backend is skipped for auth/quota/transport/timeout/empty failures\n * and keyless-tier refusals. The `unavailable` code is matched structurally so a\n * backend compiled in a different module graph still counts.\n */\nfunction isSearchFallbackEligible(error: unknown): boolean {\n\tif (isFallbackEligible(error) || isExaFallbackEligible(error)) return true;\n\treturn error instanceof Error && \"code\" in error && (error as { code?: unknown }).code === \"unavailable\";\n}\n\n/**\n * Try each search backend in order. A backend is only skipped when it reports a\n * fallback-eligible failure — a bad request still surfaces, and results are\n * never merged across backends.\n */\nasync function searchWithFallback(\n\tbackends: WebSearchBackend[],\n\tintent: ResolvedSearchIntent,\n\tsearchOptions: { limit: number; signal?: AbortSignal },\n): Promise<{ backend: WebSearchBackend; results: WebSearchResult[]; skipped: string[] }> {\n\tconst skipped: string[] = [];\n\tlet lastError: unknown;\n\tfor (const backend of backends) {\n\t\ttry {\n\t\t\tconst results = await backend.search(intent, searchOptions);\n\t\t\treturn { backend, results, skipped };\n\t\t} catch (error) {\n\t\t\tif (!isSearchFallbackEligible(error)) throw error;\n\t\t\tlastError = error;\n\t\t\tskipped.push(`${backend.id}: ${error instanceof Error ? error.message : String(error)}`);\n\t\t}\n\t}\n\tthrow lastError instanceof Error\n\t\t? lastError\n\t\t: new WebfetchError(\"No web search backend is available\", \"unavailable\");\n}\n\n/**\n * Build the search intent from the structured arguments, falling back to tag\n * sugar in the query when `results`/`filters` are absent. An explicit structured\n * call always wins; sugar is only a convenience for terse queries.\n */\nexport function buildSearchIntent(input: {\n\tquery: string;\n\tresults?: { web?: number; images?: number; news?: number };\n\tfilters?: { domains?: string[]; recency?: string; language?: string };\n\tlimit?: number;\n}): { intent: ResolvedSearchIntent; appliedTags: string[]; warnings: string[] } {\n\tconst structured = input.results !== undefined || input.filters !== undefined;\n\tlet query = input.query;\n\tlet results = input.results;\n\tlet filters = input.filters;\n\tlet appliedTags: string[] = [];\n\tlet warnings: string[] = [];\n\n\tif (!structured) {\n\t\tconst parsed = parseSearchQueryTags(input.query);\n\t\tquery = parsed.intent.query;\n\t\tresults = parsed.intent.results;\n\t\tfilters = parsed.intent.filters;\n\t\tappliedTags = parsed.appliedTags;\n\t\twarnings = parsed.warnings;\n\t}\n\n\tconst resolved = resolveSearchIntent({ query, results, filters });\n\t// `limit` is a total across sources: scale the requested counts down together\n\t// rather than truncating one modality after the backend answered.\n\tconst requestedTotal = totalRequestedResults(resolved);\n\tif (input.limit !== undefined && Number.isFinite(input.limit) && input.limit < requestedTotal) {\n\t\tconst cap = Math.max(1, Math.floor(input.limit));\n\t\tconst scale = cap / requestedTotal;\n\t\tconst scaled: Record<string, number> = {};\n\t\tlet assigned = 0;\n\t\tconst sources = Object.keys(resolved.results) as Array<\"web\" | \"images\" | \"news\">;\n\t\tfor (const [index, source] of sources.entries()) {\n\t\t\tconst count = resolved.results[source] ?? 0;\n\t\t\tconst share =\n\t\t\t\tindex === sources.length - 1 ? Math.max(0, cap - assigned) : Math.max(1, Math.floor(count * scale));\n\t\t\tscaled[source] = Math.min(count, share);\n\t\t\tassigned += scaled[source];\n\t\t}\n\t\tresolved.results = { ...resolved.results, ...scaled };\n\t\twarnings = [...warnings, `limit ${cap} reduced the requested ${requestedTotal} results per source`];\n\t}\n\treturn { intent: resolved, appliedTags, warnings };\n}\n\nfunction readFirecrawlMeta(backend: WebSearchBackend): { warning?: string; creditsUsed?: number } {\n\tif (!(\"lastMeta\" in backend)) return {};\n\tconst meta = (backend as FirecrawlBackend).lastMeta;\n\tconst result: { warning?: string; creditsUsed?: number } = {};\n\tif (meta?.warning !== undefined) result.warning = meta.warning;\n\tif (meta?.creditsUsed !== undefined) result.creditsUsed = meta.creditsUsed;\n\treturn result;\n}\n\nexport function formatSearchResults(query: string, hits: Array<{ result: WebSearchResult; ref: string }>): string {\n\tconst lines = hits.map(\n\t\t({ result, ref }, index) =>\n\t\t\t`${index + 1}. ${result.title}\\n ${result.url} (${ref})${result.snippet ? `\\n ${result.snippet}` : \"\"}`,\n\t);\n\treturn [\n\t\t`Search results for \"${query}\":`,\n\t\t...lines,\n\t\t\"\",\n\t\t\"Full text is not included. Use webextract with a web:// ref to read a result.\",\n\t].join(\"\\n\");\n}\n\nexport function createWebfetchToolDefinition(\n\t_cwd: string,\n\toptions?: WebfetchToolOptions,\n): ToolDefinition<typeof webfetchSchema, WebfetchToolDetails> {\n\tconst backends = resolveSearchBackends(options);\n\tconst store = options?.store ?? new WebDocumentStore();\n\treturn {\n\t\tname: \"webfetch\",\n\t\tlabel: \"webfetch\",\n\t\tdescription: `Search the web for a query. Returns titles, URLs, and snippets; each web result is stored as a web:// ref for on-demand full text via webextract. Control modality and cardinality with results: {web, images, news} (counts are per source), and filters: {domains, recency, language}. Tag sugar works when those are omitted: [images=3] [news=5] [recent=7d] [domains=openai.com] [img] query. Search tries Firecrawl first (keyless tier without a key, and the only source of image results), then Exa (REST with an API key, or the keyless hosted tier) when Firecrawl is unavailable.`,\n\t\tpromptSnippet: webfetchToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...webfetchToolSystemPromptContribution.guidelines],\n\t\tparameters: webfetchSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ query, results, filters, limit }: WebfetchToolInput,\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\t_ctx?: ExtensionContext,\n\t\t) {\n\t\t\tif (!query?.trim()) {\n\t\t\t\tthrow new Error(\"Search query must not be empty\");\n\t\t\t}\n\t\t\tconst built = buildSearchIntent({ query, results, filters, limit });\n\t\t\tconst intent = built.intent;\n\t\t\tconst effectiveLimit = clampToolLimit(limit);\n\t\t\tconst {\n\t\t\t\tbackend,\n\t\t\t\tresults: hits,\n\t\t\t\tskipped,\n\t\t\t} = await searchWithFallback(backends, intent, {\n\t\t\t\tlimit: effectiveLimit,\n\t\t\t\tsignal,\n\t\t\t});\n\t\t\tconst meta = readFirecrawlMeta(backend);\n\t\t\tconst backendNotice = skipped.length > 0 ? `Search backend fallback: ${skipped.join(\"; \")}` : undefined;\n\t\t\tconst requested = {\n\t\t\t\t...(intent.results.images !== undefined ? { images: intent.results.images } : {}),\n\t\t\t\t...(intent.results.news !== undefined ? { news: intent.results.news } : {}),\n\t\t\t\t...(intent.results.web !== undefined ? { web: intent.results.web } : {}),\n\t\t\t};\n\t\t\tconst extraDetails = {\n\t\t\t\trequested,\n\t\t\t\t...(built.appliedTags.length > 0 ? { appliedTags: built.appliedTags } : {}),\n\t\t\t\t...(built.warnings.length > 0 ? { tagWarnings: built.warnings } : {}),\n\t\t\t};\n\t\t\tif (hits.length === 0) {\n\t\t\t\tconst details: WebfetchToolDetails = {\n\t\t\t\t\trefs: [],\n\t\t\t\t\tbackend: backend.id,\n\t\t\t\t\t...meta,\n\t\t\t\t\tbackendNotice,\n\t\t\t\t\t...extraDetails,\n\t\t\t\t};\n\t\t\t\t// Zero results after a backend was skipped is not the same as \"nothing\n\t\t\t\t// matched\": say which backend could not serve the request.\n\t\t\t\tconst text = backendNotice\n\t\t\t\t\t? `No results found for \"${intent.query}\". ${backendNotice}`\n\t\t\t\t\t: `No results found for \"${intent.query}\"`;\n\t\t\t\treturn { content: [{ type: \"text\", text }], details };\n\t\t\t}\n\t\t\tconst stored = hits.slice(0, effectiveLimit).map((result) => ({\n\t\t\t\tresult,\n\t\t\t\tref: store.store(resultToDocument(result), backend.id === \"undici\" ? \"undici\" : \"firecrawl\", false),\n\t\t\t}));\n\t\t\tconst details: WebfetchToolDetails = {\n\t\t\t\trefs: stored.map((hit) => hit.ref),\n\t\t\t\tbackend: backend.id,\n\t\t\t\t...meta,\n\t\t\t\tbackendNotice,\n\t\t\t\t...extraDetails,\n\t\t\t};\n\t\t\treturn { content: [{ type: \"text\", text: formatSearchResults(intent.query, stored) }], details };\n\t\t},\n\t\t...webfetchRenderers,\n\t};\n}\n\nfunction resultToDocument(result: WebSearchResult): WebDocument {\n\treturn { url: result.url, title: result.title, markdown: result.snippet, fetchedAt: new Date().toISOString() };\n}\n\nexport function resolveFetchBackends(options?: WebfetchToolOptions): {\n\tprimary: WebFetchBackend;\n\tfallback: WebFetchBackend;\n} {\n\treturn {\n\t\tprimary: options?.fetchBackend ?? createFirecrawlBackend({ apiKey: resolveWebApiKey(options?.apiKey) }),\n\t\tfallback: options?.fallbackBackend ?? createUndiciBackend(),\n\t};\n}\n\nexport function createWebfetchTool(_cwd: string, options?: WebfetchToolOptions): AgentTool<typeof webfetchSchema> {\n\treturn wrapToolDefinition(createWebfetchToolDefinition(_cwd, options));\n}\n"]}
|