@humain/terminal 0.0.2 → 0.0.3-beta.1
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 +251 -24
- package/README.md +143 -119
- package/dist/cli/args.d.ts +4 -2
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +37 -39
- package/dist/cli/args.js.map +1 -1
- 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.map +1 -1
- package/dist/cli/config-selector.js +2 -2
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/credential-print.d.ts +5 -15
- package/dist/cli/credential-print.d.ts.map +1 -1
- package/dist/cli/credential-print.js +42 -83
- package/dist/cli/credential-print.js.map +1 -1
- package/dist/cli/experimental/auth.d.ts +16 -0
- package/dist/cli/experimental/auth.d.ts.map +1 -0
- package/dist/cli/experimental/auth.js +13 -0
- package/dist/cli/experimental/auth.js.map +1 -0
- package/dist/cli/experimental/cli.d.ts +6 -0
- package/dist/cli/experimental/cli.d.ts.map +1 -0
- package/dist/cli/experimental/cli.js +5 -0
- package/dist/cli/experimental/cli.js.map +1 -0
- package/dist/cli/experimental/command-options.d.ts +17 -0
- package/dist/cli/experimental/command-options.d.ts.map +1 -0
- package/dist/cli/experimental/command-options.js +35 -0
- package/dist/cli/experimental/command-options.js.map +1 -0
- package/dist/cli/experimental/command.d.ts +63 -0
- package/dist/cli/experimental/command.d.ts.map +1 -0
- package/dist/cli/experimental/command.js +130 -0
- package/dist/cli/experimental/command.js.map +1 -0
- package/dist/cli/experimental/commands/client.d.ts +13 -0
- package/dist/cli/experimental/commands/client.d.ts.map +1 -0
- package/dist/cli/experimental/commands/client.js +25 -0
- package/dist/cli/experimental/commands/client.js.map +1 -0
- package/dist/cli/experimental/commands/pi.d.ts +15 -0
- package/dist/cli/experimental/commands/pi.d.ts.map +1 -0
- package/dist/cli/experimental/commands/pi.js +28 -0
- package/dist/cli/experimental/commands/pi.js.map +1 -0
- package/dist/cli/experimental/commands/server.d.ts +13 -0
- package/dist/cli/experimental/commands/server.d.ts.map +1 -0
- package/dist/cli/experimental/commands/server.js +25 -0
- package/dist/cli/experimental/commands/server.js.map +1 -0
- package/dist/cli/experimental/transport-address.d.ts +10 -0
- package/dist/cli/experimental/transport-address.d.ts.map +1 -0
- package/dist/cli/experimental/transport-address.js +38 -0
- package/dist/cli/experimental/transport-address.js.map +1 -0
- package/dist/cli/list-models.d.ts +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js +2 -2
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/startup-ui.d.ts +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +2 -2
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +3 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/remote-session.d.ts +53 -0
- package/dist/client/remote-session.d.ts.map +1 -0
- package/dist/client/remote-session.js +340 -0
- package/dist/client/remote-session.js.map +1 -0
- package/dist/client/transcript.d.ts +12 -0
- package/dist/client/transcript.d.ts.map +1 -0
- package/dist/client/transcript.js +98 -0
- package/dist/client/transcript.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +4 -3
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -10
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +72 -70
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +25 -9
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +237 -39
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +60 -41
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +2 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +3 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +27 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +5 -0
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/keybindings.d.ts +45 -5
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-config.d.ts +29 -5
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +4 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -3
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +13 -10
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +4 -3
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +42 -10
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +30 -13
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +233 -73
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/models-store.d.ts +12 -7
- package/dist/core/models-store.d.ts.map +1 -1
- package/dist/core/models-store.js +83 -14
- package/dist/core/models-store.js.map +1 -1
- package/dist/core/package-manager.d.ts +6 -3
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +80 -61
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/pi-manifest.d.ts +8 -0
- package/dist/core/pi-manifest.d.ts.map +1 -0
- package/dist/core/pi-manifest.js +28 -0
- package/dist/core/pi-manifest.js.map +1 -0
- package/dist/core/provider-composer.d.ts +4 -1
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +36 -15
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +73 -67
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +2 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/runtime-credentials.d.ts +5 -5
- package/dist/core/runtime-credentials.d.ts.map +1 -1
- package/dist/core/runtime-credentials.js +11 -8
- package/dist/core/runtime-credentials.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +2 -2
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +3 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +12 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +40 -16
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +8 -0
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +5 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +16 -15
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts +4 -0
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +11 -7
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts +7 -0
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +16 -19
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +4 -0
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +5 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts +4 -0
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +5 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts +4 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +7 -3
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts +4 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +6 -2
- package/dist/core/tools/write.js.map +1 -1
- package/dist/extensions/llama/index.d.ts.map +1 -1
- package/dist/extensions/llama/index.js +11 -2
- package/dist/extensions/llama/index.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +21 -7
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/humain/agent-execution-protocol.d.ts +218 -0
- package/dist/humain/agent-execution-protocol.d.ts.map +1 -0
- package/dist/humain/agent-execution-protocol.js +204 -0
- package/dist/humain/agent-execution-protocol.js.map +1 -0
- package/dist/humain/agent-execution-runtime.d.ts +35 -0
- package/dist/humain/agent-execution-runtime.d.ts.map +1 -0
- package/dist/humain/agent-execution-runtime.js +170 -0
- package/dist/humain/agent-execution-runtime.js.map +1 -0
- package/dist/humain/index.d.ts.map +1 -1
- package/dist/humain/index.js +8 -7
- package/dist/humain/index.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/CHANGELOG.md +673 -0
- package/dist/humain/mcp-adapter/vendor/LICENSE +21 -0
- package/dist/humain/mcp-adapter/vendor/README.md +736 -0
- package/dist/humain/mcp-adapter/vendor/abort.ts +34 -0
- package/dist/humain/mcp-adapter/vendor/agent-dir.ts +68 -0
- package/dist/humain/mcp-adapter/vendor/agent-plugin-loader.ts +377 -0
- package/dist/humain/mcp-adapter/vendor/app-bridge.bundle.js +67 -0
- package/dist/humain/mcp-adapter/vendor/banner.png +0 -0
- package/dist/humain/mcp-adapter/vendor/cli.js +230 -0
- package/dist/humain/mcp-adapter/vendor/commands.ts +627 -0
- package/dist/humain/mcp-adapter/vendor/config.ts +1226 -0
- package/dist/humain/mcp-adapter/vendor/consent-manager.ts +64 -0
- package/dist/humain/mcp-adapter/vendor/direct-tools.ts +607 -0
- package/dist/humain/mcp-adapter/vendor/elicitation-handler.ts +348 -0
- package/dist/humain/mcp-adapter/vendor/error-signal.ts +21 -0
- package/dist/humain/mcp-adapter/vendor/errors.ts +223 -0
- package/dist/humain/mcp-adapter/vendor/glimpse-ui.ts +80 -0
- package/dist/humain/mcp-adapter/vendor/host-html-template.ts +461 -0
- package/dist/humain/mcp-adapter/vendor/index.bundle.d.mts +4 -0
- package/dist/humain/mcp-adapter/vendor/index.bundle.mjs +16279 -0
- package/dist/humain/mcp-adapter/vendor/index.ts +898 -0
- package/dist/humain/mcp-adapter/vendor/init.ts +649 -0
- package/dist/humain/mcp-adapter/vendor/json-schema-validator.ts +69 -0
- package/dist/humain/mcp-adapter/vendor/lifecycle.ts +147 -0
- package/dist/humain/mcp-adapter/vendor/logger.ts +169 -0
- package/dist/humain/mcp-adapter/vendor/mcp-auth-flow.ts +993 -0
- package/dist/humain/mcp-adapter/vendor/mcp-auth.ts +1000 -0
- package/dist/humain/mcp-adapter/vendor/mcp-callback-server.ts +510 -0
- package/dist/humain/mcp-adapter/vendor/mcp-code.ts +354 -0
- package/dist/humain/mcp-adapter/vendor/mcp-keyring-helper.cjs +89 -0
- package/dist/humain/mcp-adapter/vendor/mcp-oauth-provider.ts +616 -0
- package/dist/humain/mcp-adapter/vendor/mcp-output-guard.ts +408 -0
- package/dist/humain/mcp-adapter/vendor/mcp-panel.ts +1015 -0
- package/dist/humain/mcp-adapter/vendor/mcp-probe.ts +187 -0
- package/dist/humain/mcp-adapter/vendor/mcp-script-worker.mjs +130 -0
- package/dist/humain/mcp-adapter/vendor/mcp-setup-panel.ts +667 -0
- package/dist/humain/mcp-adapter/vendor/mcp-status.ts +109 -0
- package/dist/humain/mcp-adapter/vendor/mcp-trace.ts +306 -0
- package/dist/humain/mcp-adapter/vendor/metadata-cache.ts +363 -0
- package/dist/humain/mcp-adapter/vendor/npx-resolver.ts +543 -0
- package/dist/humain/mcp-adapter/vendor/oauth-handler.ts +30 -0
- package/dist/humain/mcp-adapter/vendor/oauth.ts +48 -0
- package/dist/humain/mcp-adapter/vendor/onboarding-state.ts +76 -0
- package/dist/humain/mcp-adapter/vendor/package.json +179 -0
- package/dist/humain/mcp-adapter/vendor/panel-keys.ts +53 -0
- package/dist/humain/mcp-adapter/vendor/prompts.ts +353 -0
- package/dist/humain/mcp-adapter/vendor/proxy-modes.ts +1331 -0
- package/dist/humain/mcp-adapter/vendor/request-headers-command.ts +336 -0
- package/dist/humain/mcp-adapter/vendor/resource-tools.ts +17 -0
- package/dist/humain/mcp-adapter/vendor/runtime-owner.ts +91 -0
- package/dist/humain/mcp-adapter/vendor/sampling-handler.ts +284 -0
- package/dist/humain/mcp-adapter/vendor/search-ranking.ts +206 -0
- package/dist/humain/mcp-adapter/vendor/server-manager.ts +1129 -0
- package/dist/humain/mcp-adapter/vendor/session-recovery.ts +151 -0
- package/dist/humain/mcp-adapter/vendor/skills/mcp-scripting/SKILL.md +38 -0
- package/dist/humain/mcp-adapter/vendor/state.ts +62 -0
- package/dist/humain/mcp-adapter/vendor/tool-approval.ts +182 -0
- package/dist/humain/mcp-adapter/vendor/tool-metadata.ts +296 -0
- package/dist/humain/mcp-adapter/vendor/tool-registrar.ts +253 -0
- package/dist/humain/mcp-adapter/vendor/tool-result-renderer.ts +423 -0
- package/dist/humain/mcp-adapter/vendor/ts-shape.ts +149 -0
- package/dist/humain/mcp-adapter/vendor/types.ts +942 -0
- package/dist/humain/mcp-adapter/vendor/ui-app-bridge-helpers.ts +40 -0
- package/dist/humain/mcp-adapter/vendor/ui-resource-handler.ts +250 -0
- package/dist/humain/mcp-adapter/vendor/ui-server.ts +866 -0
- package/dist/humain/mcp-adapter/vendor/ui-session.ts +570 -0
- package/dist/humain/mcp-adapter/vendor/ui-stream-types.ts +89 -0
- package/dist/humain/mcp-adapter/vendor/ui-tool-visibility.ts +25 -0
- package/dist/humain/mcp-adapter/vendor/unix-socket-transport.ts +85 -0
- package/dist/humain/mcp-adapter/vendor/utils.ts +310 -0
- package/dist/humain/mcp-adapter.d.ts +3 -0
- package/dist/humain/mcp-adapter.d.ts.map +1 -0
- package/dist/humain/mcp-adapter.js +5 -0
- package/dist/humain/mcp-adapter.js.map +1 -0
- package/dist/humain/pi-agent-execution-host.d.ts +34 -0
- package/dist/humain/pi-agent-execution-host.d.ts.map +1 -0
- package/dist/humain/pi-agent-execution-host.js +77 -0
- package/dist/humain/pi-agent-execution-host.js.map +1 -0
- package/dist/humain/web-access/host.d.ts +4 -0
- package/dist/humain/web-access/host.d.ts.map +1 -0
- package/dist/humain/web-access/host.js +3 -0
- package/dist/humain/web-access/host.js.map +1 -0
- package/dist/humain/web-access/index.d.ts +3 -0
- package/dist/humain/web-access/index.d.ts.map +1 -0
- package/dist/humain/web-access/index.js +5 -0
- package/dist/humain/web-access/index.js.map +1 -0
- package/dist/humain/web-access/vendor/activity.d.ts +34 -0
- package/dist/humain/web-access/vendor/activity.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/activity.js +68 -0
- package/dist/humain/web-access/vendor/activity.js.map +1 -0
- package/dist/humain/web-access/vendor/anysearch.d.ts +8 -0
- package/dist/humain/web-access/vendor/anysearch.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/anysearch.js +167 -0
- package/dist/humain/web-access/vendor/anysearch.js.map +1 -0
- package/dist/humain/web-access/vendor/auth-fetch.d.ts +13 -0
- package/dist/humain/web-access/vendor/auth-fetch.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/auth-fetch.js +134 -0
- package/dist/humain/web-access/vendor/auth-fetch.js.map +1 -0
- package/dist/humain/web-access/vendor/bocha.d.ts +4 -0
- package/dist/humain/web-access/vendor/bocha.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/bocha.js +219 -0
- package/dist/humain/web-access/vendor/bocha.js.map +1 -0
- package/dist/humain/web-access/vendor/brave.d.ts +4 -0
- package/dist/humain/web-access/vendor/brave.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/brave.js +194 -0
- package/dist/humain/web-access/vendor/brave.js.map +1 -0
- package/dist/humain/web-access/vendor/brightdata-unlocker.d.ts +12 -0
- package/dist/humain/web-access/vendor/brightdata-unlocker.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/brightdata-unlocker.js +230 -0
- package/dist/humain/web-access/vendor/brightdata-unlocker.js.map +1 -0
- package/dist/humain/web-access/vendor/brightdata.d.ts +8 -0
- package/dist/humain/web-access/vendor/brightdata.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/brightdata.js +519 -0
- package/dist/humain/web-access/vendor/brightdata.js.map +1 -0
- package/dist/humain/web-access/vendor/chrome-cookies.d.ts +23 -0
- package/dist/humain/web-access/vendor/chrome-cookies.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/chrome-cookies.js +522 -0
- package/dist/humain/web-access/vendor/chrome-cookies.js.map +1 -0
- package/dist/humain/web-access/vendor/content-find.d.ts +11 -0
- package/dist/humain/web-access/vendor/content-find.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/content-find.js +117 -0
- package/dist/humain/web-access/vendor/content-find.js.map +1 -0
- package/dist/humain/web-access/vendor/credential-source.d.ts +28 -0
- package/dist/humain/web-access/vendor/credential-source.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/credential-source.js +151 -0
- package/dist/humain/web-access/vendor/credential-source.js.map +1 -0
- package/dist/humain/web-access/vendor/curator-page.d.ts +30 -0
- package/dist/humain/web-access/vendor/curator-page.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/curator-page.js +3556 -0
- package/dist/humain/web-access/vendor/curator-page.js.map +1 -0
- package/dist/humain/web-access/vendor/curator-server.d.ts +94 -0
- package/dist/humain/web-access/vendor/curator-server.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/curator-server.js +690 -0
- package/dist/humain/web-access/vendor/curator-server.js.map +1 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.d.ts +60 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.js +416 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/declared-web-links.d.ts +16 -0
- package/dist/humain/web-access/vendor/declared-web-links.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/declared-web-links.js +168 -0
- package/dist/humain/web-access/vendor/declared-web-links.js.map +1 -0
- package/dist/humain/web-access/vendor/duckduckgo.d.ts +4 -0
- package/dist/humain/web-access/vendor/duckduckgo.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/duckduckgo.js +123 -0
- package/dist/humain/web-access/vendor/duckduckgo.js.map +1 -0
- package/dist/humain/web-access/vendor/exa.d.ts +10 -0
- package/dist/humain/web-access/vendor/exa.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/exa.js +426 -0
- package/dist/humain/web-access/vendor/exa.js.map +1 -0
- package/dist/humain/web-access/vendor/extract.d.ts +48 -0
- package/dist/humain/web-access/vendor/extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/extract.js +1126 -0
- package/dist/humain/web-access/vendor/extract.js.map +1 -0
- package/dist/humain/web-access/vendor/feature-config.d.ts +3 -0
- package/dist/humain/web-access/vendor/feature-config.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/feature-config.js +27 -0
- package/dist/humain/web-access/vendor/feature-config.js.map +1 -0
- package/dist/humain/web-access/vendor/fetch-params.d.ts +27 -0
- package/dist/humain/web-access/vendor/fetch-params.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/fetch-params.js +71 -0
- package/dist/humain/web-access/vendor/fetch-params.js.map +1 -0
- package/dist/humain/web-access/vendor/firecrawl.d.ts +19 -0
- package/dist/humain/web-access/vendor/firecrawl.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/firecrawl.js +370 -0
- package/dist/humain/web-access/vendor/firecrawl.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-api.d.ts +27 -0
- package/dist/humain/web-access/vendor/gemini-api.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-api.js +230 -0
- package/dist/humain/web-access/vendor/gemini-api.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-pdf-extract.d.ts +9 -0
- package/dist/humain/web-access/vendor/gemini-pdf-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-pdf-extract.js +85 -0
- package/dist/humain/web-access/vendor/gemini-pdf-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-search.d.ts +40 -0
- package/dist/humain/web-access/vendor/gemini-search.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-search.js +832 -0
- package/dist/humain/web-access/vendor/gemini-search.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-url-context.d.ts +4 -0
- package/dist/humain/web-access/vendor/gemini-url-context.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-url-context.js +101 -0
- package/dist/humain/web-access/vendor/gemini-url-context.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-web-config.d.ts +4 -0
- package/dist/humain/web-access/vendor/gemini-web-config.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-web-config.js +42 -0
- package/dist/humain/web-access/vendor/gemini-web-config.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-web.d.ts +18 -0
- package/dist/humain/web-access/vendor/gemini-web.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-web.js +385 -0
- package/dist/humain/web-access/vendor/gemini-web.js.map +1 -0
- package/dist/humain/web-access/vendor/github-api.d.ts +7 -0
- package/dist/humain/web-access/vendor/github-api.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/github-api.js +160 -0
- package/dist/humain/web-access/vendor/github-api.js.map +1 -0
- package/dist/humain/web-access/vendor/github-extract.d.ts +13 -0
- package/dist/humain/web-access/vendor/github-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/github-extract.js +635 -0
- package/dist/humain/web-access/vendor/github-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/index.d.ts +4 -0
- package/dist/humain/web-access/vendor/index.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/index.js +3076 -0
- package/dist/humain/web-access/vendor/index.js.map +1 -0
- package/dist/humain/web-access/vendor/jina-search.d.ts +8 -0
- package/dist/humain/web-access/vendor/jina-search.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/jina-search.js +255 -0
- package/dist/humain/web-access/vendor/jina-search.js.map +1 -0
- package/dist/humain/web-access/vendor/kagi.d.ts +15 -0
- package/dist/humain/web-access/vendor/kagi.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/kagi.js +262 -0
- package/dist/humain/web-access/vendor/kagi.js.map +1 -0
- package/dist/humain/web-access/vendor/ollama.d.ts +15 -0
- package/dist/humain/web-access/vendor/ollama.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/ollama.js +216 -0
- package/dist/humain/web-access/vendor/ollama.js.map +1 -0
- package/dist/humain/web-access/vendor/openai-search.d.ts +15 -0
- package/dist/humain/web-access/vendor/openai-search.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/openai-search.js +459 -0
- package/dist/humain/web-access/vendor/openai-search.js.map +1 -0
- package/dist/humain/web-access/vendor/page-query.d.ts +16 -0
- package/dist/humain/web-access/vendor/page-query.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/page-query.js +79 -0
- package/dist/humain/web-access/vendor/page-query.js.map +1 -0
- package/dist/humain/web-access/vendor/parallel.d.ts +12 -0
- package/dist/humain/web-access/vendor/parallel.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/parallel.js +343 -0
- package/dist/humain/web-access/vendor/parallel.js.map +1 -0
- package/dist/humain/web-access/vendor/pdf-extract.d.ts +44 -0
- package/dist/humain/web-access/vendor/pdf-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/pdf-extract.js +298 -0
- package/dist/humain/web-access/vendor/pdf-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/perplexity.d.ts +20 -0
- package/dist/humain/web-access/vendor/perplexity.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/perplexity.js +159 -0
- package/dist/humain/web-access/vendor/perplexity.js.map +1 -0
- package/dist/humain/web-access/vendor/querit.d.ts +10 -0
- package/dist/humain/web-access/vendor/querit.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/querit.js +335 -0
- package/dist/humain/web-access/vendor/querit.js.map +1 -0
- package/dist/humain/web-access/vendor/render-search-error.d.ts +57 -0
- package/dist/humain/web-access/vendor/render-search-error.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/render-search-error.js +130 -0
- package/dist/humain/web-access/vendor/render-search-error.js.map +1 -0
- package/dist/humain/web-access/vendor/rsc-extract.d.ts +12 -0
- package/dist/humain/web-access/vendor/rsc-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/rsc-extract.js +329 -0
- package/dist/humain/web-access/vendor/rsc-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/search1api.d.ts +10 -0
- package/dist/humain/web-access/vendor/search1api.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/search1api.js +251 -0
- package/dist/humain/web-access/vendor/search1api.js.map +1 -0
- package/dist/humain/web-access/vendor/searchinfinity.d.ts +8 -0
- package/dist/humain/web-access/vendor/searchinfinity.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/searchinfinity.js +229 -0
- package/dist/humain/web-access/vendor/searchinfinity.js.map +1 -0
- package/dist/humain/web-access/vendor/searxng.d.ts +4 -0
- package/dist/humain/web-access/vendor/searxng.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/searxng.js +238 -0
- package/dist/humain/web-access/vendor/searxng.js.map +1 -0
- package/dist/humain/web-access/vendor/serpbase.d.ts +4 -0
- package/dist/humain/web-access/vendor/serpbase.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/serpbase.js +211 -0
- package/dist/humain/web-access/vendor/serpbase.js.map +1 -0
- package/dist/humain/web-access/vendor/serpdive.d.ts +8 -0
- package/dist/humain/web-access/vendor/serpdive.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/serpdive.js +267 -0
- package/dist/humain/web-access/vendor/serpdive.js.map +1 -0
- package/dist/humain/web-access/vendor/source-check.d.ts +99 -0
- package/dist/humain/web-access/vendor/source-check.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/source-check.js +205 -0
- package/dist/humain/web-access/vendor/source-check.js.map +1 -0
- package/dist/humain/web-access/vendor/ssrf-protection.d.ts +50 -0
- package/dist/humain/web-access/vendor/ssrf-protection.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/ssrf-protection.js +466 -0
- package/dist/humain/web-access/vendor/ssrf-protection.js.map +1 -0
- package/dist/humain/web-access/vendor/storage.d.ts +55 -0
- package/dist/humain/web-access/vendor/storage.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/storage.js +485 -0
- package/dist/humain/web-access/vendor/storage.js.map +1 -0
- package/dist/humain/web-access/vendor/summary-model-scope.d.ts +25 -0
- package/dist/humain/web-access/vendor/summary-model-scope.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/summary-model-scope.js +98 -0
- package/dist/humain/web-access/vendor/summary-model-scope.js.map +1 -0
- package/dist/humain/web-access/vendor/summary-review.d.ts +26 -0
- package/dist/humain/web-access/vendor/summary-review.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/summary-review.js +344 -0
- package/dist/humain/web-access/vendor/summary-review.js.map +1 -0
- package/dist/humain/web-access/vendor/tavily.d.ts +8 -0
- package/dist/humain/web-access/vendor/tavily.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/tavily.js +194 -0
- package/dist/humain/web-access/vendor/tavily.js.map +1 -0
- package/dist/humain/web-access/vendor/tinyfish.d.ts +11 -0
- package/dist/humain/web-access/vendor/tinyfish.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/tinyfish.js +331 -0
- package/dist/humain/web-access/vendor/tinyfish.js.map +1 -0
- package/dist/humain/web-access/vendor/utils.d.ts +20 -0
- package/dist/humain/web-access/vendor/utils.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/utils.js +91 -0
- package/dist/humain/web-access/vendor/utils.js.map +1 -0
- package/dist/humain/web-access/vendor/video-extract.d.ts +16 -0
- package/dist/humain/web-access/vendor/video-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/video-extract.js +335 -0
- package/dist/humain/web-access/vendor/video-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/xai-search.d.ts +13 -0
- package/dist/humain/web-access/vendor/xai-search.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/xai-search.js +331 -0
- package/dist/humain/web-access/vendor/xai-search.js.map +1 -0
- package/dist/humain/web-access/vendor/youtube-extract.d.ts +27 -0
- package/dist/humain/web-access/vendor/youtube-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/youtube-extract.js +282 -0
- package/dist/humain/web-access/vendor/youtube-extract.js.map +1 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +2 -2
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +169 -102
- package/dist/main.js.map +1 -1
- package/dist/modes/agent-exec-mode.d.ts +14 -0
- package/dist/modes/agent-exec-mode.d.ts.map +1 -0
- package/dist/modes/agent-exec-mode.js +92 -0
- package/dist/modes/agent-exec-mode.js.map +1 -0
- package/dist/modes/index.d.ts +4 -2
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +2 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +5 -2
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +13 -4
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +7 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- 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/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/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 +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +16 -4
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +4 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +26 -0
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +8 -2
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +30 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +3 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +9 -2
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +45 -9
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +581 -211
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +1 -0
- package/dist/modes/interactive/theme/light.json +1 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +3 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +10 -1
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +5 -1
- package/dist/modes/interactive/theme/theme.d.ts +2 -2
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +24 -6
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +28 -0
- package/dist/modes/json-event.d.ts.map +1 -0
- package/dist/modes/json-event.js +12 -0
- package/dist/modes/json-event.js.map +1 -0
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +12 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +12 -5
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +55 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +13 -3
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +15 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +11 -9
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/rpc-entry.d.ts.map +1 -1
- package/dist/rpc-entry.js +3 -2
- package/dist/rpc-entry.js.map +1 -1
- package/dist/server/create-harness.d.ts +26 -0
- package/dist/server/create-harness.d.ts.map +1 -0
- package/dist/server/create-harness.js +104 -0
- package/dist/server/create-harness.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/clipboard.d.ts +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +22 -2
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/management-http.d.ts +23 -0
- package/dist/utils/management-http.d.ts.map +1 -0
- package/dist/utils/management-http.js +50 -0
- package/dist/utils/management-http.js.map +1 -0
- package/dist/utils/paths.d.ts +3 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +23 -1
- package/dist/utils/paths.js.map +1 -1
- 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.map +1 -1
- package/dist/utils/tools-manager.js +13 -25
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts +4 -0
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +23 -5
- package/dist/utils/version-check.js.map +1 -1
- package/docs/compaction.md +2 -2
- package/docs/custom-provider.md +7 -5
- package/docs/extensions.md +30 -5
- package/docs/humain-terminal.md +21 -1
- package/docs/json.md +24 -19
- package/docs/keybindings.md +46 -14
- package/docs/models.md +32 -11
- package/docs/providers.md +9 -1
- package/docs/quickstart.md +39 -37
- package/docs/rpc.md +31 -11
- package/docs/sdk.md +21 -2
- package/docs/security.md +21 -21
- package/docs/session-format.md +14 -14
- package/docs/settings.md +4 -1
- package/docs/themes.md +5 -3
- package/docs/usage.md +7 -0
- package/examples/extensions/custom-compaction.ts +3 -18
- package/examples/extensions/custom-provider-anthropic/index.ts +5 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +5 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/doom-overlay/wad-finder.ts +7 -3
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/handoff.ts +4 -13
- package/examples/extensions/qna.ts +5 -9
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/summarize.ts +9 -20
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/rpc-extension-ui.ts +11 -2
- package/examples/sdk/02-custom-model.ts +2 -3
- package/examples/sdk/09-api-keys-and-oauth.ts +1 -1
- package/examples/sdk/12-full-control.ts +1 -1
- package/examples/sdk/README.md +1 -1
- package/npm-shrinkwrap.json +2771 -535
- package/package.json +40 -11
- package/src/humain/mcp-adapter/UPSTREAM.md +15 -0
- package/src/humain/mcp-adapter/upstream.json +7 -0
- package/src/humain/mcp-adapter/vendor/CHANGELOG.md +673 -0
- package/src/humain/mcp-adapter/vendor/LICENSE +21 -0
- package/src/humain/web-access/UPSTREAM.md +17 -0
- package/src/humain/web-access/upstream.json +23 -0
- package/src/humain/web-access/vendor/LICENSE +21 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { activityMonitor } from "./activity.js";
|
|
3
|
+
import { hasCredentialSource, redactCredential, resolveCredential } from "./credential-source.js";
|
|
4
|
+
import { getWebSearchConfigPath } from "./utils.js";
|
|
5
|
+
const SEARCH1API_SEARCH_URL = "https://api.search1api.com/search";
|
|
6
|
+
const SEARCH1API_CRAWL_URL = "https://api.search1api.com/crawl";
|
|
7
|
+
const CONFIG_PATH = getWebSearchConfigPath();
|
|
8
|
+
const SEARCH_TIMEOUT_MS = 60_000;
|
|
9
|
+
const CRAWL_TIMEOUT_MS = 60_000;
|
|
10
|
+
let cachedConfig = null;
|
|
11
|
+
function loadConfig() {
|
|
12
|
+
if (cachedConfig)
|
|
13
|
+
return cachedConfig;
|
|
14
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
15
|
+
cachedConfig = {};
|
|
16
|
+
return cachedConfig;
|
|
17
|
+
}
|
|
18
|
+
const raw = readFileSync(CONFIG_PATH, "utf-8");
|
|
19
|
+
let parsed;
|
|
20
|
+
try {
|
|
21
|
+
parsed = JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
25
|
+
throw new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);
|
|
26
|
+
}
|
|
27
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
28
|
+
throw new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);
|
|
29
|
+
}
|
|
30
|
+
cachedConfig = parsed;
|
|
31
|
+
return cachedConfig;
|
|
32
|
+
}
|
|
33
|
+
async function getApiKey(signal) {
|
|
34
|
+
const key = await resolveCredential({
|
|
35
|
+
provider: "Search1API",
|
|
36
|
+
configuredValue: loadConfig().search1apiApiKey,
|
|
37
|
+
environmentValue: process.env.SEARCH1API_KEY,
|
|
38
|
+
signal,
|
|
39
|
+
});
|
|
40
|
+
if (!key) {
|
|
41
|
+
throw new Error("Search1API key not found. Either:\n" +
|
|
42
|
+
` 1. Create ${CONFIG_PATH} with { "search1apiApiKey": "your-key" }\n` +
|
|
43
|
+
" 2. Set SEARCH1API_KEY environment variable\n" +
|
|
44
|
+
"Create a key at https://dashboard.search1api.com");
|
|
45
|
+
}
|
|
46
|
+
return key;
|
|
47
|
+
}
|
|
48
|
+
export function isSearch1APIAvailable() {
|
|
49
|
+
return hasCredentialSource({
|
|
50
|
+
provider: "Search1API",
|
|
51
|
+
configuredValue: loadConfig().search1apiApiKey,
|
|
52
|
+
environmentValue: process.env.SEARCH1API_KEY,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function errorMessage(err) {
|
|
56
|
+
return err instanceof Error ? err.message : String(err);
|
|
57
|
+
}
|
|
58
|
+
function requestSignal(signal, timeoutMs) {
|
|
59
|
+
const timeout = AbortSignal.timeout(timeoutMs);
|
|
60
|
+
return signal ? AbortSignal.any([signal, timeout]) : timeout;
|
|
61
|
+
}
|
|
62
|
+
function normalizeNumResults(value) {
|
|
63
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
64
|
+
return 5;
|
|
65
|
+
return Math.max(1, Math.min(Math.floor(value), 20));
|
|
66
|
+
}
|
|
67
|
+
function normalizeDomain(value) {
|
|
68
|
+
let input = value.trim().toLowerCase();
|
|
69
|
+
if (!input)
|
|
70
|
+
return null;
|
|
71
|
+
if (input.startsWith("-"))
|
|
72
|
+
input = input.slice(1).trim();
|
|
73
|
+
if (!input)
|
|
74
|
+
return null;
|
|
75
|
+
try {
|
|
76
|
+
const parsed = input.includes("://") ? new URL(input) : new URL(`https://${input}`);
|
|
77
|
+
input = parsed.hostname;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
input = input.split("/")[0]?.split(":")[0] ?? "";
|
|
81
|
+
}
|
|
82
|
+
input = input.replace(/^\.+|\.+$/g, "");
|
|
83
|
+
return /^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/i.test(input) ? input : null;
|
|
84
|
+
}
|
|
85
|
+
function mapDomainFilter(domainFilter) {
|
|
86
|
+
const includeSites = [];
|
|
87
|
+
const excludeSites = [];
|
|
88
|
+
for (const raw of domainFilter ?? []) {
|
|
89
|
+
const domain = normalizeDomain(raw);
|
|
90
|
+
if (!domain)
|
|
91
|
+
continue;
|
|
92
|
+
const target = raw.trim().startsWith("-") ? excludeSites : includeSites;
|
|
93
|
+
if (!target.includes(domain))
|
|
94
|
+
target.push(domain);
|
|
95
|
+
}
|
|
96
|
+
return { includeSites, excludeSites };
|
|
97
|
+
}
|
|
98
|
+
function buildSearchBody(query, options) {
|
|
99
|
+
const numResults = normalizeNumResults(options.numResults);
|
|
100
|
+
const { includeSites, excludeSites } = mapDomainFilter(options.domainFilter);
|
|
101
|
+
return {
|
|
102
|
+
query,
|
|
103
|
+
max_results: numResults,
|
|
104
|
+
crawl_results: options.includeContent ? numResults : 0,
|
|
105
|
+
...(includeSites.length > 0 ? { include_sites: includeSites } : {}),
|
|
106
|
+
...(excludeSites.length > 0 ? { exclude_sites: excludeSites } : {}),
|
|
107
|
+
...(options.recencyFilter ? { time_range: options.recencyFilter } : {}),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
async function search1APIJsonRequest(label, url, apiKey, body, timeoutMs, signal) {
|
|
111
|
+
let response;
|
|
112
|
+
try {
|
|
113
|
+
response = await fetch(url, {
|
|
114
|
+
method: "POST",
|
|
115
|
+
headers: {
|
|
116
|
+
Authorization: `Bearer ${apiKey}`,
|
|
117
|
+
"Content-Type": "application/json",
|
|
118
|
+
},
|
|
119
|
+
body: JSON.stringify(body),
|
|
120
|
+
signal: requestSignal(signal, timeoutMs),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
const message = errorMessage(err);
|
|
125
|
+
const redactedMessage = redactCredential(message, apiKey);
|
|
126
|
+
if (redactedMessage === message)
|
|
127
|
+
throw err;
|
|
128
|
+
const redactedError = new Error(redactedMessage);
|
|
129
|
+
if (err instanceof Error)
|
|
130
|
+
redactedError.name = err.name;
|
|
131
|
+
throw redactedError;
|
|
132
|
+
}
|
|
133
|
+
const raw = await response.text();
|
|
134
|
+
if (!response.ok) {
|
|
135
|
+
throw new Error(`Search1API ${label} API error ${response.status}: ${redactCredential(raw, apiKey).slice(0, 300)}`);
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
return JSON.parse(raw);
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
throw new Error(`Search1API ${label} API returned invalid JSON: ${errorMessage(err)}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function mapSearchResults(results) {
|
|
145
|
+
if (!Array.isArray(results)) {
|
|
146
|
+
throw new Error("Search1API Search API returned an unexpected response shape");
|
|
147
|
+
}
|
|
148
|
+
return results.flatMap((item) => {
|
|
149
|
+
if (!item || typeof item.link !== "string" || item.link.trim().length === 0)
|
|
150
|
+
return [];
|
|
151
|
+
const url = item.link.trim();
|
|
152
|
+
return [{
|
|
153
|
+
title: typeof item.title === "string" && item.title.trim() ? item.title.trim() : url,
|
|
154
|
+
url,
|
|
155
|
+
snippet: typeof item.snippet === "string" ? item.snippet.replace(/\s+/g, " ").trim() : "",
|
|
156
|
+
}];
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function mapInlineContent(results) {
|
|
160
|
+
if (!Array.isArray(results))
|
|
161
|
+
return [];
|
|
162
|
+
return results.flatMap((item) => {
|
|
163
|
+
if (!item || typeof item.link !== "string" || item.link.trim().length === 0)
|
|
164
|
+
return [];
|
|
165
|
+
if (typeof item.content !== "string" || item.content.trim().length === 0)
|
|
166
|
+
return [];
|
|
167
|
+
return [{
|
|
168
|
+
url: item.link.trim(),
|
|
169
|
+
title: typeof item.title === "string" ? item.title.trim() : "",
|
|
170
|
+
content: item.content,
|
|
171
|
+
error: null,
|
|
172
|
+
}];
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
function buildAnswer(results) {
|
|
176
|
+
return results.map((result) => {
|
|
177
|
+
if (result.snippet)
|
|
178
|
+
return `${result.snippet}\nSource: ${result.title} (${result.url})`;
|
|
179
|
+
return `Source: ${result.title} (${result.url})`;
|
|
180
|
+
}).join("\n\n");
|
|
181
|
+
}
|
|
182
|
+
export async function searchWithSearch1API(query, options = {}) {
|
|
183
|
+
const apiKey = await getApiKey(options.signal);
|
|
184
|
+
const activityId = activityMonitor.logStart({ type: "api", query });
|
|
185
|
+
try {
|
|
186
|
+
const data = await search1APIJsonRequest("Search", SEARCH1API_SEARCH_URL, apiKey, buildSearchBody(query, options), SEARCH_TIMEOUT_MS, options.signal);
|
|
187
|
+
const results = mapSearchResults(data.results);
|
|
188
|
+
const response = { answer: buildAnswer(results), results };
|
|
189
|
+
if (options.includeContent) {
|
|
190
|
+
const inlineContent = mapInlineContent(data.results);
|
|
191
|
+
if (inlineContent.length > 0)
|
|
192
|
+
response.inlineContent = inlineContent;
|
|
193
|
+
}
|
|
194
|
+
activityMonitor.logComplete(activityId, 200);
|
|
195
|
+
return response;
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
const message = errorMessage(err);
|
|
199
|
+
const redactedMessage = redactCredential(message, apiKey);
|
|
200
|
+
if (redactedMessage.toLowerCase().includes("abort"))
|
|
201
|
+
activityMonitor.logComplete(activityId, 0);
|
|
202
|
+
else
|
|
203
|
+
activityMonitor.logError(activityId, redactedMessage);
|
|
204
|
+
if (redactedMessage === message)
|
|
205
|
+
throw err;
|
|
206
|
+
const redactedError = new Error(redactedMessage);
|
|
207
|
+
if (err instanceof Error)
|
|
208
|
+
redactedError.name = err.name;
|
|
209
|
+
throw redactedError;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
export async function extractWithSearch1API(url, signal, options = {}) {
|
|
213
|
+
const apiKey = await getApiKey(signal);
|
|
214
|
+
const activityId = activityMonitor.logStart({ type: "fetch", url });
|
|
215
|
+
try {
|
|
216
|
+
const data = await search1APIJsonRequest("Crawl", SEARCH1API_CRAWL_URL, apiKey, { url }, typeof options.timeoutMs === "number" && Number.isFinite(options.timeoutMs)
|
|
217
|
+
? Math.max(1, Math.floor(options.timeoutMs))
|
|
218
|
+
: CRAWL_TIMEOUT_MS, signal);
|
|
219
|
+
const result = data.results;
|
|
220
|
+
if (!result || typeof result !== "object") {
|
|
221
|
+
throw new Error("Search1API Crawl API returned an unexpected response shape");
|
|
222
|
+
}
|
|
223
|
+
const content = typeof result.content === "string" ? result.content.trim() : "";
|
|
224
|
+
if (!content) {
|
|
225
|
+
activityMonitor.logComplete(activityId, 200);
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
activityMonitor.logComplete(activityId, 200);
|
|
229
|
+
return {
|
|
230
|
+
url,
|
|
231
|
+
title: typeof result.title === "string" ? result.title.trim() : "",
|
|
232
|
+
content,
|
|
233
|
+
error: null,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
const message = errorMessage(err);
|
|
238
|
+
const redactedMessage = redactCredential(message, apiKey);
|
|
239
|
+
if (redactedMessage.toLowerCase().includes("abort"))
|
|
240
|
+
activityMonitor.logComplete(activityId, 0);
|
|
241
|
+
else
|
|
242
|
+
activityMonitor.logError(activityId, redactedMessage);
|
|
243
|
+
if (redactedMessage === message)
|
|
244
|
+
throw err;
|
|
245
|
+
const redactedError = new Error(redactedMessage);
|
|
246
|
+
if (err instanceof Error)
|
|
247
|
+
redactedError.name = err.name;
|
|
248
|
+
throw redactedError;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=search1api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search1api.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/search1api.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport type { ExtractedContent, ExtractOptions } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst SEARCH1API_SEARCH_URL = \"https://api.search1api.com/search\";\nconst SEARCH1API_CRAWL_URL = \"https://api.search1api.com/crawl\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\nconst CRAWL_TIMEOUT_MS = 60_000;\n\ninterface WebSearchConfig {\n\tsearch1apiApiKey?: unknown;\n}\n\ninterface Search1APISearchResult {\n\ttitle?: string | null;\n\tlink?: string | null;\n\tsnippet?: string | null;\n\tcontent?: string | null;\n}\n\ninterface Search1APISearchResponse {\n\tsearchParameters?: Record<string, unknown>;\n\tresults?: Search1APISearchResult[];\n}\n\ninterface Search1APICrawlResult {\n\ttitle?: string | null;\n\tlink?: string | null;\n\tcontent?: string | null;\n\tmetadata?: Record<string, unknown>;\n}\n\ninterface Search1APICrawlResponse {\n\tcrawlParameters?: { url?: string };\n\tresults?: Search1APICrawlResult;\n}\n\ninterface Search1APISearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveCredential({\n\t\tprovider: \"Search1API\",\n\t\tconfiguredValue: loadConfig().search1apiApiKey,\n\t\tenvironmentValue: process.env.SEARCH1API_KEY,\n\t\tsignal,\n\t});\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Search1API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"search1apiApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set SEARCH1API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://dashboard.search1api.com\",\n\t\t);\n\t}\n\treturn key;\n}\n\nexport function isSearch1APIAvailable(): boolean {\n\treturn hasCredentialSource({\n\t\tprovider: \"Search1API\",\n\t\tconfiguredValue: loadConfig().search1apiApiKey,\n\t\tenvironmentValue: process.env.SEARCH1API_KEY,\n\t});\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction requestSignal(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {\n\tconst timeout = AbortSignal.timeout(timeoutMs);\n\treturn signal ? AbortSignal.any([signal, timeout]) : timeout;\n}\n\nfunction normalizeNumResults(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 20));\n}\n\nfunction normalizeDomain(value: string): string | null {\n\tlet input = value.trim().toLowerCase();\n\tif (!input) return null;\n\tif (input.startsWith(\"-\")) input = input.slice(1).trim();\n\tif (!input) return null;\n\ttry {\n\t\tconst parsed = input.includes(\"://\") ? new URL(input) : new URL(`https://${input}`);\n\t\tinput = parsed.hostname;\n\t} catch {\n\t\tinput = input.split(\"/\")[0]?.split(\":\")[0] ?? \"\";\n\t}\n\tinput = input.replace(/^\\.+|\\.+$/g, \"\");\n\treturn /^[a-z0-9][a-z0-9.-]*\\.[a-z]{2,}$/i.test(input) ? input : null;\n}\n\nfunction mapDomainFilter(domainFilter: string[] | undefined): { includeSites: string[]; excludeSites: string[] } {\n\tconst includeSites: string[] = [];\n\tconst excludeSites: string[] = [];\n\tfor (const raw of domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? excludeSites : includeSites;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn { includeSites, excludeSites };\n}\n\nfunction buildSearchBody(query: string, options: Search1APISearchOptions): Record<string, unknown> {\n\tconst numResults = normalizeNumResults(options.numResults);\n\tconst { includeSites, excludeSites } = mapDomainFilter(options.domainFilter);\n\treturn {\n\t\tquery,\n\t\tmax_results: numResults,\n\t\tcrawl_results: options.includeContent ? numResults : 0,\n\t\t...(includeSites.length > 0 ? { include_sites: includeSites } : {}),\n\t\t...(excludeSites.length > 0 ? { exclude_sites: excludeSites } : {}),\n\t\t...(options.recencyFilter ? { time_range: options.recencyFilter } : {}),\n\t};\n}\n\nasync function search1APIJsonRequest<T>(\n\tlabel: \"Search\" | \"Crawl\",\n\turl: string,\n\tapiKey: string,\n\tbody: Record<string, unknown>,\n\ttimeoutMs: number,\n\tsignal?: AbortSignal,\n): Promise<T> {\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: requestSignal(signal, timeoutMs),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tconst raw = await response.text();\n\tif (!response.ok) {\n\t\tthrow new Error(`Search1API ${label} API error ${response.status}: ${redactCredential(raw, apiKey).slice(0, 300)}`);\n\t}\n\ttry {\n\t\treturn JSON.parse(raw) as T;\n\t} catch (err) {\n\t\tthrow new Error(`Search1API ${label} API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n}\n\nfunction mapSearchResults(results: Search1APISearchResult[] | undefined): SearchResponse[\"results\"] {\n\tif (!Array.isArray(results)) {\n\t\tthrow new Error(\"Search1API Search API returned an unexpected response shape\");\n\t}\n\treturn results.flatMap((item) => {\n\t\tif (!item || typeof item.link !== \"string\" || item.link.trim().length === 0) return [];\n\t\tconst url = item.link.trim();\n\t\treturn [{\n\t\t\ttitle: typeof item.title === \"string\" && item.title.trim() ? item.title.trim() : url,\n\t\t\turl,\n\t\t\tsnippet: typeof item.snippet === \"string\" ? item.snippet.replace(/\\s+/g, \" \").trim() : \"\",\n\t\t}];\n\t});\n}\n\nfunction mapInlineContent(results: Search1APISearchResult[] | undefined): ExtractedContent[] {\n\tif (!Array.isArray(results)) return [];\n\treturn results.flatMap((item) => {\n\t\tif (!item || typeof item.link !== \"string\" || item.link.trim().length === 0) return [];\n\t\tif (typeof item.content !== \"string\" || item.content.trim().length === 0) return [];\n\t\treturn [{\n\t\t\turl: item.link.trim(),\n\t\t\ttitle: typeof item.title === \"string\" ? item.title.trim() : \"\",\n\t\t\tcontent: item.content,\n\t\t\terror: null,\n\t\t}];\n\t});\n}\n\nfunction buildAnswer(results: SearchResponse[\"results\"]): string {\n\treturn results.map((result) => {\n\t\tif (result.snippet) return `${result.snippet}\\nSource: ${result.title} (${result.url})`;\n\t\treturn `Source: ${result.title} (${result.url})`;\n\t}).join(\"\\n\\n\");\n}\n\nexport async function searchWithSearch1API(\n\tquery: string,\n\toptions: Search1APISearchOptions = {},\n): Promise<SearchResponse> {\n\tconst apiKey = await getApiKey(options.signal);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\ttry {\n\t\tconst data = await search1APIJsonRequest<Search1APISearchResponse>(\n\t\t\t\"Search\",\n\t\t\tSEARCH1API_SEARCH_URL,\n\t\t\tapiKey,\n\t\t\tbuildSearchBody(query, options),\n\t\t\tSEARCH_TIMEOUT_MS,\n\t\t\toptions.signal,\n\t\t);\n\t\tconst results = mapSearchResults(data.results);\n\t\tconst response: SearchResponse = { answer: buildAnswer(results), results };\n\t\tif (options.includeContent) {\n\t\t\tconst inlineContent = mapInlineContent(data.results);\n\t\t\tif (inlineContent.length > 0) response.inlineContent = inlineContent;\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn response;\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n\nexport async function extractWithSearch1API(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions: ExtractOptions = {},\n): Promise<ExtractedContent | null> {\n\tconst apiKey = await getApiKey(signal);\n\tconst activityId = activityMonitor.logStart({ type: \"fetch\", url });\n\ttry {\n\t\tconst data = await search1APIJsonRequest<Search1APICrawlResponse>(\n\t\t\t\"Crawl\",\n\t\t\tSEARCH1API_CRAWL_URL,\n\t\t\tapiKey,\n\t\t\t{ url },\n\t\t\ttypeof options.timeoutMs === \"number\" && Number.isFinite(options.timeoutMs)\n\t\t\t\t? Math.max(1, Math.floor(options.timeoutMs))\n\t\t\t\t: CRAWL_TIMEOUT_MS,\n\t\t\tsignal,\n\t\t);\n\t\tconst result = data.results;\n\t\tif (!result || typeof result !== \"object\") {\n\t\t\tthrow new Error(\"Search1API Crawl API returned an unexpected response shape\");\n\t\t}\n\t\tconst content = typeof result.content === \"string\" ? result.content.trim() : \"\";\n\t\tif (!content) {\n\t\t\tactivityMonitor.logComplete(activityId, 200);\n\t\t\treturn null;\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn {\n\t\t\turl,\n\t\t\ttitle: typeof result.title === \"string\" ? result.title.trim() : \"\",\n\t\t\tcontent,\n\t\t\terror: null,\n\t\t};\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SearchOptions, SearchResponse } from "./perplexity.ts";
|
|
2
|
+
interface SearchinfinitySearchOptions extends SearchOptions {
|
|
3
|
+
includeContent?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function isSearchinfinityAvailable(): boolean;
|
|
6
|
+
export declare function searchWithSearchinfinity(query: string, options?: SearchinfinitySearchOptions): Promise<SearchResponse>;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=searchinfinity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchinfinity.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/searchinfinity.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA6CrE,UAAU,2BAA4B,SAAQ,aAAa;IAC1D,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AA4CD,wBAAgB,yBAAyB,IAAI,OAAO,CAMnD;AAkJD,wBAAsB,wBAAwB,CAC7C,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,2BAAgC,GACvC,OAAO,CAAC,cAAc,CAAC,CAmBzB","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst SEARCHINFINITY_SEARCH_URL = \"https://torchlight.byteintlapi.com/search_api/web_search\";\nconst CONFIG_PATH = getWebSearchConfigPath();\n// API Key authenticated requests time out server-side after 30 seconds.\nconst SEARCH_TIMEOUT_MS = 30_000;\n\ninterface WebSearchConfig {\n\tsearchinfinityApiKey?: unknown;\n}\n\ninterface SearchinfinityWebResult {\n\tId?: string;\n\tSortId?: number;\n\tTitle?: string | null;\n\tSiteName?: string | null;\n\tUrl?: string | null;\n\tSnippet?: string | null;\n\tSummary?: string | null;\n\tPublishTime?: string | null;\n\tLogoUrl?: string | null;\n}\n\ninterface SearchinfinitySearchResponse {\n\tResponseMetadata?: {\n\t\tRequestId?: string;\n\t\tError?: {\n\t\t\tCodeN?: number;\n\t\t\tCode?: string;\n\t\t\tMessage?: string;\n\t\t} | null;\n\t};\n\tResult?: {\n\t\tResultCount?: number;\n\t\tWebResults?: SearchinfinityWebResult[];\n\t\tSearchContext?: {\n\t\t\tOriginQuery?: string;\n\t\t\tSearchType?: string;\n\t\t};\n\t\tTimeCost?: number;\n\t\tLogId?: string;\n\t} | null;\n}\n\ninterface SearchinfinitySearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveCredential({\n\t\tprovider: \"Searchinfinity\",\n\t\tconfiguredValue: loadConfig().searchinfinityApiKey,\n\t\tenvironmentValue: process.env.SEARCHINFINITY_API_KEY,\n\t\tsignal,\n\t});\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Searchinfinity API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"searchinfinityApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set SEARCHINFINITY_API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://console.byteplus.com/search-infinity/api-key\",\n\t\t);\n\t}\n\treturn key;\n}\n\nexport function isSearchinfinityAvailable(): boolean {\n\treturn hasCredentialSource({\n\t\tprovider: \"Searchinfinity\",\n\t\tconfiguredValue: loadConfig().searchinfinityApiKey,\n\t\tenvironmentValue: process.env.SEARCHINFINITY_API_KEY,\n\t});\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction requestSignal(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {\n\tconst timeout = AbortSignal.timeout(timeoutMs);\n\treturn signal ? AbortSignal.any([signal, timeout]) : timeout;\n}\n\nfunction normalizeNumResults(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 20));\n}\n\nfunction normalizeDomain(value: string): string | null {\n\tlet input = value.trim().toLowerCase();\n\tif (!input) return null;\n\tif (input.startsWith(\"-\")) input = input.slice(1).trim();\n\tif (!input) return null;\n\ttry {\n\t\tconst parsed = input.includes(\"://\") ? new URL(input) : new URL(`https://${input}`);\n\t\tinput = parsed.hostname;\n\t} catch {\n\t\tinput = input.split(\"/\")[0]?.split(\":\")[0] ?? \"\";\n\t}\n\tinput = input.replace(/^\\.+|\\.+$/g, \"\");\n\treturn /^[a-z0-9][a-z0-9.-]*\\.[a-z]{2,}$/i.test(input) ? input : null;\n}\n\nfunction mapRecencyFilter(recency: SearchOptions[\"recencyFilter\"]): string | undefined {\n\tif (recency === \"day\") return \"OneDay\";\n\tif (recency === \"week\") return \"OneWeek\";\n\tif (recency === \"month\") return \"OneMonth\";\n\tif (recency === \"year\") return \"OneYear\";\n\treturn undefined;\n}\n\nfunction buildSearchBody(query: string, options: SearchinfinitySearchOptions): Record<string, unknown> {\n\tconst includeSites: string[] = [];\n\tconst blockHosts: string[] = [];\n\tfor (const raw of options.domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? blockHosts : includeSites;\n\t\tif (target.length < 5 && !target.includes(domain)) target.push(domain);\n\t}\n\tconst filter: Record<string, unknown> = {};\n\tif (includeSites.length > 0) filter.Sites = includeSites.join(\"|\");\n\tif (blockHosts.length > 0) filter.BlockHosts = blockHosts.join(\"|\");\n\n\tconst timeRange = mapRecencyFilter(options.recencyFilter);\n\treturn {\n\t\tQuery: query,\n\t\tCount: normalizeNumResults(options.numResults),\n\t\t...(Object.keys(filter).length > 0 ? { Filter: filter } : {}),\n\t\t...(timeRange ? { TimeRange: timeRange } : {}),\n\t};\n}\n\n// Map Searchinfinity business error codes to the closest HTTP semantics so\n// error classification (auth/quota/invalid-request/transient) keeps working.\n// CodeN carries the numeric code (e.g. 700901); Code may be a slug (e.g.\n// \"invalid_api_key\"), so match both.\nfunction businessErrorStatus(codeN: number | undefined, code: string, message: string): number | undefined {\n\tif (codeN === 700901 || code === \"invalid_api_key\") return 401;\n\tif (codeN === 700429 || code === \"700429\") return 429;\n\tif (codeN === 10400 || code === \"10400\") return 400;\n\tif (codeN === 10500 || code === \"10500\") return 500;\n\tif (codeN === 10403 || code === \"10403\") return /quota|exhaust/i.test(message) ? 429 : 403;\n\treturn undefined;\n}\n\nasync function searchinfinityJsonRequest(\n\tapiKey: string,\n\tbody: Record<string, unknown>,\n\tsignal?: AbortSignal,\n): Promise<SearchinfinitySearchResponse> {\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(SEARCHINFINITY_SEARCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: requestSignal(signal, SEARCH_TIMEOUT_MS),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tconst raw = await response.text();\n\tif (!response.ok) {\n\t\tthrow new Error(`Searchinfinity Search API error ${response.status}: ${redactCredential(raw, apiKey).slice(0, 300)}`);\n\t}\n\tlet data: SearchinfinitySearchResponse;\n\ttry {\n\t\tdata = JSON.parse(raw) as SearchinfinitySearchResponse;\n\t} catch (err) {\n\t\tthrow new Error(`Searchinfinity Search API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\tconst businessError = data.ResponseMetadata?.Error;\n\tif (businessError && (businessError.Code || businessError.Message)) {\n\t\tconst code = typeof businessError.Code === \"string\" && businessError.Code ? businessError.Code : \"unknown\";\n\t\tconst message = typeof businessError.Message === \"string\" && businessError.Message ? businessError.Message : \"unknown error\";\n\t\tconst status = businessErrorStatus(businessError.CodeN, code, message);\n\t\tconst codeLabel = typeof businessError.CodeN === \"number\" ? `${businessError.CodeN} ${code}` : code;\n\t\tthrow new Error(\n\t\t\t`Searchinfinity Search API error ${status ?? \"unknown\"}: ${message} (code ${codeLabel})`,\n\t\t);\n\t}\n\treturn data;\n}\n\nfunction mapSearchResults(results: SearchinfinityWebResult[] | undefined): SearchResponse[\"results\"] {\n\tif (!Array.isArray(results)) {\n\t\tthrow new Error(\"Searchinfinity Search API returned an unexpected response shape\");\n\t}\n\treturn results.flatMap((item) => {\n\t\tif (!item || typeof item.Url !== \"string\" || item.Url.trim().length === 0) return [];\n\t\tconst url = item.Url.trim();\n\t\tconst summary = typeof item.Summary === \"string\" ? item.Summary.replace(/\\s+/g, \" \").trim() : \"\";\n\t\tconst snippet = typeof item.Snippet === \"string\" ? item.Snippet.replace(/\\s+/g, \" \").trim() : \"\";\n\t\treturn [{\n\t\t\ttitle: typeof item.Title === \"string\" && item.Title.trim() ? item.Title.trim() : url,\n\t\t\turl,\n\t\t\tsnippet: summary || snippet,\n\t\t}];\n\t});\n}\n\nfunction buildAnswer(results: SearchResponse[\"results\"]): string {\n\treturn results.map((result) => {\n\t\tif (result.snippet) return `${result.snippet}\\nSource: ${result.title} (${result.url})`;\n\t\treturn `Source: ${result.title} (${result.url})`;\n\t}).join(\"\\n\\n\");\n}\n\nexport async function searchWithSearchinfinity(\n\tquery: string,\n\toptions: SearchinfinitySearchOptions = {},\n): Promise<SearchResponse> {\n\tconst apiKey = await getApiKey(options.signal);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\ttry {\n\t\tconst data = await searchinfinityJsonRequest(apiKey, buildSearchBody(query, options), options.signal);\n\t\tconst results = mapSearchResults(data.Result?.WebResults);\n\t\tconst response: SearchResponse = { answer: buildAnswer(results), results };\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn response;\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { activityMonitor } from "./activity.js";
|
|
3
|
+
import { hasCredentialSource, redactCredential, resolveCredential } from "./credential-source.js";
|
|
4
|
+
import { getWebSearchConfigPath } from "./utils.js";
|
|
5
|
+
const SEARCHINFINITY_SEARCH_URL = "https://torchlight.byteintlapi.com/search_api/web_search";
|
|
6
|
+
const CONFIG_PATH = getWebSearchConfigPath();
|
|
7
|
+
// API Key authenticated requests time out server-side after 30 seconds.
|
|
8
|
+
const SEARCH_TIMEOUT_MS = 30_000;
|
|
9
|
+
let cachedConfig = null;
|
|
10
|
+
function loadConfig() {
|
|
11
|
+
if (cachedConfig)
|
|
12
|
+
return cachedConfig;
|
|
13
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
14
|
+
cachedConfig = {};
|
|
15
|
+
return cachedConfig;
|
|
16
|
+
}
|
|
17
|
+
const raw = readFileSync(CONFIG_PATH, "utf-8");
|
|
18
|
+
let parsed;
|
|
19
|
+
try {
|
|
20
|
+
parsed = JSON.parse(raw);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
24
|
+
throw new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);
|
|
25
|
+
}
|
|
26
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
27
|
+
throw new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);
|
|
28
|
+
}
|
|
29
|
+
cachedConfig = parsed;
|
|
30
|
+
return cachedConfig;
|
|
31
|
+
}
|
|
32
|
+
async function getApiKey(signal) {
|
|
33
|
+
const key = await resolveCredential({
|
|
34
|
+
provider: "Searchinfinity",
|
|
35
|
+
configuredValue: loadConfig().searchinfinityApiKey,
|
|
36
|
+
environmentValue: process.env.SEARCHINFINITY_API_KEY,
|
|
37
|
+
signal,
|
|
38
|
+
});
|
|
39
|
+
if (!key) {
|
|
40
|
+
throw new Error("Searchinfinity API key not found. Either:\n" +
|
|
41
|
+
` 1. Create ${CONFIG_PATH} with { "searchinfinityApiKey": "your-key" }\n` +
|
|
42
|
+
" 2. Set SEARCHINFINITY_API_KEY environment variable\n" +
|
|
43
|
+
"Create a key at https://console.byteplus.com/search-infinity/api-key");
|
|
44
|
+
}
|
|
45
|
+
return key;
|
|
46
|
+
}
|
|
47
|
+
export function isSearchinfinityAvailable() {
|
|
48
|
+
return hasCredentialSource({
|
|
49
|
+
provider: "Searchinfinity",
|
|
50
|
+
configuredValue: loadConfig().searchinfinityApiKey,
|
|
51
|
+
environmentValue: process.env.SEARCHINFINITY_API_KEY,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function errorMessage(err) {
|
|
55
|
+
return err instanceof Error ? err.message : String(err);
|
|
56
|
+
}
|
|
57
|
+
function requestSignal(signal, timeoutMs) {
|
|
58
|
+
const timeout = AbortSignal.timeout(timeoutMs);
|
|
59
|
+
return signal ? AbortSignal.any([signal, timeout]) : timeout;
|
|
60
|
+
}
|
|
61
|
+
function normalizeNumResults(value) {
|
|
62
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
63
|
+
return 5;
|
|
64
|
+
return Math.max(1, Math.min(Math.floor(value), 20));
|
|
65
|
+
}
|
|
66
|
+
function normalizeDomain(value) {
|
|
67
|
+
let input = value.trim().toLowerCase();
|
|
68
|
+
if (!input)
|
|
69
|
+
return null;
|
|
70
|
+
if (input.startsWith("-"))
|
|
71
|
+
input = input.slice(1).trim();
|
|
72
|
+
if (!input)
|
|
73
|
+
return null;
|
|
74
|
+
try {
|
|
75
|
+
const parsed = input.includes("://") ? new URL(input) : new URL(`https://${input}`);
|
|
76
|
+
input = parsed.hostname;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
input = input.split("/")[0]?.split(":")[0] ?? "";
|
|
80
|
+
}
|
|
81
|
+
input = input.replace(/^\.+|\.+$/g, "");
|
|
82
|
+
return /^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/i.test(input) ? input : null;
|
|
83
|
+
}
|
|
84
|
+
function mapRecencyFilter(recency) {
|
|
85
|
+
if (recency === "day")
|
|
86
|
+
return "OneDay";
|
|
87
|
+
if (recency === "week")
|
|
88
|
+
return "OneWeek";
|
|
89
|
+
if (recency === "month")
|
|
90
|
+
return "OneMonth";
|
|
91
|
+
if (recency === "year")
|
|
92
|
+
return "OneYear";
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
function buildSearchBody(query, options) {
|
|
96
|
+
const includeSites = [];
|
|
97
|
+
const blockHosts = [];
|
|
98
|
+
for (const raw of options.domainFilter ?? []) {
|
|
99
|
+
const domain = normalizeDomain(raw);
|
|
100
|
+
if (!domain)
|
|
101
|
+
continue;
|
|
102
|
+
const target = raw.trim().startsWith("-") ? blockHosts : includeSites;
|
|
103
|
+
if (target.length < 5 && !target.includes(domain))
|
|
104
|
+
target.push(domain);
|
|
105
|
+
}
|
|
106
|
+
const filter = {};
|
|
107
|
+
if (includeSites.length > 0)
|
|
108
|
+
filter.Sites = includeSites.join("|");
|
|
109
|
+
if (blockHosts.length > 0)
|
|
110
|
+
filter.BlockHosts = blockHosts.join("|");
|
|
111
|
+
const timeRange = mapRecencyFilter(options.recencyFilter);
|
|
112
|
+
return {
|
|
113
|
+
Query: query,
|
|
114
|
+
Count: normalizeNumResults(options.numResults),
|
|
115
|
+
...(Object.keys(filter).length > 0 ? { Filter: filter } : {}),
|
|
116
|
+
...(timeRange ? { TimeRange: timeRange } : {}),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// Map Searchinfinity business error codes to the closest HTTP semantics so
|
|
120
|
+
// error classification (auth/quota/invalid-request/transient) keeps working.
|
|
121
|
+
// CodeN carries the numeric code (e.g. 700901); Code may be a slug (e.g.
|
|
122
|
+
// "invalid_api_key"), so match both.
|
|
123
|
+
function businessErrorStatus(codeN, code, message) {
|
|
124
|
+
if (codeN === 700901 || code === "invalid_api_key")
|
|
125
|
+
return 401;
|
|
126
|
+
if (codeN === 700429 || code === "700429")
|
|
127
|
+
return 429;
|
|
128
|
+
if (codeN === 10400 || code === "10400")
|
|
129
|
+
return 400;
|
|
130
|
+
if (codeN === 10500 || code === "10500")
|
|
131
|
+
return 500;
|
|
132
|
+
if (codeN === 10403 || code === "10403")
|
|
133
|
+
return /quota|exhaust/i.test(message) ? 429 : 403;
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
async function searchinfinityJsonRequest(apiKey, body, signal) {
|
|
137
|
+
let response;
|
|
138
|
+
try {
|
|
139
|
+
response = await fetch(SEARCHINFINITY_SEARCH_URL, {
|
|
140
|
+
method: "POST",
|
|
141
|
+
headers: {
|
|
142
|
+
Authorization: `Bearer ${apiKey}`,
|
|
143
|
+
"Content-Type": "application/json",
|
|
144
|
+
},
|
|
145
|
+
body: JSON.stringify(body),
|
|
146
|
+
signal: requestSignal(signal, SEARCH_TIMEOUT_MS),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
const message = errorMessage(err);
|
|
151
|
+
const redactedMessage = redactCredential(message, apiKey);
|
|
152
|
+
if (redactedMessage === message)
|
|
153
|
+
throw err;
|
|
154
|
+
const redactedError = new Error(redactedMessage);
|
|
155
|
+
if (err instanceof Error)
|
|
156
|
+
redactedError.name = err.name;
|
|
157
|
+
throw redactedError;
|
|
158
|
+
}
|
|
159
|
+
const raw = await response.text();
|
|
160
|
+
if (!response.ok) {
|
|
161
|
+
throw new Error(`Searchinfinity Search API error ${response.status}: ${redactCredential(raw, apiKey).slice(0, 300)}`);
|
|
162
|
+
}
|
|
163
|
+
let data;
|
|
164
|
+
try {
|
|
165
|
+
data = JSON.parse(raw);
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
throw new Error(`Searchinfinity Search API returned invalid JSON: ${errorMessage(err)}`);
|
|
169
|
+
}
|
|
170
|
+
const businessError = data.ResponseMetadata?.Error;
|
|
171
|
+
if (businessError && (businessError.Code || businessError.Message)) {
|
|
172
|
+
const code = typeof businessError.Code === "string" && businessError.Code ? businessError.Code : "unknown";
|
|
173
|
+
const message = typeof businessError.Message === "string" && businessError.Message ? businessError.Message : "unknown error";
|
|
174
|
+
const status = businessErrorStatus(businessError.CodeN, code, message);
|
|
175
|
+
const codeLabel = typeof businessError.CodeN === "number" ? `${businessError.CodeN} ${code}` : code;
|
|
176
|
+
throw new Error(`Searchinfinity Search API error ${status ?? "unknown"}: ${message} (code ${codeLabel})`);
|
|
177
|
+
}
|
|
178
|
+
return data;
|
|
179
|
+
}
|
|
180
|
+
function mapSearchResults(results) {
|
|
181
|
+
if (!Array.isArray(results)) {
|
|
182
|
+
throw new Error("Searchinfinity Search API returned an unexpected response shape");
|
|
183
|
+
}
|
|
184
|
+
return results.flatMap((item) => {
|
|
185
|
+
if (!item || typeof item.Url !== "string" || item.Url.trim().length === 0)
|
|
186
|
+
return [];
|
|
187
|
+
const url = item.Url.trim();
|
|
188
|
+
const summary = typeof item.Summary === "string" ? item.Summary.replace(/\s+/g, " ").trim() : "";
|
|
189
|
+
const snippet = typeof item.Snippet === "string" ? item.Snippet.replace(/\s+/g, " ").trim() : "";
|
|
190
|
+
return [{
|
|
191
|
+
title: typeof item.Title === "string" && item.Title.trim() ? item.Title.trim() : url,
|
|
192
|
+
url,
|
|
193
|
+
snippet: summary || snippet,
|
|
194
|
+
}];
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
function buildAnswer(results) {
|
|
198
|
+
return results.map((result) => {
|
|
199
|
+
if (result.snippet)
|
|
200
|
+
return `${result.snippet}\nSource: ${result.title} (${result.url})`;
|
|
201
|
+
return `Source: ${result.title} (${result.url})`;
|
|
202
|
+
}).join("\n\n");
|
|
203
|
+
}
|
|
204
|
+
export async function searchWithSearchinfinity(query, options = {}) {
|
|
205
|
+
const apiKey = await getApiKey(options.signal);
|
|
206
|
+
const activityId = activityMonitor.logStart({ type: "api", query });
|
|
207
|
+
try {
|
|
208
|
+
const data = await searchinfinityJsonRequest(apiKey, buildSearchBody(query, options), options.signal);
|
|
209
|
+
const results = mapSearchResults(data.Result?.WebResults);
|
|
210
|
+
const response = { answer: buildAnswer(results), results };
|
|
211
|
+
activityMonitor.logComplete(activityId, 200);
|
|
212
|
+
return response;
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
const message = errorMessage(err);
|
|
216
|
+
const redactedMessage = redactCredential(message, apiKey);
|
|
217
|
+
if (redactedMessage.toLowerCase().includes("abort"))
|
|
218
|
+
activityMonitor.logComplete(activityId, 0);
|
|
219
|
+
else
|
|
220
|
+
activityMonitor.logError(activityId, redactedMessage);
|
|
221
|
+
if (redactedMessage === message)
|
|
222
|
+
throw err;
|
|
223
|
+
const redactedError = new Error(redactedMessage);
|
|
224
|
+
if (err instanceof Error)
|
|
225
|
+
redactedError.name = err.name;
|
|
226
|
+
throw redactedError;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=searchinfinity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchinfinity.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/searchinfinity.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst SEARCHINFINITY_SEARCH_URL = \"https://torchlight.byteintlapi.com/search_api/web_search\";\nconst CONFIG_PATH = getWebSearchConfigPath();\n// API Key authenticated requests time out server-side after 30 seconds.\nconst SEARCH_TIMEOUT_MS = 30_000;\n\ninterface WebSearchConfig {\n\tsearchinfinityApiKey?: unknown;\n}\n\ninterface SearchinfinityWebResult {\n\tId?: string;\n\tSortId?: number;\n\tTitle?: string | null;\n\tSiteName?: string | null;\n\tUrl?: string | null;\n\tSnippet?: string | null;\n\tSummary?: string | null;\n\tPublishTime?: string | null;\n\tLogoUrl?: string | null;\n}\n\ninterface SearchinfinitySearchResponse {\n\tResponseMetadata?: {\n\t\tRequestId?: string;\n\t\tError?: {\n\t\t\tCodeN?: number;\n\t\t\tCode?: string;\n\t\t\tMessage?: string;\n\t\t} | null;\n\t};\n\tResult?: {\n\t\tResultCount?: number;\n\t\tWebResults?: SearchinfinityWebResult[];\n\t\tSearchContext?: {\n\t\t\tOriginQuery?: string;\n\t\t\tSearchType?: string;\n\t\t};\n\t\tTimeCost?: number;\n\t\tLogId?: string;\n\t} | null;\n}\n\ninterface SearchinfinitySearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveCredential({\n\t\tprovider: \"Searchinfinity\",\n\t\tconfiguredValue: loadConfig().searchinfinityApiKey,\n\t\tenvironmentValue: process.env.SEARCHINFINITY_API_KEY,\n\t\tsignal,\n\t});\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Searchinfinity API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"searchinfinityApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set SEARCHINFINITY_API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://console.byteplus.com/search-infinity/api-key\",\n\t\t);\n\t}\n\treturn key;\n}\n\nexport function isSearchinfinityAvailable(): boolean {\n\treturn hasCredentialSource({\n\t\tprovider: \"Searchinfinity\",\n\t\tconfiguredValue: loadConfig().searchinfinityApiKey,\n\t\tenvironmentValue: process.env.SEARCHINFINITY_API_KEY,\n\t});\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction requestSignal(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {\n\tconst timeout = AbortSignal.timeout(timeoutMs);\n\treturn signal ? AbortSignal.any([signal, timeout]) : timeout;\n}\n\nfunction normalizeNumResults(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 20));\n}\n\nfunction normalizeDomain(value: string): string | null {\n\tlet input = value.trim().toLowerCase();\n\tif (!input) return null;\n\tif (input.startsWith(\"-\")) input = input.slice(1).trim();\n\tif (!input) return null;\n\ttry {\n\t\tconst parsed = input.includes(\"://\") ? new URL(input) : new URL(`https://${input}`);\n\t\tinput = parsed.hostname;\n\t} catch {\n\t\tinput = input.split(\"/\")[0]?.split(\":\")[0] ?? \"\";\n\t}\n\tinput = input.replace(/^\\.+|\\.+$/g, \"\");\n\treturn /^[a-z0-9][a-z0-9.-]*\\.[a-z]{2,}$/i.test(input) ? input : null;\n}\n\nfunction mapRecencyFilter(recency: SearchOptions[\"recencyFilter\"]): string | undefined {\n\tif (recency === \"day\") return \"OneDay\";\n\tif (recency === \"week\") return \"OneWeek\";\n\tif (recency === \"month\") return \"OneMonth\";\n\tif (recency === \"year\") return \"OneYear\";\n\treturn undefined;\n}\n\nfunction buildSearchBody(query: string, options: SearchinfinitySearchOptions): Record<string, unknown> {\n\tconst includeSites: string[] = [];\n\tconst blockHosts: string[] = [];\n\tfor (const raw of options.domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? blockHosts : includeSites;\n\t\tif (target.length < 5 && !target.includes(domain)) target.push(domain);\n\t}\n\tconst filter: Record<string, unknown> = {};\n\tif (includeSites.length > 0) filter.Sites = includeSites.join(\"|\");\n\tif (blockHosts.length > 0) filter.BlockHosts = blockHosts.join(\"|\");\n\n\tconst timeRange = mapRecencyFilter(options.recencyFilter);\n\treturn {\n\t\tQuery: query,\n\t\tCount: normalizeNumResults(options.numResults),\n\t\t...(Object.keys(filter).length > 0 ? { Filter: filter } : {}),\n\t\t...(timeRange ? { TimeRange: timeRange } : {}),\n\t};\n}\n\n// Map Searchinfinity business error codes to the closest HTTP semantics so\n// error classification (auth/quota/invalid-request/transient) keeps working.\n// CodeN carries the numeric code (e.g. 700901); Code may be a slug (e.g.\n// \"invalid_api_key\"), so match both.\nfunction businessErrorStatus(codeN: number | undefined, code: string, message: string): number | undefined {\n\tif (codeN === 700901 || code === \"invalid_api_key\") return 401;\n\tif (codeN === 700429 || code === \"700429\") return 429;\n\tif (codeN === 10400 || code === \"10400\") return 400;\n\tif (codeN === 10500 || code === \"10500\") return 500;\n\tif (codeN === 10403 || code === \"10403\") return /quota|exhaust/i.test(message) ? 429 : 403;\n\treturn undefined;\n}\n\nasync function searchinfinityJsonRequest(\n\tapiKey: string,\n\tbody: Record<string, unknown>,\n\tsignal?: AbortSignal,\n): Promise<SearchinfinitySearchResponse> {\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(SEARCHINFINITY_SEARCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: requestSignal(signal, SEARCH_TIMEOUT_MS),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tconst raw = await response.text();\n\tif (!response.ok) {\n\t\tthrow new Error(`Searchinfinity Search API error ${response.status}: ${redactCredential(raw, apiKey).slice(0, 300)}`);\n\t}\n\tlet data: SearchinfinitySearchResponse;\n\ttry {\n\t\tdata = JSON.parse(raw) as SearchinfinitySearchResponse;\n\t} catch (err) {\n\t\tthrow new Error(`Searchinfinity Search API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\tconst businessError = data.ResponseMetadata?.Error;\n\tif (businessError && (businessError.Code || businessError.Message)) {\n\t\tconst code = typeof businessError.Code === \"string\" && businessError.Code ? businessError.Code : \"unknown\";\n\t\tconst message = typeof businessError.Message === \"string\" && businessError.Message ? businessError.Message : \"unknown error\";\n\t\tconst status = businessErrorStatus(businessError.CodeN, code, message);\n\t\tconst codeLabel = typeof businessError.CodeN === \"number\" ? `${businessError.CodeN} ${code}` : code;\n\t\tthrow new Error(\n\t\t\t`Searchinfinity Search API error ${status ?? \"unknown\"}: ${message} (code ${codeLabel})`,\n\t\t);\n\t}\n\treturn data;\n}\n\nfunction mapSearchResults(results: SearchinfinityWebResult[] | undefined): SearchResponse[\"results\"] {\n\tif (!Array.isArray(results)) {\n\t\tthrow new Error(\"Searchinfinity Search API returned an unexpected response shape\");\n\t}\n\treturn results.flatMap((item) => {\n\t\tif (!item || typeof item.Url !== \"string\" || item.Url.trim().length === 0) return [];\n\t\tconst url = item.Url.trim();\n\t\tconst summary = typeof item.Summary === \"string\" ? item.Summary.replace(/\\s+/g, \" \").trim() : \"\";\n\t\tconst snippet = typeof item.Snippet === \"string\" ? item.Snippet.replace(/\\s+/g, \" \").trim() : \"\";\n\t\treturn [{\n\t\t\ttitle: typeof item.Title === \"string\" && item.Title.trim() ? item.Title.trim() : url,\n\t\t\turl,\n\t\t\tsnippet: summary || snippet,\n\t\t}];\n\t});\n}\n\nfunction buildAnswer(results: SearchResponse[\"results\"]): string {\n\treturn results.map((result) => {\n\t\tif (result.snippet) return `${result.snippet}\\nSource: ${result.title} (${result.url})`;\n\t\treturn `Source: ${result.title} (${result.url})`;\n\t}).join(\"\\n\\n\");\n}\n\nexport async function searchWithSearchinfinity(\n\tquery: string,\n\toptions: SearchinfinitySearchOptions = {},\n): Promise<SearchResponse> {\n\tconst apiKey = await getApiKey(options.signal);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\ttry {\n\t\tconst data = await searchinfinityJsonRequest(apiKey, buildSearchBody(query, options), options.signal);\n\t\tconst results = mapSearchResults(data.Result?.WebResults);\n\t\tconst response: SearchResponse = { answer: buildAnswer(results), results };\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn response;\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SearchOptions, SearchResponse } from "./perplexity.ts";
|
|
2
|
+
export declare function isSearXNGAvailable(): boolean;
|
|
3
|
+
export declare function searchWithSearXNG(query: string, options?: SearchOptions): Promise<SearchResponse>;
|
|
4
|
+
//# sourceMappingURL=searxng.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searxng.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/searxng.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAgB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAwLnF,wBAAgB,kBAAkB,IAAI,OAAO,CAK5C;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CA0D3G","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { fetchRemoteUrl, loadSsrfConfig } from \"./ssrf-protection.ts\";\nimport type { SearchOptions, SearchResult, SearchResponse } from \"./perplexity.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 30_000;\n\ninterface WebSearchConfig {\n\tsearxngBaseUrl?: unknown;\n\tsearxngHeaders?: unknown;\n}\n\ninterface NormalizedDomainFilters {\n\tallowed: string[];\n\tblocked: string[];\n}\n\ninterface SearXNGResult {\n\ttitle?: string;\n\turl?: string;\n\tcontent?: string;\n}\n\ninterface SearXNGResponse {\n\tresults?: SearXNGResult[];\n\tanswers?: string[];\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\ttry {\n\t\tcachedConfig = JSON.parse(raw) as WebSearchConfig;\n\t\treturn cachedConfig;\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n}\n\nfunction normalizeBaseUrl(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst trimmed = value.trim();\n\tif (!trimmed) return null;\n\ttry {\n\t\tconst url = new URL(trimmed);\n\t\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") return null;\n\t\tif (url.username || url.password) return null;\n\t\turl.pathname = url.pathname.replace(/\\/+$/, \"\");\n\t\turl.search = \"\";\n\t\turl.hash = \"\";\n\t\treturn url.toString().replace(/\\/+$/, \"\");\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction getBaseUrl(): string | null {\n\tconst configured = process.env.SEARXNG_BASE_URL;\n\treturn configured !== undefined\n\t\t? normalizeBaseUrl(configured)\n\t\t: normalizeBaseUrl(loadConfig().searxngBaseUrl);\n}\n\nfunction isValidHeaderValue(value: string): boolean {\n\ttry {\n\t\tnew Headers({ \"x-pi-web-access-validation\": value });\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction normalizeHeaders(value: unknown): Record<string, string> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return {};\n\tconst headers: Record<string, string> = {};\n\tfor (const [key, headerValue] of Object.entries(value as Record<string, unknown>)) {\n\t\tif (typeof headerValue !== \"string\") continue;\n\t\tconst name = key.trim();\n\t\t// RFC 7230 token chars only — reject empty or malformed header names.\n\t\tif (!name || !/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name)) continue;\n\t\tif (!isValidHeaderValue(headerValue)) continue;\n\t\theaders[name] = headerValue;\n\t}\n\treturn headers;\n}\n\nfunction getConfiguredHeaders(): Record<string, string> {\n\treturn normalizeHeaders(loadConfig().searxngHeaders);\n}\n\nfunction mergeDefaultHeaders(configured: Record<string, string>): Record<string, string> {\n\tconst headers: Record<string, string> = { Accept: \"application/json\" };\n\tfor (const [name, value] of Object.entries(configured)) {\n\t\tfor (const existing of Object.keys(headers)) {\n\t\t\tif (existing.toLowerCase() === name.toLowerCase()) delete headers[existing];\n\t\t}\n\t\theaders[name] = value;\n\t}\n\treturn headers;\n}\n\nfunction requireBaseUrl(): string {\n\tconst baseUrl = getBaseUrl();\n\tif (!baseUrl) {\n\t\tthrow new Error(\n\t\t\t\"SearXNG base URL is invalid or missing. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"searxngBaseUrl\": \"https://search.example.com\" }\\n` +\n\t\t\t\" 2. Set SEARXNG_BASE_URL to an HTTP(S) URL\",\n\t\t);\n\t}\n\treturn baseUrl;\n}\n\nfunction normalizeCount(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 20));\n}\n\nfunction normalizeDomain(value: string): string | null {\n\tlet input = value.trim().toLowerCase();\n\tif (!input) return null;\n\tif (input.startsWith(\"-\")) input = input.slice(1).trim();\n\tif (!input) return null;\n\ttry {\n\t\tconst parsed = input.includes(\"://\") ? new URL(input) : new URL(`https://${input}`);\n\t\tinput = parsed.hostname;\n\t} catch {\n\t\tinput = input.split(\"/\")[0]?.split(\":\")[0] ?? \"\";\n\t}\n\tinput = input.replace(/^\\.+|\\.+$/g, \"\");\n\treturn /^[a-z0-9][a-z0-9.-]*\\.[a-z]{2,}$/i.test(input) ? input : null;\n}\n\nfunction normalizeDomainFilters(domainFilter: string[] | undefined): NormalizedDomainFilters {\n\tconst filters: NormalizedDomainFilters = { allowed: [], blocked: [] };\n\tfor (const raw of domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? filters.blocked : filters.allowed;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn filters;\n}\n\nfunction buildSearXNGQuery(query: string, filters: NormalizedDomainFilters): string {\n\tconst parts = [query];\n\tif (filters.allowed.length === 1) {\n\t\tparts.push(`site:${filters.allowed[0]}`);\n\t} else if (filters.allowed.length > 1) {\n\t\tparts.push(filters.allowed.map(domain => `site:${domain}`).join(\" OR \"));\n\t}\n\tfor (const domain of filters.blocked) parts.push(`-site:${domain}`);\n\treturn parts.join(\" \");\n}\n\nfunction hostMatchesDomain(hostname: string, domain: string): boolean {\n\treturn hostname === domain || hostname.endsWith(`.${domain}`);\n}\n\nfunction matchesDomainFilters(url: string, filters: NormalizedDomainFilters): boolean {\n\tif (filters.allowed.length === 0 && filters.blocked.length === 0) return true;\n\tlet hostname: string;\n\ttry {\n\t\thostname = new URL(url).hostname.toLowerCase();\n\t} catch {\n\t\treturn false;\n\t}\n\tif (filters.allowed.length > 0 && !filters.allowed.some(domain => hostMatchesDomain(hostname, domain))) return false;\n\treturn !filters.blocked.some(domain => hostMatchesDomain(hostname, domain));\n}\n\nfunction mapTimeRange(recencyFilter: SearchOptions[\"recencyFilter\"]): string | null {\n\treturn recencyFilter === \"day\" || recencyFilter === \"week\" || recencyFilter === \"month\" || recencyFilter === \"year\"\n\t\t? recencyFilter\n\t\t: null;\n}\n\nexport function isSearXNGAvailable(): boolean {\n\tconst baseUrl = getBaseUrl();\n\tif (baseUrl === null) return false;\n\tloadSsrfConfig();\n\treturn true;\n}\n\nexport async function searchWithSearXNG(query: string, options: SearchOptions = {}): Promise<SearchResponse> {\n\tconst baseUrl = requireBaseUrl();\n\tconst numResults = normalizeCount(options.numResults);\n\tconst filters = normalizeDomainFilters(options.domainFilter);\n\tconst searchQuery = buildSearXNGQuery(query, filters);\n\tconst url = new URL(`${baseUrl}/search`);\n\turl.searchParams.set(\"q\", searchQuery);\n\turl.searchParams.set(\"format\", \"json\");\n\tconst timeRange = mapTimeRange(options.recencyFilter);\n\tif (timeRange) url.searchParams.set(\"time_range\", timeRange);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query: searchQuery });\n\n\ttry {\n\t\tconst headers = mergeDefaultHeaders(getConfiguredHeaders());\n\t\tconst response = await fetchRemoteUrl(url, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders,\n\t\t\tsignal: options.signal\n\t\t\t\t? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal])\n\t\t\t\t: AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t}, {\n\t\t\t...loadSsrfConfig(),\n\t\t\tonRedirect: ({ from, to, init }) => from.origin === to.origin ? init : { ...init, headers: { Accept: \"application/json\" } },\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tactivityMonitor.logError(activityId, `HTTP ${response.status}`);\n\t\t\tconst errorText = await response.text();\n\t\t\tthrow new Error(`SearXNG search error ${response.status}: ${errorText.slice(0, 300)}`);\n\t\t}\n\n\t\tlet data: SearXNGResponse;\n\t\ttry {\n\t\t\tdata = await response.json() as SearXNGResponse;\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\tthrow new Error(`SearXNG returned invalid JSON: ${message}`);\n\t\t}\n\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst results: SearchResult[] = [];\n\t\tfor (const item of data.results ?? []) {\n\t\t\tif (!item.url || !matchesDomainFilters(item.url, filters)) continue;\n\t\t\tresults.push({ title: item.title || item.url, url: item.url, snippet: item.content || \"\" });\n\t\t\tif (results.length >= numResults) break;\n\t\t}\n\n\t\tconst answerParts = (data.answers ?? []).filter((answer): answer is string => typeof answer === \"string\" && answer.trim().length > 0).map(answer => answer.trim());\n\t\tanswerParts.push(...results.map(result => result.snippet\n\t\t\t? `${result.snippet}\\nSource: ${result.title} (${result.url})`\n\t\t\t: `Source: ${result.title} (${result.url})`));\n\t\treturn { answer: answerParts.join(\"\\n\\n\"), results };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tif (message.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, message);\n\t\tthrow err;\n\t}\n}\n"]}
|