@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,339 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firecrawl backend for webfetch: thin `undici` POSTs to the hosted Firecrawl
|
|
3
|
+
* API. The SDK is never vendored (extra `axios` dep) and the server is never
|
|
4
|
+
* vendored (AGPL-3.0).
|
|
5
|
+
*
|
|
6
|
+
* Auth is an optional `Bearer` key, omitted entirely on the keyless tier.
|
|
7
|
+
* Resolve it with `resolveFirecrawlApiKey` (explicit settings value first,
|
|
8
|
+
* `FIRECRAWL_API_KEY` env second).
|
|
9
|
+
*/
|
|
10
|
+
import { request as undiciRequest } from "undici";
|
|
11
|
+
import { clampLimit, WEBFETCH_FIRECRAWL_MAX_LIMIT, WEBFETCH_REQUEST_TIMEOUT_MS, WebfetchError, } from "./guardrails.js";
|
|
12
|
+
export const FIRECRAWL_BASE_URL = "https://api.firecrawl.dev";
|
|
13
|
+
export const FIRECRAWL_API_KEY_ENV = "FIRECRAWL_API_KEY";
|
|
14
|
+
const FIRECRAWL_502_MAX_ATTEMPTS = 3;
|
|
15
|
+
const FIRECRAWL_HTTP_HEADROOM_MS = 5_000;
|
|
16
|
+
/** Explicit settings value wins; `FIRECRAWL_API_KEY` env is the fallback. Keyless (undefined) works with lower limits. */
|
|
17
|
+
export function resolveFirecrawlApiKey(explicit, env = process.env) {
|
|
18
|
+
const trimmed = explicit?.trim() || env[FIRECRAWL_API_KEY_ENV]?.trim();
|
|
19
|
+
return trimmed || undefined;
|
|
20
|
+
}
|
|
21
|
+
export class FirecrawlError extends WebfetchError {
|
|
22
|
+
status;
|
|
23
|
+
/** True when the caller should try the `undici` direct-fetch fallback (transport/auth failure, never content failure). */
|
|
24
|
+
fallback;
|
|
25
|
+
constructor(message, options) {
|
|
26
|
+
super(message, options.code);
|
|
27
|
+
this.name = "FirecrawlError";
|
|
28
|
+
this.status = options.status;
|
|
29
|
+
this.fallback = options.fallback;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The keyless Firecrawl tier refused this network (403 "your IP address looks
|
|
34
|
+
* suspicious", 401 without a key, or 429 on the shared anonymous pool). This is
|
|
35
|
+
* provider-side and often IP-dependent, so the message names the exact fix
|
|
36
|
+
* instead of leaking the raw status. Direct page fetch still works through the
|
|
37
|
+
* `undici` fallback; only search is unavailable.
|
|
38
|
+
*/
|
|
39
|
+
export function keylessUnavailableMessage(status, path) {
|
|
40
|
+
const reason = status === 429
|
|
41
|
+
? "the keyless rate limit was exhausted"
|
|
42
|
+
: status === 401
|
|
43
|
+
? "no API key was sent"
|
|
44
|
+
: "this network is not allowed on the anonymous tier";
|
|
45
|
+
return [
|
|
46
|
+
`Firecrawl ${path} is unavailable: ${reason} (status ${status}).`,
|
|
47
|
+
"Set a Firecrawl API key to fix this: add the `firecrawlApiKey` setting or the",
|
|
48
|
+
"`FIRECRAWL_API_KEY` environment variable, then retry.",
|
|
49
|
+
"`webextract` still works without a key: it fetches pages directly.",
|
|
50
|
+
].join(" ");
|
|
51
|
+
}
|
|
52
|
+
/** True when a failed Firecrawl call should fall back to direct `undici` fetch instead of surfacing the error. */
|
|
53
|
+
export function isFallbackEligible(error) {
|
|
54
|
+
if (error instanceof FirecrawlError)
|
|
55
|
+
return error.fallback;
|
|
56
|
+
if (error instanceof WebfetchError) {
|
|
57
|
+
return error.code === "timeout" || error.code === "transport" || error.code === "empty";
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
async function defaultPost(path, body, init) {
|
|
62
|
+
const timeoutSignal = AbortSignal.timeout(init.timeoutMs + FIRECRAWL_HTTP_HEADROOM_MS);
|
|
63
|
+
const signal = init.signal ? AbortSignal.any([init.signal, timeoutSignal]) : timeoutSignal;
|
|
64
|
+
let response;
|
|
65
|
+
try {
|
|
66
|
+
response = await undiciRequest(`${FIRECRAWL_BASE_URL}${path}`, {
|
|
67
|
+
method: "POST",
|
|
68
|
+
headers: { "content-type": "application/json", ...init.headers },
|
|
69
|
+
body: JSON.stringify(body),
|
|
70
|
+
signal,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (timeoutSignal.aborted && !init.signal?.aborted) {
|
|
75
|
+
throw new WebfetchError(`Firecrawl request to ${path} timed out`, "timeout");
|
|
76
|
+
}
|
|
77
|
+
if (init.signal?.aborted) {
|
|
78
|
+
throw new Error("Operation aborted");
|
|
79
|
+
}
|
|
80
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
81
|
+
throw new WebfetchError(`Firecrawl request to ${path} failed: ${reason}`, "transport");
|
|
82
|
+
}
|
|
83
|
+
let text;
|
|
84
|
+
try {
|
|
85
|
+
text = await response.body.text();
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
89
|
+
throw new WebfetchError(`Firecrawl request to ${path} failed: ${reason}`, "transport");
|
|
90
|
+
}
|
|
91
|
+
let json;
|
|
92
|
+
try {
|
|
93
|
+
json = text ? JSON.parse(text) : undefined;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
throw new WebfetchError(`Firecrawl request to ${path} returned invalid JSON`, "transport");
|
|
97
|
+
}
|
|
98
|
+
return { status: response.statusCode, json };
|
|
99
|
+
}
|
|
100
|
+
function isRecord(value) {
|
|
101
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
102
|
+
}
|
|
103
|
+
function asString(value) {
|
|
104
|
+
return typeof value === "string" ? value : undefined;
|
|
105
|
+
}
|
|
106
|
+
function asNumber(value) {
|
|
107
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
108
|
+
}
|
|
109
|
+
function firecrawlErrorMessage(json) {
|
|
110
|
+
if (!isRecord(json))
|
|
111
|
+
return undefined;
|
|
112
|
+
const direct = asString(json.error);
|
|
113
|
+
if (direct)
|
|
114
|
+
return direct;
|
|
115
|
+
if (isRecord(json.data)) {
|
|
116
|
+
const nested = asString(json.data.error);
|
|
117
|
+
if (nested)
|
|
118
|
+
return nested;
|
|
119
|
+
}
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
function readMeta(json) {
|
|
123
|
+
if (!isRecord(json))
|
|
124
|
+
return undefined;
|
|
125
|
+
const data = isRecord(json.data) ? json.data : undefined;
|
|
126
|
+
const warning = asString(json.warning) ?? (data ? asString(data.warning) : undefined);
|
|
127
|
+
const creditsUsed = asNumber(json.creditsUsed) ?? (data ? asNumber(data.creditsUsed) : undefined);
|
|
128
|
+
if (warning === undefined && creditsUsed === undefined)
|
|
129
|
+
return undefined;
|
|
130
|
+
return { warning, creditsUsed };
|
|
131
|
+
}
|
|
132
|
+
function normalizeSearchEntry(entry, source) {
|
|
133
|
+
if (!isRecord(entry))
|
|
134
|
+
return undefined;
|
|
135
|
+
const url = asString(entry.url);
|
|
136
|
+
if (!url)
|
|
137
|
+
return undefined;
|
|
138
|
+
const markdown = asString(entry.markdown);
|
|
139
|
+
const description = asString(entry.description);
|
|
140
|
+
const snippet = source === "news" ? (asString(entry.snippet) ?? description ?? "") : description || markdown?.slice(0, 300) || "";
|
|
141
|
+
return {
|
|
142
|
+
title: asString(entry.title) || url,
|
|
143
|
+
url,
|
|
144
|
+
snippet,
|
|
145
|
+
publishedDate: asString(entry.publishedDate) ?? asString(entry.date),
|
|
146
|
+
score: asNumber(entry.score),
|
|
147
|
+
source,
|
|
148
|
+
...(source === "images"
|
|
149
|
+
? {
|
|
150
|
+
imageUrl: asString(entry.imageUrl) ?? asString(entry.image),
|
|
151
|
+
imageWidth: asNumber(entry.imageWidth),
|
|
152
|
+
imageHeight: asNumber(entry.imageHeight),
|
|
153
|
+
}
|
|
154
|
+
: {}),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Flatten Firecrawl's per-source buckets into one ordered list, each bucket
|
|
159
|
+
* trimmed to its requested budget. Web hits keep their inline markdown as the
|
|
160
|
+
* snippet; image hits point at the image and its source page.
|
|
161
|
+
*/
|
|
162
|
+
function normalizeSearchResponse(json, budgets) {
|
|
163
|
+
if (!isRecord(json))
|
|
164
|
+
return [];
|
|
165
|
+
const data = json.data;
|
|
166
|
+
const results = [];
|
|
167
|
+
for (const source of ["web", "images", "news"]) {
|
|
168
|
+
const budget = budgets[source];
|
|
169
|
+
if (budget === undefined)
|
|
170
|
+
continue;
|
|
171
|
+
const bucket = isRecord(data) ? data[source] : undefined;
|
|
172
|
+
const entries = Array.isArray(bucket) ? bucket : source === "web" && Array.isArray(data) ? data : undefined;
|
|
173
|
+
if (!entries)
|
|
174
|
+
continue;
|
|
175
|
+
let taken = 0;
|
|
176
|
+
for (const entry of entries) {
|
|
177
|
+
if (taken >= budget)
|
|
178
|
+
break;
|
|
179
|
+
const normalized = normalizeSearchEntry(entry, source);
|
|
180
|
+
if (!normalized)
|
|
181
|
+
continue;
|
|
182
|
+
results.push(normalized);
|
|
183
|
+
taken++;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return results;
|
|
187
|
+
}
|
|
188
|
+
function normalizeScrapeResponse(url, json) {
|
|
189
|
+
const data = isRecord(json) ? (isRecord(json.data) ? json.data : undefined) : undefined;
|
|
190
|
+
const markdown = (data ? asString(data.markdown) : undefined) ?? "";
|
|
191
|
+
const metadata = data && isRecord(data.metadata) ? data.metadata : undefined;
|
|
192
|
+
const title = (metadata ? asString(metadata.title) : undefined) ?? (data ? asString(data.title) : undefined) ?? url;
|
|
193
|
+
if (!markdown.trim()) {
|
|
194
|
+
throw new FirecrawlError(`Firecrawl scrape of ${url} returned no usable text`, {
|
|
195
|
+
code: "empty",
|
|
196
|
+
fallback: true,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return { url, title, markdown, fetchedAt: new Date().toISOString() };
|
|
200
|
+
}
|
|
201
|
+
export function createFirecrawlBackend(options = {}) {
|
|
202
|
+
const timeoutMs = options.timeoutMs ?? WEBFETCH_REQUEST_TIMEOUT_MS;
|
|
203
|
+
const post = options.post ?? defaultPost;
|
|
204
|
+
const headers = {};
|
|
205
|
+
if (options.apiKey) {
|
|
206
|
+
headers.authorization = `Bearer ${options.apiKey}`;
|
|
207
|
+
}
|
|
208
|
+
async function callApi(path, body, signal) {
|
|
209
|
+
let lastError;
|
|
210
|
+
for (let attempt = 1; attempt <= FIRECRAWL_502_MAX_ATTEMPTS; attempt++) {
|
|
211
|
+
if (signal?.aborted) {
|
|
212
|
+
throw new Error("Operation aborted");
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
const response = await post(path, body, { headers, timeoutMs, signal });
|
|
216
|
+
if (response.status === 502 && attempt < FIRECRAWL_502_MAX_ATTEMPTS) {
|
|
217
|
+
lastError = new FirecrawlError(`Firecrawl request to ${path} failed with status 502`, {
|
|
218
|
+
code: "transport",
|
|
219
|
+
status: 502,
|
|
220
|
+
fallback: true,
|
|
221
|
+
});
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
return response;
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
if (error instanceof FirecrawlError && error.status === 502 && attempt < FIRECRAWL_502_MAX_ATTEMPTS) {
|
|
228
|
+
lastError = error;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
throw lastError;
|
|
235
|
+
}
|
|
236
|
+
function throwForStatus(path, status, json) {
|
|
237
|
+
const detail = firecrawlErrorMessage(json);
|
|
238
|
+
// Keyless 401/403/429 is provider-side (anonymous pool or blocked network),
|
|
239
|
+
// not a transport blip: name the fix instead of the raw status.
|
|
240
|
+
if (!options.apiKey && (status === 401 || status === 403 || status === 429)) {
|
|
241
|
+
throw new FirecrawlError(keylessUnavailableMessage(status, path), {
|
|
242
|
+
code: "unavailable",
|
|
243
|
+
status,
|
|
244
|
+
fallback: true,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
const message = `Firecrawl request to ${path} failed with status ${status}${detail ? `: ${detail}` : ""}`;
|
|
248
|
+
if (status === 401 || status === 403) {
|
|
249
|
+
throw new FirecrawlError(message, { code: "transport", status, fallback: true });
|
|
250
|
+
}
|
|
251
|
+
if (status === 402 || status === 429 || status >= 500) {
|
|
252
|
+
throw new FirecrawlError(message, { code: "transport", status, fallback: true });
|
|
253
|
+
}
|
|
254
|
+
throw new FirecrawlError(message, { code: "transport", status, fallback: false });
|
|
255
|
+
}
|
|
256
|
+
const backend = {
|
|
257
|
+
id: "firecrawl",
|
|
258
|
+
lastMeta: undefined,
|
|
259
|
+
async search(intent, searchOptions) {
|
|
260
|
+
if (!intent.query) {
|
|
261
|
+
throw new Error("Search query must not be empty");
|
|
262
|
+
}
|
|
263
|
+
// Per-modality limits: sum the requested counts, then slice each bucket
|
|
264
|
+
// back to its own budget so one modality cannot starve another.
|
|
265
|
+
const sources = [];
|
|
266
|
+
if (intent.results.web !== undefined)
|
|
267
|
+
sources.push("web");
|
|
268
|
+
if (intent.results.images !== undefined)
|
|
269
|
+
sources.push("images");
|
|
270
|
+
if (intent.results.news !== undefined)
|
|
271
|
+
sources.push("news");
|
|
272
|
+
const budgets = {};
|
|
273
|
+
let total = 0;
|
|
274
|
+
for (const source of sources) {
|
|
275
|
+
const count = clampLimit(intent.results[source] ?? 0, {
|
|
276
|
+
fallback: 1,
|
|
277
|
+
min: 1,
|
|
278
|
+
max: WEBFETCH_FIRECRAWL_MAX_LIMIT,
|
|
279
|
+
});
|
|
280
|
+
budgets[source] = count;
|
|
281
|
+
total += count;
|
|
282
|
+
}
|
|
283
|
+
total = clampLimit(total, { fallback: 10, min: 1, max: WEBFETCH_FIRECRAWL_MAX_LIMIT });
|
|
284
|
+
const body = {
|
|
285
|
+
query: intent.query,
|
|
286
|
+
limit: total,
|
|
287
|
+
sources,
|
|
288
|
+
highlights: true,
|
|
289
|
+
timeout: timeoutMs,
|
|
290
|
+
};
|
|
291
|
+
if (intent.filters.domains) {
|
|
292
|
+
// Firecrawl treats includeDomains/excludeDomains as mutually exclusive;
|
|
293
|
+
// a request for both is narrowed to the include list.
|
|
294
|
+
body.includeDomains = intent.filters.domains;
|
|
295
|
+
}
|
|
296
|
+
if (intent.filters.recencyMs !== undefined) {
|
|
297
|
+
body.tbs = `qdr:d${Math.max(1, Math.round(intent.filters.recencyMs / (24 * 60 * 60 * 1000)))}`;
|
|
298
|
+
}
|
|
299
|
+
if (intent.filters.language) {
|
|
300
|
+
body.country = intent.filters.language;
|
|
301
|
+
}
|
|
302
|
+
// Page text is only useful for web hits; image and news hits carry their
|
|
303
|
+
// own metadata and are cheaper without a scrape.
|
|
304
|
+
if (intent.results.web !== undefined) {
|
|
305
|
+
body.scrapeOptions = { formats: ["markdown"], onlyMainContent: true };
|
|
306
|
+
}
|
|
307
|
+
const response = await callApi("/v2/search", body, searchOptions.signal);
|
|
308
|
+
if (response.status !== 200) {
|
|
309
|
+
throwForStatus("/v2/search", response.status, response.json);
|
|
310
|
+
}
|
|
311
|
+
if (isRecord(response.json) && response.json.success === false) {
|
|
312
|
+
throw new FirecrawlError(firecrawlErrorMessage(response.json) ?? "Firecrawl search failed", {
|
|
313
|
+
code: "transport",
|
|
314
|
+
status: response.status,
|
|
315
|
+
fallback: false,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
backend.lastMeta = readMeta(response.json);
|
|
319
|
+
return normalizeSearchResponse(response.json, budgets);
|
|
320
|
+
},
|
|
321
|
+
async fetch(url, fetchOptions) {
|
|
322
|
+
const response = await callApi("/v2/scrape", { url, formats: ["markdown"], onlyMainContent: true, timeout: timeoutMs }, fetchOptions.signal);
|
|
323
|
+
if (response.status !== 200) {
|
|
324
|
+
throwForStatus("/v2/scrape", response.status, response.json);
|
|
325
|
+
}
|
|
326
|
+
if (isRecord(response.json) && response.json.success === false) {
|
|
327
|
+
throw new FirecrawlError(firecrawlErrorMessage(response.json) ?? `Firecrawl scrape of ${url} failed`, {
|
|
328
|
+
code: "transport",
|
|
329
|
+
status: response.status,
|
|
330
|
+
fallback: false,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
backend.lastMeta = readMeta(response.json);
|
|
334
|
+
return normalizeScrapeResponse(url, response.json);
|
|
335
|
+
},
|
|
336
|
+
};
|
|
337
|
+
return backend;
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=backend-firecrawl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-firecrawl.js","sourceRoot":"","sources":["../../../src/core/webfetch/backend-firecrawl.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Firecrawl backend for webfetch: thin `undici` POSTs to the hosted Firecrawl\n * API. The SDK is never vendored (extra `axios` dep) and the server is never\n * vendored (AGPL-3.0).\n *\n * Auth is an optional `Bearer` key, omitted entirely on the keyless tier.\n * Resolve it with `resolveFirecrawlApiKey` (explicit settings value first,\n * `FIRECRAWL_API_KEY` env second).\n */\n\nimport { request as undiciRequest } from \"undici\";\nimport type { WebDocument, WebSearchBackend, WebSearchResult } from \"./backend.ts\";\nimport {\n\tclampLimit,\n\tWEBFETCH_FIRECRAWL_MAX_LIMIT,\n\tWEBFETCH_REQUEST_TIMEOUT_MS,\n\tWebfetchError,\n\ttype WebfetchErrorCode,\n} from \"./guardrails.ts\";\nimport type { ResolvedSearchIntent } from \"./search-intent.ts\";\n\nexport const FIRECRAWL_BASE_URL = \"https://api.firecrawl.dev\";\nexport const FIRECRAWL_API_KEY_ENV = \"FIRECRAWL_API_KEY\";\nconst FIRECRAWL_502_MAX_ATTEMPTS = 3;\nconst FIRECRAWL_HTTP_HEADROOM_MS = 5_000;\n\n/** Explicit settings value wins; `FIRECRAWL_API_KEY` env is the fallback. Keyless (undefined) works with lower limits. */\nexport function resolveFirecrawlApiKey(explicit?: string, env: NodeJS.ProcessEnv = process.env): string | undefined {\n\tconst trimmed = explicit?.trim() || env[FIRECRAWL_API_KEY_ENV]?.trim();\n\treturn trimmed || undefined;\n}\n\nexport class FirecrawlError extends WebfetchError {\n\treadonly status?: number;\n\t/** True when the caller should try the `undici` direct-fetch fallback (transport/auth failure, never content failure). */\n\treadonly fallback: boolean;\n\tconstructor(message: string, options: { code: WebfetchErrorCode; status?: number; fallback: boolean }) {\n\t\tsuper(message, options.code);\n\t\tthis.name = \"FirecrawlError\";\n\t\tthis.status = options.status;\n\t\tthis.fallback = options.fallback;\n\t}\n}\n\n/**\n * The keyless Firecrawl tier refused this network (403 \"your IP address looks\n * suspicious\", 401 without a key, or 429 on the shared anonymous pool). This is\n * provider-side and often IP-dependent, so the message names the exact fix\n * instead of leaking the raw status. Direct page fetch still works through the\n * `undici` fallback; only search is unavailable.\n */\nexport function keylessUnavailableMessage(status: number, path: string): string {\n\tconst reason =\n\t\tstatus === 429\n\t\t\t? \"the keyless rate limit was exhausted\"\n\t\t\t: status === 401\n\t\t\t\t? \"no API key was sent\"\n\t\t\t\t: \"this network is not allowed on the anonymous tier\";\n\treturn [\n\t\t`Firecrawl ${path} is unavailable: ${reason} (status ${status}).`,\n\t\t\"Set a Firecrawl API key to fix this: add the `firecrawlApiKey` setting or the\",\n\t\t\"`FIRECRAWL_API_KEY` environment variable, then retry.\",\n\t\t\"`webextract` still works without a key: it fetches pages directly.\",\n\t].join(\" \");\n}\n\n/** True when a failed Firecrawl call should fall back to direct `undici` fetch instead of surfacing the error. */\nexport function isFallbackEligible(error: unknown): boolean {\n\tif (error instanceof FirecrawlError) return error.fallback;\n\tif (error instanceof WebfetchError) {\n\t\treturn error.code === \"timeout\" || error.code === \"transport\" || error.code === \"empty\";\n\t}\n\treturn false;\n}\n\nexport interface FirecrawlResponseMeta {\n\twarning?: string;\n\tcreditsUsed?: number;\n}\n\nexport interface FirecrawlBackend extends WebSearchBackend {\n\treadonly id: \"firecrawl\";\n\t/** `warning`/`creditsUsed` from the most recent search or scrape, for cost observability in tool details. */\n\tlastMeta: FirecrawlResponseMeta | undefined;\n}\n\nexport type FirecrawlPostFn = (\n\tpath: string,\n\tbody: Record<string, unknown>,\n\tinit: { headers: Record<string, string>; timeoutMs: number; signal?: AbortSignal },\n) => Promise<{ status: number; json: unknown }>;\n\nasync function defaultPost(\n\tpath: string,\n\tbody: Record<string, unknown>,\n\tinit: { headers: Record<string, string>; timeoutMs: number; signal?: AbortSignal },\n): Promise<{ status: number; json: unknown }> {\n\tconst timeoutSignal = AbortSignal.timeout(init.timeoutMs + FIRECRAWL_HTTP_HEADROOM_MS);\n\tconst signal = init.signal ? AbortSignal.any([init.signal, timeoutSignal]) : timeoutSignal;\n\tlet response: Awaited<ReturnType<typeof undiciRequest>>;\n\ttry {\n\t\tresponse = await undiciRequest(`${FIRECRAWL_BASE_URL}${path}`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"content-type\": \"application/json\", ...init.headers },\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal,\n\t\t});\n\t} catch (error) {\n\t\tif (timeoutSignal.aborted && !init.signal?.aborted) {\n\t\t\tthrow new WebfetchError(`Firecrawl request to ${path} timed out`, \"timeout\");\n\t\t}\n\t\tif (init.signal?.aborted) {\n\t\t\tthrow new Error(\"Operation aborted\");\n\t\t}\n\t\tconst reason = error instanceof Error ? error.message : String(error);\n\t\tthrow new WebfetchError(`Firecrawl request to ${path} failed: ${reason}`, \"transport\");\n\t}\n\tlet text: string;\n\ttry {\n\t\ttext = await response.body.text();\n\t} catch (error) {\n\t\tconst reason = error instanceof Error ? error.message : String(error);\n\t\tthrow new WebfetchError(`Firecrawl request to ${path} failed: ${reason}`, \"transport\");\n\t}\n\tlet json: unknown;\n\ttry {\n\t\tjson = text ? (JSON.parse(text) as unknown) : undefined;\n\t} catch {\n\t\tthrow new WebfetchError(`Firecrawl request to ${path} returned invalid JSON`, \"transport\");\n\t}\n\treturn { status: response.statusCode, json };\n}\n\nexport interface FirecrawlBackendOptions {\n\tapiKey?: string;\n\ttimeoutMs?: number;\n\tpost?: FirecrawlPostFn;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction asString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n\treturn typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction firecrawlErrorMessage(json: unknown): string | undefined {\n\tif (!isRecord(json)) return undefined;\n\tconst direct = asString(json.error);\n\tif (direct) return direct;\n\tif (isRecord(json.data)) {\n\t\tconst nested = asString(json.data.error);\n\t\tif (nested) return nested;\n\t}\n\treturn undefined;\n}\n\nfunction readMeta(json: unknown): FirecrawlResponseMeta | undefined {\n\tif (!isRecord(json)) return undefined;\n\tconst data = isRecord(json.data) ? json.data : undefined;\n\tconst warning = asString(json.warning) ?? (data ? asString(data.warning) : undefined);\n\tconst creditsUsed = asNumber(json.creditsUsed) ?? (data ? asNumber(data.creditsUsed) : undefined);\n\tif (warning === undefined && creditsUsed === undefined) return undefined;\n\treturn { warning, creditsUsed };\n}\n\nfunction normalizeSearchEntry(entry: unknown, source: \"web\" | \"images\" | \"news\"): WebSearchResult | undefined {\n\tif (!isRecord(entry)) return undefined;\n\tconst url = asString(entry.url);\n\tif (!url) return undefined;\n\tconst markdown = asString(entry.markdown);\n\tconst description = asString(entry.description);\n\tconst snippet =\n\t\tsource === \"news\" ? (asString(entry.snippet) ?? description ?? \"\") : description || markdown?.slice(0, 300) || \"\";\n\treturn {\n\t\ttitle: asString(entry.title) || url,\n\t\turl,\n\t\tsnippet,\n\t\tpublishedDate: asString(entry.publishedDate) ?? asString(entry.date),\n\t\tscore: asNumber(entry.score),\n\t\tsource,\n\t\t...(source === \"images\"\n\t\t\t? {\n\t\t\t\t\timageUrl: asString(entry.imageUrl) ?? asString(entry.image),\n\t\t\t\t\timageWidth: asNumber(entry.imageWidth),\n\t\t\t\t\timageHeight: asNumber(entry.imageHeight),\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\n\n/**\n * Flatten Firecrawl's per-source buckets into one ordered list, each bucket\n * trimmed to its requested budget. Web hits keep their inline markdown as the\n * snippet; image hits point at the image and its source page.\n */\nfunction normalizeSearchResponse(json: unknown, budgets: Record<string, number>): WebSearchResult[] {\n\tif (!isRecord(json)) return [];\n\tconst data = json.data;\n\tconst results: WebSearchResult[] = [];\n\tfor (const source of [\"web\", \"images\", \"news\"] as const) {\n\t\tconst budget = budgets[source];\n\t\tif (budget === undefined) continue;\n\t\tconst bucket = isRecord(data) ? data[source] : undefined;\n\t\tconst entries = Array.isArray(bucket) ? bucket : source === \"web\" && Array.isArray(data) ? data : undefined;\n\t\tif (!entries) continue;\n\t\tlet taken = 0;\n\t\tfor (const entry of entries) {\n\t\t\tif (taken >= budget) break;\n\t\t\tconst normalized = normalizeSearchEntry(entry, source);\n\t\t\tif (!normalized) continue;\n\t\t\tresults.push(normalized);\n\t\t\ttaken++;\n\t\t}\n\t}\n\treturn results;\n}\n\nfunction normalizeScrapeResponse(url: string, json: unknown): WebDocument {\n\tconst data = isRecord(json) ? (isRecord(json.data) ? json.data : undefined) : undefined;\n\tconst markdown = (data ? asString(data.markdown) : undefined) ?? \"\";\n\tconst metadata = data && isRecord(data.metadata) ? data.metadata : undefined;\n\tconst title = (metadata ? asString(metadata.title) : undefined) ?? (data ? asString(data.title) : undefined) ?? url;\n\tif (!markdown.trim()) {\n\t\tthrow new FirecrawlError(`Firecrawl scrape of ${url} returned no usable text`, {\n\t\t\tcode: \"empty\",\n\t\t\tfallback: true,\n\t\t});\n\t}\n\treturn { url, title, markdown, fetchedAt: new Date().toISOString() };\n}\n\nexport function createFirecrawlBackend(options: FirecrawlBackendOptions = {}): FirecrawlBackend {\n\tconst timeoutMs = options.timeoutMs ?? WEBFETCH_REQUEST_TIMEOUT_MS;\n\tconst post = options.post ?? defaultPost;\n\tconst headers: Record<string, string> = {};\n\tif (options.apiKey) {\n\t\theaders.authorization = `Bearer ${options.apiKey}`;\n\t}\n\n\tasync function callApi(\n\t\tpath: string,\n\t\tbody: Record<string, unknown>,\n\t\tsignal?: AbortSignal,\n\t): Promise<{ status: number; json: unknown }> {\n\t\tlet lastError: unknown;\n\t\tfor (let attempt = 1; attempt <= FIRECRAWL_502_MAX_ATTEMPTS; attempt++) {\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"Operation aborted\");\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst response = await post(path, body, { headers, timeoutMs, signal });\n\t\t\t\tif (response.status === 502 && attempt < FIRECRAWL_502_MAX_ATTEMPTS) {\n\t\t\t\t\tlastError = new FirecrawlError(`Firecrawl request to ${path} failed with status 502`, {\n\t\t\t\t\t\tcode: \"transport\",\n\t\t\t\t\t\tstatus: 502,\n\t\t\t\t\t\tfallback: true,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\treturn response;\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof FirecrawlError && error.status === 502 && attempt < FIRECRAWL_502_MAX_ATTEMPTS) {\n\t\t\t\t\tlastError = error;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\tthrow lastError;\n\t}\n\n\tfunction throwForStatus(path: string, status: number, json: unknown): never {\n\t\tconst detail = firecrawlErrorMessage(json);\n\t\t// Keyless 401/403/429 is provider-side (anonymous pool or blocked network),\n\t\t// not a transport blip: name the fix instead of the raw status.\n\t\tif (!options.apiKey && (status === 401 || status === 403 || status === 429)) {\n\t\t\tthrow new FirecrawlError(keylessUnavailableMessage(status, path), {\n\t\t\t\tcode: \"unavailable\",\n\t\t\t\tstatus,\n\t\t\t\tfallback: true,\n\t\t\t});\n\t\t}\n\t\tconst message = `Firecrawl request to ${path} failed with status ${status}${detail ? `: ${detail}` : \"\"}`;\n\t\tif (status === 401 || status === 403) {\n\t\t\tthrow new FirecrawlError(message, { code: \"transport\", status, fallback: true });\n\t\t}\n\t\tif (status === 402 || status === 429 || status >= 500) {\n\t\t\tthrow new FirecrawlError(message, { code: \"transport\", status, fallback: true });\n\t\t}\n\t\tthrow new FirecrawlError(message, { code: \"transport\", status, fallback: false });\n\t}\n\n\tconst backend: FirecrawlBackend = {\n\t\tid: \"firecrawl\",\n\t\tlastMeta: undefined,\n\t\tasync search(\n\t\t\tintent: ResolvedSearchIntent,\n\t\t\tsearchOptions: { limit: number; signal?: AbortSignal },\n\t\t): Promise<WebSearchResult[]> {\n\t\t\tif (!intent.query) {\n\t\t\t\tthrow new Error(\"Search query must not be empty\");\n\t\t\t}\n\t\t\t// Per-modality limits: sum the requested counts, then slice each bucket\n\t\t\t// back to its own budget so one modality cannot starve another.\n\t\t\tconst sources: Array<\"web\" | \"images\" | \"news\"> = [];\n\t\t\tif (intent.results.web !== undefined) sources.push(\"web\");\n\t\t\tif (intent.results.images !== undefined) sources.push(\"images\");\n\t\t\tif (intent.results.news !== undefined) sources.push(\"news\");\n\t\t\tconst budgets: Record<string, number> = {};\n\t\t\tlet total = 0;\n\t\t\tfor (const source of sources) {\n\t\t\t\tconst count = clampLimit(intent.results[source] ?? 0, {\n\t\t\t\t\tfallback: 1,\n\t\t\t\t\tmin: 1,\n\t\t\t\t\tmax: WEBFETCH_FIRECRAWL_MAX_LIMIT,\n\t\t\t\t});\n\t\t\t\tbudgets[source] = count;\n\t\t\t\ttotal += count;\n\t\t\t}\n\t\t\ttotal = clampLimit(total, { fallback: 10, min: 1, max: WEBFETCH_FIRECRAWL_MAX_LIMIT });\n\n\t\t\tconst body: Record<string, unknown> = {\n\t\t\t\tquery: intent.query,\n\t\t\t\tlimit: total,\n\t\t\t\tsources,\n\t\t\t\thighlights: true,\n\t\t\t\ttimeout: timeoutMs,\n\t\t\t};\n\t\t\tif (intent.filters.domains) {\n\t\t\t\t// Firecrawl treats includeDomains/excludeDomains as mutually exclusive;\n\t\t\t\t// a request for both is narrowed to the include list.\n\t\t\t\tbody.includeDomains = intent.filters.domains;\n\t\t\t}\n\t\t\tif (intent.filters.recencyMs !== undefined) {\n\t\t\t\tbody.tbs = `qdr:d${Math.max(1, Math.round(intent.filters.recencyMs / (24 * 60 * 60 * 1000)))}`;\n\t\t\t}\n\t\t\tif (intent.filters.language) {\n\t\t\t\tbody.country = intent.filters.language;\n\t\t\t}\n\t\t\t// Page text is only useful for web hits; image and news hits carry their\n\t\t\t// own metadata and are cheaper without a scrape.\n\t\t\tif (intent.results.web !== undefined) {\n\t\t\t\tbody.scrapeOptions = { formats: [\"markdown\"], onlyMainContent: true };\n\t\t\t}\n\n\t\t\tconst response = await callApi(\"/v2/search\", body, searchOptions.signal);\n\t\t\tif (response.status !== 200) {\n\t\t\t\tthrowForStatus(\"/v2/search\", response.status, response.json);\n\t\t\t}\n\t\t\tif (isRecord(response.json) && response.json.success === false) {\n\t\t\t\tthrow new FirecrawlError(firecrawlErrorMessage(response.json) ?? \"Firecrawl search failed\", {\n\t\t\t\t\tcode: \"transport\",\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t\tfallback: false,\n\t\t\t\t});\n\t\t\t}\n\t\t\tbackend.lastMeta = readMeta(response.json);\n\t\t\treturn normalizeSearchResponse(response.json, budgets);\n\t\t},\n\t\tasync fetch(url: string, fetchOptions: { signal?: AbortSignal }): Promise<WebDocument> {\n\t\t\tconst response = await callApi(\n\t\t\t\t\"/v2/scrape\",\n\t\t\t\t{ url, formats: [\"markdown\"], onlyMainContent: true, timeout: timeoutMs },\n\t\t\t\tfetchOptions.signal,\n\t\t\t);\n\t\t\tif (response.status !== 200) {\n\t\t\t\tthrowForStatus(\"/v2/scrape\", response.status, response.json);\n\t\t\t}\n\t\t\tif (isRecord(response.json) && response.json.success === false) {\n\t\t\t\tthrow new FirecrawlError(firecrawlErrorMessage(response.json) ?? `Firecrawl scrape of ${url} failed`, {\n\t\t\t\t\tcode: \"transport\",\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t\tfallback: false,\n\t\t\t\t});\n\t\t\t}\n\t\t\tbackend.lastMeta = readMeta(response.json);\n\t\t\treturn normalizeScrapeResponse(url, response.json);\n\t\t},\n\t};\n\treturn backend;\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `undici` fallback backend for webfetch: direct fetch of the target URL under
|
|
3
|
+
* the shared guardrails, with minimal inline HTML→text cleanup (no readability
|
|
4
|
+
* dep, no new packages).
|
|
5
|
+
*
|
|
6
|
+
* Only `fetch` is supported. `search` has no direct-fetch equivalent, so it
|
|
7
|
+
* throws a named error instead of fabricating results.
|
|
8
|
+
*/
|
|
9
|
+
import type { WebFetchBackend } from "./backend.ts";
|
|
10
|
+
import { type DnsLookup, type LowLevelRequestFn } from "./guardrails.ts";
|
|
11
|
+
export interface UndiciBackendOptions {
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
maxBytes?: number;
|
|
14
|
+
maxRedirects?: number;
|
|
15
|
+
lookup?: DnsLookup;
|
|
16
|
+
request?: LowLevelRequestFn;
|
|
17
|
+
}
|
|
18
|
+
/** Minimal HTML→text cleanup: drop scripts/styles/comments/tags, decode entities, collapse whitespace. */
|
|
19
|
+
export declare function htmlToText(html: string): string;
|
|
20
|
+
export declare function createUndiciBackend(options?: UndiciBackendOptions): WebFetchBackend;
|
|
21
|
+
//# sourceMappingURL=backend-undici.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-undici.d.ts","sourceRoot":"","sources":["../../../src/core/webfetch/backend-undici.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAe,eAAe,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAEN,KAAK,SAAS,EAEd,KAAK,iBAAiB,EAKtB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,oBAAoB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAwBD,4GAA0G;AAC1G,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAe/C;AAoBD,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG,eAAe,CAgDvF","sourcesContent":["/**\n * `undici` fallback backend for webfetch: direct fetch of the target URL under\n * the shared guardrails, with minimal inline HTML→text cleanup (no readability\n * dep, no new packages).\n *\n * Only `fetch` is supported. `search` has no direct-fetch equivalent, so it\n * throws a named error instead of fabricating results.\n */\n\nimport type { WebDocument, WebFetchBackend } from \"./backend.ts\";\nimport {\n\tassertBytesWithinBudget,\n\ttype DnsLookup,\n\tguardedRequest,\n\ttype LowLevelRequestFn,\n\tWEBFETCH_MAX_BYTES,\n\tWEBFETCH_MAX_REDIRECTS,\n\tWEBFETCH_REQUEST_TIMEOUT_MS,\n\tWebfetchError,\n} from \"./guardrails.ts\";\n\nexport interface UndiciBackendOptions {\n\ttimeoutMs?: number;\n\tmaxBytes?: number;\n\tmaxRedirects?: number;\n\tlookup?: DnsLookup;\n\trequest?: LowLevelRequestFn;\n}\n\nfunction decodeEntities(text: string): string {\n\treturn text\n\t\t.replace(/&#(\\d+);/g, (_match, digits: string) => String.fromCodePoint(Number.parseInt(digits, 10)))\n\t\t.replace(/&#x([0-9a-fA-F]+);/g, (_match, digits: string) => String.fromCodePoint(Number.parseInt(digits, 16)))\n\t\t.replace(/&(amp|lt|gt|quot|apos|nbsp);/g, (_match, name: string) => {\n\t\t\tswitch (name) {\n\t\t\t\tcase \"amp\":\n\t\t\t\t\treturn \"&\";\n\t\t\t\tcase \"lt\":\n\t\t\t\t\treturn \"<\";\n\t\t\t\tcase \"gt\":\n\t\t\t\t\treturn \">\";\n\t\t\t\tcase \"quot\":\n\t\t\t\t\treturn '\"';\n\t\t\t\tcase \"apos\":\n\t\t\t\t\treturn \"'\";\n\t\t\t\tdefault:\n\t\t\t\t\treturn \" \";\n\t\t\t}\n\t\t});\n}\n\n/** Minimal HTML→text cleanup: drop scripts/styles/comments/tags, decode entities, collapse whitespace. */\nexport function htmlToText(html: string): string {\n\tconst withoutScripts = html\n\t\t.replace(/<head[\\s\\S]*?<\\/head\\s*>/gi, \" \")\n\t\t.replace(/<script[\\s\\S]*?<\\/script\\s*>/gi, \" \")\n\t\t.replace(/<style[\\s\\S]*?<\\/style\\s*>/gi, \" \")\n\t\t.replace(/<!--[\\s\\S]*?-->/g, \" \");\n\tconst withBreaks = withoutScripts\n\t\t.replace(/<br[^>]*>/gi, \"\\n\")\n\t\t.replace(/<\\/(p|div|h[1-6]|li|tr|table|section|article|header|footer|blockquote|pre)[^>]*>/gi, \"\\n\");\n\tconst withoutTags = withBreaks.replace(/<[^>]+>/g, \" \");\n\tconst lines = decodeEntities(withoutTags)\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.replace(/[ \\t\\r\\f\\v]+/g, \" \").trim())\n\t\t.filter((line) => line.length > 0);\n\treturn lines.join(\"\\n\");\n}\n\nfunction extractHtmlTitle(html: string): string | undefined {\n\tconst match = /<title[^>]*>([\\s\\S]*?)<\\/title\\s*>/i.exec(html);\n\tconst title = match?.[1] ? decodeEntities(match[1].replace(/\\s+/g, \" \").trim()) : undefined;\n\treturn title || undefined;\n}\n\nfunction isSupportedContentType(contentType: string): boolean {\n\tif (contentType === \"\") return true;\n\tconst type = contentType.split(\";\")[0]?.trim().toLowerCase() ?? \"\";\n\treturn (\n\t\ttype.startsWith(\"text/\") ||\n\t\ttype.includes(\"html\") ||\n\t\ttype.includes(\"json\") ||\n\t\ttype.includes(\"xml\") ||\n\t\ttype.includes(\"javascript\")\n\t);\n}\n\nexport function createUndiciBackend(options: UndiciBackendOptions = {}): WebFetchBackend {\n\tconst timeoutMs = options.timeoutMs ?? WEBFETCH_REQUEST_TIMEOUT_MS;\n\tconst maxBytes = options.maxBytes ?? WEBFETCH_MAX_BYTES;\n\tconst maxRedirects = options.maxRedirects ?? WEBFETCH_MAX_REDIRECTS;\n\treturn {\n\t\tid: \"undici\",\n\t\tasync search(): Promise<never> {\n\t\t\tthrow new WebfetchError(\n\t\t\t\t\"The undici backend does not support search; configure Firecrawl for search\",\n\t\t\t\t\"transport\",\n\t\t\t);\n\t\t},\n\t\tasync fetch(url: string, fetchOptions: { signal?: AbortSignal }): Promise<WebDocument> {\n\t\t\tconst response = await guardedRequest(url, {\n\t\t\t\ttimeoutMs,\n\t\t\t\tmaxBytes,\n\t\t\t\tmaxRedirects,\n\t\t\t\tsignal: fetchOptions.signal,\n\t\t\t\tlookup: options.lookup,\n\t\t\t\trequest: options.request,\n\t\t\t});\n\t\t\tconst contentType = response.headers[\"content-type\"] ?? \"\";\n\t\t\tif (!isSupportedContentType(contentType)) {\n\t\t\t\tthrow new WebfetchError(`Unsupported content type \"${contentType}\" for ${response.finalUrl}`, \"empty\");\n\t\t\t}\n\t\t\tconst chunks: Uint8Array[] = [];\n\t\t\tlet totalBytes = 0;\n\t\t\tfor await (const chunk of response.body) {\n\t\t\t\ttotalBytes += chunk.length;\n\t\t\t\tassertBytesWithinBudget(totalBytes, maxBytes);\n\t\t\t\tchunks.push(chunk);\n\t\t\t}\n\t\t\tconst merged = new Uint8Array(totalBytes);\n\t\t\tlet offset = 0;\n\t\t\tfor (const chunk of chunks) {\n\t\t\t\tmerged.set(chunk, offset);\n\t\t\t\toffset += chunk.length;\n\t\t\t}\n\t\t\tconst raw = new TextDecoder().decode(merged);\n\t\t\tconst looksLikeHtml = contentType.toLowerCase().includes(\"html\") || /^\\s*</.test(raw.slice(0, 1024));\n\t\t\tconst markdown = (looksLikeHtml ? htmlToText(raw) : raw.trim()).trim();\n\t\t\tif (!markdown) {\n\t\t\t\tthrow new WebfetchError(`Fetch of ${response.finalUrl} returned no usable text`, \"empty\");\n\t\t\t}\n\t\t\tconst title = (looksLikeHtml ? extractHtmlTitle(raw) : undefined) ?? response.finalUrl;\n\t\t\treturn { url: response.finalUrl, title, markdown, fetchedAt: new Date().toISOString() };\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `undici` fallback backend for webfetch: direct fetch of the target URL under
|
|
3
|
+
* the shared guardrails, with minimal inline HTML→text cleanup (no readability
|
|
4
|
+
* dep, no new packages).
|
|
5
|
+
*
|
|
6
|
+
* Only `fetch` is supported. `search` has no direct-fetch equivalent, so it
|
|
7
|
+
* throws a named error instead of fabricating results.
|
|
8
|
+
*/
|
|
9
|
+
import { assertBytesWithinBudget, guardedRequest, WEBFETCH_MAX_BYTES, WEBFETCH_MAX_REDIRECTS, WEBFETCH_REQUEST_TIMEOUT_MS, WebfetchError, } from "./guardrails.js";
|
|
10
|
+
function decodeEntities(text) {
|
|
11
|
+
return text
|
|
12
|
+
.replace(/&#(\d+);/g, (_match, digits) => String.fromCodePoint(Number.parseInt(digits, 10)))
|
|
13
|
+
.replace(/&#x([0-9a-fA-F]+);/g, (_match, digits) => String.fromCodePoint(Number.parseInt(digits, 16)))
|
|
14
|
+
.replace(/&(amp|lt|gt|quot|apos|nbsp);/g, (_match, name) => {
|
|
15
|
+
switch (name) {
|
|
16
|
+
case "amp":
|
|
17
|
+
return "&";
|
|
18
|
+
case "lt":
|
|
19
|
+
return "<";
|
|
20
|
+
case "gt":
|
|
21
|
+
return ">";
|
|
22
|
+
case "quot":
|
|
23
|
+
return '"';
|
|
24
|
+
case "apos":
|
|
25
|
+
return "'";
|
|
26
|
+
default:
|
|
27
|
+
return " ";
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** Minimal HTML→text cleanup: drop scripts/styles/comments/tags, decode entities, collapse whitespace. */
|
|
32
|
+
export function htmlToText(html) {
|
|
33
|
+
const withoutScripts = html
|
|
34
|
+
.replace(/<head[\s\S]*?<\/head\s*>/gi, " ")
|
|
35
|
+
.replace(/<script[\s\S]*?<\/script\s*>/gi, " ")
|
|
36
|
+
.replace(/<style[\s\S]*?<\/style\s*>/gi, " ")
|
|
37
|
+
.replace(/<!--[\s\S]*?-->/g, " ");
|
|
38
|
+
const withBreaks = withoutScripts
|
|
39
|
+
.replace(/<br[^>]*>/gi, "\n")
|
|
40
|
+
.replace(/<\/(p|div|h[1-6]|li|tr|table|section|article|header|footer|blockquote|pre)[^>]*>/gi, "\n");
|
|
41
|
+
const withoutTags = withBreaks.replace(/<[^>]+>/g, " ");
|
|
42
|
+
const lines = decodeEntities(withoutTags)
|
|
43
|
+
.split("\n")
|
|
44
|
+
.map((line) => line.replace(/[ \t\r\f\v]+/g, " ").trim())
|
|
45
|
+
.filter((line) => line.length > 0);
|
|
46
|
+
return lines.join("\n");
|
|
47
|
+
}
|
|
48
|
+
function extractHtmlTitle(html) {
|
|
49
|
+
const match = /<title[^>]*>([\s\S]*?)<\/title\s*>/i.exec(html);
|
|
50
|
+
const title = match?.[1] ? decodeEntities(match[1].replace(/\s+/g, " ").trim()) : undefined;
|
|
51
|
+
return title || undefined;
|
|
52
|
+
}
|
|
53
|
+
function isSupportedContentType(contentType) {
|
|
54
|
+
if (contentType === "")
|
|
55
|
+
return true;
|
|
56
|
+
const type = contentType.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
57
|
+
return (type.startsWith("text/") ||
|
|
58
|
+
type.includes("html") ||
|
|
59
|
+
type.includes("json") ||
|
|
60
|
+
type.includes("xml") ||
|
|
61
|
+
type.includes("javascript"));
|
|
62
|
+
}
|
|
63
|
+
export function createUndiciBackend(options = {}) {
|
|
64
|
+
const timeoutMs = options.timeoutMs ?? WEBFETCH_REQUEST_TIMEOUT_MS;
|
|
65
|
+
const maxBytes = options.maxBytes ?? WEBFETCH_MAX_BYTES;
|
|
66
|
+
const maxRedirects = options.maxRedirects ?? WEBFETCH_MAX_REDIRECTS;
|
|
67
|
+
return {
|
|
68
|
+
id: "undici",
|
|
69
|
+
async search() {
|
|
70
|
+
throw new WebfetchError("The undici backend does not support search; configure Firecrawl for search", "transport");
|
|
71
|
+
},
|
|
72
|
+
async fetch(url, fetchOptions) {
|
|
73
|
+
const response = await guardedRequest(url, {
|
|
74
|
+
timeoutMs,
|
|
75
|
+
maxBytes,
|
|
76
|
+
maxRedirects,
|
|
77
|
+
signal: fetchOptions.signal,
|
|
78
|
+
lookup: options.lookup,
|
|
79
|
+
request: options.request,
|
|
80
|
+
});
|
|
81
|
+
const contentType = response.headers["content-type"] ?? "";
|
|
82
|
+
if (!isSupportedContentType(contentType)) {
|
|
83
|
+
throw new WebfetchError(`Unsupported content type "${contentType}" for ${response.finalUrl}`, "empty");
|
|
84
|
+
}
|
|
85
|
+
const chunks = [];
|
|
86
|
+
let totalBytes = 0;
|
|
87
|
+
for await (const chunk of response.body) {
|
|
88
|
+
totalBytes += chunk.length;
|
|
89
|
+
assertBytesWithinBudget(totalBytes, maxBytes);
|
|
90
|
+
chunks.push(chunk);
|
|
91
|
+
}
|
|
92
|
+
const merged = new Uint8Array(totalBytes);
|
|
93
|
+
let offset = 0;
|
|
94
|
+
for (const chunk of chunks) {
|
|
95
|
+
merged.set(chunk, offset);
|
|
96
|
+
offset += chunk.length;
|
|
97
|
+
}
|
|
98
|
+
const raw = new TextDecoder().decode(merged);
|
|
99
|
+
const looksLikeHtml = contentType.toLowerCase().includes("html") || /^\s*</.test(raw.slice(0, 1024));
|
|
100
|
+
const markdown = (looksLikeHtml ? htmlToText(raw) : raw.trim()).trim();
|
|
101
|
+
if (!markdown) {
|
|
102
|
+
throw new WebfetchError(`Fetch of ${response.finalUrl} returned no usable text`, "empty");
|
|
103
|
+
}
|
|
104
|
+
const title = (looksLikeHtml ? extractHtmlTitle(raw) : undefined) ?? response.finalUrl;
|
|
105
|
+
return { url: response.finalUrl, title, markdown, fetchedAt: new Date().toISOString() };
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=backend-undici.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-undici.js","sourceRoot":"","sources":["../../../src/core/webfetch/backend-undici.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACN,uBAAuB,EAEvB,cAAc,EAEd,kBAAkB,EAClB,sBAAsB,EACtB,2BAA2B,EAC3B,aAAa,GACb,MAAM,iBAAiB,CAAC;AAUzB,SAAS,cAAc,CAAC,IAAY,EAAU;IAC7C,OAAO,IAAI;SACT,OAAO,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;SACnG,OAAO,CAAC,qBAAqB,EAAE,CAAC,MAAM,EAAE,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;SAC7G,OAAO,CAAC,+BAA+B,EAAE,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE,CAAC;QACnE,QAAQ,IAAI,EAAE,CAAC;YACd,KAAK,KAAK;gBACT,OAAO,GAAG,CAAC;YACZ,KAAK,IAAI;gBACR,OAAO,GAAG,CAAC;YACZ,KAAK,IAAI;gBACR,OAAO,GAAG,CAAC;YACZ,KAAK,MAAM;gBACV,OAAO,GAAG,CAAC;YACZ,KAAK,MAAM;gBACV,OAAO,GAAG,CAAC;YACZ;gBACC,OAAO,GAAG,CAAC;QACb,CAAC;IAAA,CACD,CAAC,CAAC;AAAA,CACJ;AAED,4GAA0G;AAC1G,MAAM,UAAU,UAAU,CAAC,IAAY,EAAU;IAChD,MAAM,cAAc,GAAG,IAAI;SACzB,OAAO,CAAC,4BAA4B,EAAE,GAAG,CAAC;SAC1C,OAAO,CAAC,gCAAgC,EAAE,GAAG,CAAC;SAC9C,OAAO,CAAC,8BAA8B,EAAE,GAAG,CAAC;SAC5C,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,cAAc;SAC/B,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC;SAC5B,OAAO,CAAC,oFAAoF,EAAE,IAAI,CAAC,CAAC;IACtG,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,cAAc,CAAC,WAAW,CAAC;SACvC,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;SACxD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACpC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CACxB;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAsB;IAC3D,MAAM,KAAK,GAAG,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5F,OAAO,KAAK,IAAI,SAAS,CAAC;AAAA,CAC1B;AAED,SAAS,sBAAsB,CAAC,WAAmB,EAAW;IAC7D,IAAI,WAAW,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IACnE,OAAO,CACN,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QACxB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QACpB,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAC3B,CAAC;AAAA,CACF;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAO,GAAyB,EAAE,EAAmB;IACxF,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,2BAA2B,CAAC;IACnE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,kBAAkB,CAAC;IACxD,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,sBAAsB,CAAC;IACpE,OAAO;QACN,EAAE,EAAE,QAAQ;QACZ,KAAK,CAAC,MAAM,GAAmB;YAC9B,MAAM,IAAI,aAAa,CACtB,4EAA4E,EAC5E,WAAW,CACX,CAAC;QAAA,CACF;QACD,KAAK,CAAC,KAAK,CAAC,GAAW,EAAE,YAAsC,EAAwB;YACtF,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE;gBAC1C,SAAS;gBACT,QAAQ;gBACR,YAAY;gBACZ,MAAM,EAAE,YAAY,CAAC,MAAM;gBAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;aACxB,CAAC,CAAC;YACH,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YAC3D,IAAI,CAAC,sBAAsB,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,aAAa,CAAC,6BAA6B,WAAW,SAAS,QAAQ,CAAC,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC;YACxG,CAAC;YACD,MAAM,MAAM,GAAiB,EAAE,CAAC;YAChC,IAAI,UAAU,GAAG,CAAC,CAAC;YACnB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACzC,UAAU,IAAI,KAAK,CAAC,MAAM,CAAC;gBAC3B,uBAAuB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;gBAC9C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;YAC1C,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC5B,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;YACxB,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC7C,MAAM,aAAa,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YACrG,MAAM,QAAQ,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACvE,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACf,MAAM,IAAI,aAAa,CAAC,YAAY,QAAQ,CAAC,QAAQ,0BAA0B,EAAE,OAAO,CAAC,CAAC;YAC3F,CAAC;YACD,MAAM,KAAK,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC;YACvF,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QAAA,CACxF;KACD,CAAC;AAAA,CACF","sourcesContent":["/**\n * `undici` fallback backend for webfetch: direct fetch of the target URL under\n * the shared guardrails, with minimal inline HTML→text cleanup (no readability\n * dep, no new packages).\n *\n * Only `fetch` is supported. `search` has no direct-fetch equivalent, so it\n * throws a named error instead of fabricating results.\n */\n\nimport type { WebDocument, WebFetchBackend } from \"./backend.ts\";\nimport {\n\tassertBytesWithinBudget,\n\ttype DnsLookup,\n\tguardedRequest,\n\ttype LowLevelRequestFn,\n\tWEBFETCH_MAX_BYTES,\n\tWEBFETCH_MAX_REDIRECTS,\n\tWEBFETCH_REQUEST_TIMEOUT_MS,\n\tWebfetchError,\n} from \"./guardrails.ts\";\n\nexport interface UndiciBackendOptions {\n\ttimeoutMs?: number;\n\tmaxBytes?: number;\n\tmaxRedirects?: number;\n\tlookup?: DnsLookup;\n\trequest?: LowLevelRequestFn;\n}\n\nfunction decodeEntities(text: string): string {\n\treturn text\n\t\t.replace(/&#(\\d+);/g, (_match, digits: string) => String.fromCodePoint(Number.parseInt(digits, 10)))\n\t\t.replace(/&#x([0-9a-fA-F]+);/g, (_match, digits: string) => String.fromCodePoint(Number.parseInt(digits, 16)))\n\t\t.replace(/&(amp|lt|gt|quot|apos|nbsp);/g, (_match, name: string) => {\n\t\t\tswitch (name) {\n\t\t\t\tcase \"amp\":\n\t\t\t\t\treturn \"&\";\n\t\t\t\tcase \"lt\":\n\t\t\t\t\treturn \"<\";\n\t\t\t\tcase \"gt\":\n\t\t\t\t\treturn \">\";\n\t\t\t\tcase \"quot\":\n\t\t\t\t\treturn '\"';\n\t\t\t\tcase \"apos\":\n\t\t\t\t\treturn \"'\";\n\t\t\t\tdefault:\n\t\t\t\t\treturn \" \";\n\t\t\t}\n\t\t});\n}\n\n/** Minimal HTML→text cleanup: drop scripts/styles/comments/tags, decode entities, collapse whitespace. */\nexport function htmlToText(html: string): string {\n\tconst withoutScripts = html\n\t\t.replace(/<head[\\s\\S]*?<\\/head\\s*>/gi, \" \")\n\t\t.replace(/<script[\\s\\S]*?<\\/script\\s*>/gi, \" \")\n\t\t.replace(/<style[\\s\\S]*?<\\/style\\s*>/gi, \" \")\n\t\t.replace(/<!--[\\s\\S]*?-->/g, \" \");\n\tconst withBreaks = withoutScripts\n\t\t.replace(/<br[^>]*>/gi, \"\\n\")\n\t\t.replace(/<\\/(p|div|h[1-6]|li|tr|table|section|article|header|footer|blockquote|pre)[^>]*>/gi, \"\\n\");\n\tconst withoutTags = withBreaks.replace(/<[^>]+>/g, \" \");\n\tconst lines = decodeEntities(withoutTags)\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.replace(/[ \\t\\r\\f\\v]+/g, \" \").trim())\n\t\t.filter((line) => line.length > 0);\n\treturn lines.join(\"\\n\");\n}\n\nfunction extractHtmlTitle(html: string): string | undefined {\n\tconst match = /<title[^>]*>([\\s\\S]*?)<\\/title\\s*>/i.exec(html);\n\tconst title = match?.[1] ? decodeEntities(match[1].replace(/\\s+/g, \" \").trim()) : undefined;\n\treturn title || undefined;\n}\n\nfunction isSupportedContentType(contentType: string): boolean {\n\tif (contentType === \"\") return true;\n\tconst type = contentType.split(\";\")[0]?.trim().toLowerCase() ?? \"\";\n\treturn (\n\t\ttype.startsWith(\"text/\") ||\n\t\ttype.includes(\"html\") ||\n\t\ttype.includes(\"json\") ||\n\t\ttype.includes(\"xml\") ||\n\t\ttype.includes(\"javascript\")\n\t);\n}\n\nexport function createUndiciBackend(options: UndiciBackendOptions = {}): WebFetchBackend {\n\tconst timeoutMs = options.timeoutMs ?? WEBFETCH_REQUEST_TIMEOUT_MS;\n\tconst maxBytes = options.maxBytes ?? WEBFETCH_MAX_BYTES;\n\tconst maxRedirects = options.maxRedirects ?? WEBFETCH_MAX_REDIRECTS;\n\treturn {\n\t\tid: \"undici\",\n\t\tasync search(): Promise<never> {\n\t\t\tthrow new WebfetchError(\n\t\t\t\t\"The undici backend does not support search; configure Firecrawl for search\",\n\t\t\t\t\"transport\",\n\t\t\t);\n\t\t},\n\t\tasync fetch(url: string, fetchOptions: { signal?: AbortSignal }): Promise<WebDocument> {\n\t\t\tconst response = await guardedRequest(url, {\n\t\t\t\ttimeoutMs,\n\t\t\t\tmaxBytes,\n\t\t\t\tmaxRedirects,\n\t\t\t\tsignal: fetchOptions.signal,\n\t\t\t\tlookup: options.lookup,\n\t\t\t\trequest: options.request,\n\t\t\t});\n\t\t\tconst contentType = response.headers[\"content-type\"] ?? \"\";\n\t\t\tif (!isSupportedContentType(contentType)) {\n\t\t\t\tthrow new WebfetchError(`Unsupported content type \"${contentType}\" for ${response.finalUrl}`, \"empty\");\n\t\t\t}\n\t\t\tconst chunks: Uint8Array[] = [];\n\t\t\tlet totalBytes = 0;\n\t\t\tfor await (const chunk of response.body) {\n\t\t\t\ttotalBytes += chunk.length;\n\t\t\t\tassertBytesWithinBudget(totalBytes, maxBytes);\n\t\t\t\tchunks.push(chunk);\n\t\t\t}\n\t\t\tconst merged = new Uint8Array(totalBytes);\n\t\t\tlet offset = 0;\n\t\t\tfor (const chunk of chunks) {\n\t\t\t\tmerged.set(chunk, offset);\n\t\t\t\toffset += chunk.length;\n\t\t\t}\n\t\t\tconst raw = new TextDecoder().decode(merged);\n\t\t\tconst looksLikeHtml = contentType.toLowerCase().includes(\"html\") || /^\\s*</.test(raw.slice(0, 1024));\n\t\t\tconst markdown = (looksLikeHtml ? htmlToText(raw) : raw.trim()).trim();\n\t\t\tif (!markdown) {\n\t\t\t\tthrow new WebfetchError(`Fetch of ${response.finalUrl} returned no usable text`, \"empty\");\n\t\t\t}\n\t\t\tconst title = (looksLikeHtml ? extractHtmlTitle(raw) : undefined) ?? response.finalUrl;\n\t\t\treturn { url: response.finalUrl, title, markdown, fetchedAt: new Date().toISOString() };\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared shapes for harness-native web search and extraction.
|
|
3
|
+
*
|
|
4
|
+
* Normalization keeps backends interchangeable: Firecrawl `web[]`/`images[]`/
|
|
5
|
+
* `news[]` entries and raw HTML all collapse to these shapes, and every backend
|
|
6
|
+
* receives the same `ResolvedSearchIntent` (see search-intent.ts).
|
|
7
|
+
*/
|
|
8
|
+
import type { ResolvedSearchIntent } from "./search-intent.ts";
|
|
9
|
+
export interface WebSearchResult {
|
|
10
|
+
title: string;
|
|
11
|
+
url: string;
|
|
12
|
+
snippet: string;
|
|
13
|
+
publishedDate?: string;
|
|
14
|
+
score?: number;
|
|
15
|
+
/** Which modality produced this hit (`web`, `images`, `news`). */
|
|
16
|
+
source?: "web" | "images" | "news";
|
|
17
|
+
/** Image hits: the image URL and its source page. */
|
|
18
|
+
imageUrl?: string;
|
|
19
|
+
imageWidth?: number;
|
|
20
|
+
imageHeight?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface WebDocument {
|
|
23
|
+
url: string;
|
|
24
|
+
title: string;
|
|
25
|
+
markdown: string;
|
|
26
|
+
fetchedAt: string;
|
|
27
|
+
}
|
|
28
|
+
export interface WebSearchBackend {
|
|
29
|
+
readonly id: "firecrawl" | "exa" | "undici";
|
|
30
|
+
search(intent: ResolvedSearchIntent, options: {
|
|
31
|
+
limit: number;
|
|
32
|
+
signal?: AbortSignal;
|
|
33
|
+
}): Promise<WebSearchResult[]>;
|
|
34
|
+
fetch(url: string, options: {
|
|
35
|
+
signal?: AbortSignal;
|
|
36
|
+
}): Promise<WebDocument>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Backends that can actually return a page. Exa is search-only in ion, so a
|
|
40
|
+
* document store entry can only ever come from Firecrawl or the undici fallback.
|
|
41
|
+
*/
|
|
42
|
+
export type WebFetchBackend = WebSearchBackend & {
|
|
43
|
+
readonly id: "firecrawl" | "undici";
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../../src/core/webfetch/backend.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACnC,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,EAAE,EAAE,WAAW,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC5C,MAAM,CAAC,MAAM,EAAE,oBAAoB,EAAE,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACnH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAC5E;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,WAAW,GAAG,QAAQ,CAAA;CAAE,CAAC","sourcesContent":["/**\n * Shared shapes for harness-native web search and extraction.\n *\n * Normalization keeps backends interchangeable: Firecrawl `web[]`/`images[]`/\n * `news[]` entries and raw HTML all collapse to these shapes, and every backend\n * receives the same `ResolvedSearchIntent` (see search-intent.ts).\n */\n\nimport type { ResolvedSearchIntent } from \"./search-intent.ts\";\n\nexport interface WebSearchResult {\n\ttitle: string;\n\turl: string;\n\tsnippet: string;\n\tpublishedDate?: string;\n\tscore?: number;\n\t/** Which modality produced this hit (`web`, `images`, `news`). */\n\tsource?: \"web\" | \"images\" | \"news\";\n\t/** Image hits: the image URL and its source page. */\n\timageUrl?: string;\n\timageWidth?: number;\n\timageHeight?: number;\n}\n\nexport interface WebDocument {\n\turl: string;\n\ttitle: string;\n\tmarkdown: string;\n\tfetchedAt: string;\n}\n\nexport interface WebSearchBackend {\n\treadonly id: \"firecrawl\" | \"exa\" | \"undici\";\n\tsearch(intent: ResolvedSearchIntent, options: { limit: number; signal?: AbortSignal }): Promise<WebSearchResult[]>;\n\tfetch(url: string, options: { signal?: AbortSignal }): Promise<WebDocument>;\n}\n\n/**\n * Backends that can actually return a page. Exa is search-only in ion, so a\n * document store entry can only ever come from Firecrawl or the undici fallback.\n */\nexport type WebFetchBackend = WebSearchBackend & { readonly id: \"firecrawl\" | \"undici\" };\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared shapes for harness-native web search and extraction.
|
|
3
|
+
*
|
|
4
|
+
* Normalization keeps backends interchangeable: Firecrawl `web[]`/`images[]`/
|
|
5
|
+
* `news[]` entries and raw HTML all collapse to these shapes, and every backend
|
|
6
|
+
* receives the same `ResolvedSearchIntent` (see search-intent.ts).
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../../../src/core/webfetch/backend.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * Shared shapes for harness-native web search and extraction.\n *\n * Normalization keeps backends interchangeable: Firecrawl `web[]`/`images[]`/\n * `news[]` entries and raw HTML all collapse to these shapes, and every backend\n * receives the same `ResolvedSearchIntent` (see search-intent.ts).\n */\n\nimport type { ResolvedSearchIntent } from \"./search-intent.ts\";\n\nexport interface WebSearchResult {\n\ttitle: string;\n\turl: string;\n\tsnippet: string;\n\tpublishedDate?: string;\n\tscore?: number;\n\t/** Which modality produced this hit (`web`, `images`, `news`). */\n\tsource?: \"web\" | \"images\" | \"news\";\n\t/** Image hits: the image URL and its source page. */\n\timageUrl?: string;\n\timageWidth?: number;\n\timageHeight?: number;\n}\n\nexport interface WebDocument {\n\turl: string;\n\ttitle: string;\n\tmarkdown: string;\n\tfetchedAt: string;\n}\n\nexport interface WebSearchBackend {\n\treadonly id: \"firecrawl\" | \"exa\" | \"undici\";\n\tsearch(intent: ResolvedSearchIntent, options: { limit: number; signal?: AbortSignal }): Promise<WebSearchResult[]>;\n\tfetch(url: string, options: { signal?: AbortSignal }): Promise<WebDocument>;\n}\n\n/**\n * Backends that can actually return a page. Exa is search-only in ion, so a\n * document store entry can only ever come from Firecrawl or the undici fallback.\n */\nexport type WebFetchBackend = WebSearchBackend & { readonly id: \"firecrawl\" | \"undici\" };\n"]}
|