@humain/terminal 0.0.3-beta.3 → 0.0.4-beta.2
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 +30 -0
- package/README.md +1 -0
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js.map +1 -1
- package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
- package/dist/bun/restore-sandbox-env.js.map +1 -1
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +11 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth-check.d.ts.map +1 -1
- package/dist/cli/auth-check.js.map +1 -1
- package/dist/cli/auth-command.d.ts.map +1 -1
- package/dist/cli/auth-command.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/credential-print.d.ts.map +1 -1
- package/dist/cli/credential-print.js.map +1 -1
- package/dist/cli/experimental/auth.d.ts.map +1 -1
- package/dist/cli/experimental/auth.js.map +1 -1
- package/dist/cli/experimental/cli.d.ts.map +1 -1
- package/dist/cli/experimental/command-options.d.ts.map +1 -1
- package/dist/cli/experimental/command-options.js.map +1 -1
- package/dist/cli/experimental/command.d.ts.map +1 -1
- package/dist/cli/experimental/command.js +2 -5
- package/dist/cli/experimental/command.js.map +1 -1
- package/dist/cli/experimental/commands/client.d.ts.map +1 -1
- package/dist/cli/experimental/commands/client.js.map +1 -1
- package/dist/cli/experimental/commands/pi.d.ts.map +1 -1
- package/dist/cli/experimental/commands/pi.js.map +1 -1
- package/dist/cli/experimental/commands/server.d.ts.map +1 -1
- package/dist/cli/experimental/commands/server.js.map +1 -1
- package/dist/cli/experimental/transport-address.d.ts.map +1 -1
- package/dist/cli/experimental/transport-address.js.map +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/initial-message.d.ts +1 -1
- package/dist/cli/initial-message.d.ts.map +1 -1
- package/dist/cli/initial-message.js.map +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/project-trust.d.ts.map +1 -1
- package/dist/cli/project-trust.js.map +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/remote-session.d.ts.map +1 -1
- package/dist/client/remote-session.js.map +1 -1
- package/dist/client/transcript.d.ts.map +1 -1
- package/dist/client/transcript.js +1 -1
- package/dist/client/transcript.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +0 -8
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +36 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +107 -129
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +3 -8
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/cache-stats.d.ts.map +1 -1
- package/dist/core/cache-stats.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/defaults.d.ts.map +1 -1
- package/dist/core/diagnostics.d.ts.map +1 -1
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js.map +1 -1
- package/dist/core/experimental.d.ts +4 -0
- package/dist/core/experimental.d.ts.map +1 -1
- package/dist/core/experimental.js +4 -0
- package/dist/core/experimental.js.map +1 -1
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
- package/dist/core/export-html/ansi-to-html.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +22 -30
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +4 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +17 -18
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/keybindings.d.ts +24 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +0 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-config.d.ts +5 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +1 -2
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +0 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +15 -25
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/models-store.d.ts.map +1 -1
- package/dist/core/models-store.js +3 -4
- package/dist/core/models-store.js.map +1 -1
- package/dist/core/output-guard.d.ts.map +1 -1
- package/dist/core/output-guard.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +0 -7
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/pi-manifest.d.ts.map +1 -1
- package/dist/core/pi-manifest.js.map +1 -1
- package/dist/core/project-trust.d.ts.map +1 -1
- package/dist/core/project-trust.js.map +1 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-attribution.d.ts.map +1 -1
- package/dist/core/provider-attribution.js.map +1 -1
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/radius.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +0 -44
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/runtime-credentials.d.ts.map +1 -1
- package/dist/core/runtime-credentials.js +1 -2
- package/dist/core/runtime-credentials.js.map +1 -1
- package/dist/core/sdk.d.ts +5 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +3 -2
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-cwd.d.ts.map +1 -1
- package/dist/core/session-cwd.js +0 -1
- package/dist/core/session-cwd.js.map +1 -1
- package/dist/core/session-manager.d.ts +4 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +55 -35
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +6 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +19 -17
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/source-info.d.ts.map +1 -1
- package/dist/core/source-info.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/telemetry.d.ts.map +1 -1
- package/dist/core/telemetry.js.map +1 -1
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +10 -5
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +2 -0
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.d.ts +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +2 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +9 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +12 -18
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/path-utils.d.ts.map +1 -1
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +2 -0
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/subagent.d.ts +82 -0
- package/dist/core/tools/subagent.d.ts.map +1 -0
- package/dist/core/tools/subagent.js +980 -0
- package/dist/core/tools/subagent.js.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/truncate.d.ts.map +1 -1
- package/dist/core/tools/truncate.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +2 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +0 -1
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/core/usage-totals.d.ts.map +1 -1
- package/dist/core/usage-totals.js.map +1 -1
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +0 -2
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/huggingface.d.ts.map +1 -1
- package/dist/extensions/llama/huggingface.js +0 -2
- package/dist/extensions/llama/huggingface.js.map +1 -1
- package/dist/extensions/llama/index.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/extensions/llama/ui.d.ts.map +1 -1
- package/dist/extensions/llama/ui.js +12 -28
- package/dist/extensions/llama/ui.js.map +1 -1
- package/dist/humain/agent-execution-protocol.d.ts.map +1 -1
- package/dist/humain/agent-execution-protocol.js.map +1 -1
- package/dist/humain/agent-execution-runtime.d.ts.map +1 -1
- package/dist/humain/agent-execution-runtime.js.map +1 -1
- package/dist/humain/bedrock-provider/vendor/index.bundle.mjs +127 -7
- package/dist/humain/brand-logo.d.ts.map +1 -1
- package/dist/humain/index.d.ts.map +1 -1
- package/dist/humain/index.js.map +1 -1
- package/dist/humain/legacy-workflow-tiers.d.ts.map +1 -1
- package/dist/humain/legacy-workflow-tiers.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/CHANGELOG.md +36 -0
- package/dist/humain/mcp-adapter/vendor/README.md +47 -5
- package/dist/humain/mcp-adapter/vendor/cli.js +163 -1
- package/dist/humain/mcp-adapter/vendor/commands.ts +128 -22
- package/dist/humain/mcp-adapter/vendor/config.ts +25 -7
- package/dist/humain/mcp-adapter/vendor/direct-tools.ts +5 -4
- package/dist/humain/mcp-adapter/vendor/index.bundle.mjs +1663 -458
- package/dist/humain/mcp-adapter/vendor/index.ts +219 -32
- package/dist/humain/mcp-adapter/vendor/init.ts +36 -4
- package/dist/humain/mcp-adapter/vendor/lifecycle.ts +315 -24
- package/dist/humain/mcp-adapter/vendor/mcp-auth-flow.ts +39 -6
- package/dist/humain/mcp-adapter/vendor/mcp-bearer-store.ts +387 -0
- package/dist/humain/mcp-adapter/vendor/mcp-callback-server.ts +27 -3
- package/dist/humain/mcp-adapter/vendor/mcp-code.ts +4 -0
- package/dist/humain/mcp-adapter/vendor/mcp-panel.ts +42 -13
- package/dist/humain/mcp-adapter/vendor/metadata-cache.ts +32 -21
- package/dist/humain/mcp-adapter/vendor/package-mcp-loader.ts +168 -0
- package/dist/humain/mcp-adapter/vendor/package.json +179 -177
- package/dist/humain/mcp-adapter/vendor/proxy-modes.ts +5 -4
- package/dist/humain/mcp-adapter/vendor/request-headers-command.ts +31 -37
- package/dist/humain/mcp-adapter/vendor/search-ranking.ts +92 -22
- package/dist/humain/mcp-adapter/vendor/server-manager.ts +140 -2
- package/dist/humain/mcp-adapter/vendor/session-recovery.ts +7 -0
- package/dist/humain/mcp-adapter/vendor/tool-approval.ts +15 -2
- package/dist/humain/mcp-adapter/vendor/tool-result-renderer.ts +44 -4
- package/dist/humain/mcp-adapter/vendor/types.ts +2 -0
- package/dist/humain/mcp-adapter/vendor/ui-server.ts +18 -16
- package/dist/humain/mcp-adapter/vendor/utils.ts +70 -0
- package/dist/humain/mcp-adapter.d.ts.map +1 -1
- package/dist/humain/mcp-adapter.js.map +1 -1
- package/dist/humain/pi-agent-execution-host.d.ts.map +1 -1
- package/dist/humain/pi-agent-execution-host.js.map +1 -1
- package/dist/humain/web-access/host.d.ts.map +1 -1
- package/dist/humain/web-access/index.d.ts.map +1 -1
- package/dist/humain/web-access/index.js.map +1 -1
- package/dist/humain/web-access/vendor/activity.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/activity.js +7 -5
- package/dist/humain/web-access/vendor/activity.js.map +1 -1
- package/dist/humain/web-access/vendor/anysearch.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/anysearch.js +3 -2
- package/dist/humain/web-access/vendor/anysearch.js.map +1 -1
- package/dist/humain/web-access/vendor/auth-fetch.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/auth-fetch.js.map +1 -1
- package/dist/humain/web-access/vendor/bocha.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/bocha.js.map +1 -1
- package/dist/humain/web-access/vendor/brave.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/brave.js +14 -4
- package/dist/humain/web-access/vendor/brave.js.map +1 -1
- package/dist/humain/web-access/vendor/brightdata-unlocker.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/brightdata-unlocker.js.map +1 -1
- package/dist/humain/web-access/vendor/brightdata.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/brightdata.js.map +1 -1
- package/dist/humain/web-access/vendor/chrome-cookies.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/chrome-cookies.js +92 -14
- package/dist/humain/web-access/vendor/chrome-cookies.js.map +1 -1
- package/dist/humain/web-access/vendor/content-find.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/content-find.js.map +1 -1
- package/dist/humain/web-access/vendor/credential-source.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/credential-source.js +0 -2
- package/dist/humain/web-access/vendor/credential-source.js.map +1 -1
- package/dist/humain/web-access/vendor/curator-page.d.ts +3 -0
- package/dist/humain/web-access/vendor/curator-page.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/curator-page.js +4 -1
- package/dist/humain/web-access/vendor/curator-page.js.map +1 -1
- package/dist/humain/web-access/vendor/curator-server.d.ts +3 -0
- package/dist/humain/web-access/vendor/curator-server.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/curator-server.js +6 -0
- package/dist/humain/web-access/vendor/curator-server.js.map +1 -1
- package/dist/humain/web-access/vendor/data-uri-sanitize.d.ts +21 -0
- package/dist/humain/web-access/vendor/data-uri-sanitize.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/data-uri-sanitize.js +373 -0
- package/dist/humain/web-access/vendor/data-uri-sanitize.js.map +1 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/datalab-pdf-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/declared-web-links.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/declared-web-links.js.map +1 -1
- package/dist/humain/web-access/vendor/duckduckgo.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/duckduckgo.js.map +1 -1
- package/dist/humain/web-access/vendor/exa.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/exa.js +16 -7
- package/dist/humain/web-access/vendor/exa.js.map +1 -1
- package/dist/humain/web-access/vendor/extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/extract.js +45 -5
- package/dist/humain/web-access/vendor/extract.js.map +1 -1
- package/dist/humain/web-access/vendor/feature-config.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/feature-config.js.map +1 -1
- package/dist/humain/web-access/vendor/fetch-params.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/fetch-params.js.map +1 -1
- package/dist/humain/web-access/vendor/firecrawl.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/firecrawl.js +15 -2
- package/dist/humain/web-access/vendor/firecrawl.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-api.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-api.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-pdf-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-pdf-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-search.d.ts +2 -2
- package/dist/humain/web-access/vendor/gemini-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-search.js +25 -8
- package/dist/humain/web-access/vendor/gemini-search.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-url-context.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-url-context.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-web-config.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-web-config.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-web.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-web.js.map +1 -1
- package/dist/humain/web-access/vendor/github-api.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/github-api.js.map +1 -1
- package/dist/humain/web-access/vendor/github-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/github-extract.js +69 -35
- package/dist/humain/web-access/vendor/github-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/index.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/index.js +58 -54
- package/dist/humain/web-access/vendor/index.js.map +1 -1
- package/dist/humain/web-access/vendor/jina-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/jina-search.js.map +1 -1
- package/dist/humain/web-access/vendor/kagi.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/kagi.js.map +1 -1
- package/dist/humain/web-access/vendor/ollama.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/ollama.js.map +1 -1
- package/dist/humain/web-access/vendor/openai-search.d.ts +1 -1
- package/dist/humain/web-access/vendor/openai-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/openai-search.js +15 -5
- package/dist/humain/web-access/vendor/openai-search.js.map +1 -1
- package/dist/humain/web-access/vendor/page-query.d.ts +1 -2
- package/dist/humain/web-access/vendor/page-query.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/page-query.js +5 -2
- package/dist/humain/web-access/vendor/page-query.js.map +1 -1
- package/dist/humain/web-access/vendor/parallel-mcp.d.ts +10 -0
- package/dist/humain/web-access/vendor/parallel-mcp.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/parallel-mcp.js +224 -0
- package/dist/humain/web-access/vendor/parallel-mcp.js.map +1 -0
- package/dist/humain/web-access/vendor/parallel.d.ts +1 -0
- package/dist/humain/web-access/vendor/parallel.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/parallel.js +2 -2
- package/dist/humain/web-access/vendor/parallel.js.map +1 -1
- package/dist/humain/web-access/vendor/pdf-extract.d.ts +1 -0
- package/dist/humain/web-access/vendor/pdf-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/pdf-extract.js +15 -5
- package/dist/humain/web-access/vendor/pdf-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/perplexity.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/perplexity.js.map +1 -1
- package/dist/humain/web-access/vendor/querit.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/querit.js.map +1 -1
- package/dist/humain/web-access/vendor/query-rewrite.d.ts +3 -0
- package/dist/humain/web-access/vendor/query-rewrite.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/query-rewrite.js +42 -0
- package/dist/humain/web-access/vendor/query-rewrite.js.map +1 -0
- package/dist/humain/web-access/vendor/render-search-error.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/render-search-error.js.map +1 -1
- package/dist/humain/web-access/vendor/rsc-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/rsc-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/search1api.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/search1api.js.map +1 -1
- package/dist/humain/web-access/vendor/searchinfinity.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/searchinfinity.js.map +1 -1
- package/dist/humain/web-access/vendor/searxng.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/searxng.js.map +1 -1
- package/dist/humain/web-access/vendor/serpbase.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/serpbase.js.map +1 -1
- package/dist/humain/web-access/vendor/serpdive.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/serpdive.js.map +1 -1
- package/dist/humain/web-access/vendor/serper.d.ts +4 -0
- package/dist/humain/web-access/vendor/serper.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/serper.js +206 -0
- package/dist/humain/web-access/vendor/serper.js.map +1 -0
- package/dist/humain/web-access/vendor/source-check.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/source-check.js.map +1 -1
- package/dist/humain/web-access/vendor/ssrf-protection.d.ts +2 -0
- package/dist/humain/web-access/vendor/ssrf-protection.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/ssrf-protection.js +11 -2
- package/dist/humain/web-access/vendor/ssrf-protection.js.map +1 -1
- package/dist/humain/web-access/vendor/storage.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/storage.js.map +1 -1
- package/dist/humain/web-access/vendor/summary-model-scope.d.ts +5 -0
- package/dist/humain/web-access/vendor/summary-model-scope.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/summary-model-scope.js +10 -5
- package/dist/humain/web-access/vendor/summary-model-scope.js.map +1 -1
- package/dist/humain/web-access/vendor/summary-review.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/summary-review.js +40 -14
- package/dist/humain/web-access/vendor/summary-review.js.map +1 -1
- package/dist/humain/web-access/vendor/tavily.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/tavily.js +14 -4
- package/dist/humain/web-access/vendor/tavily.js.map +1 -1
- package/dist/humain/web-access/vendor/tinyfish.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/tinyfish.js.map +1 -1
- package/dist/humain/web-access/vendor/utils.d.ts +10 -0
- package/dist/humain/web-access/vendor/utils.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/utils.js +70 -0
- package/dist/humain/web-access/vendor/utils.js.map +1 -1
- package/dist/humain/web-access/vendor/valyu.d.ts +6 -0
- package/dist/humain/web-access/vendor/valyu.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/valyu.js +194 -0
- package/dist/humain/web-access/vendor/valyu.js.map +1 -0
- package/dist/humain/web-access/vendor/video-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/video-extract.js.map +1 -1
- package/dist/humain/web-access/vendor/xai-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/xai-search.js.map +1 -1
- package/dist/humain/web-access/vendor/youtube-extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/youtube-extract.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +4 -0
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/agent-exec-mode.d.ts.map +1 -1
- package/dist/modes/agent-exec-mode.js.map +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.js +6 -10
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +2 -9
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +4 -9
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +0 -3
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +1 -3
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +1 -3
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +5 -22
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +0 -5
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +1 -8
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-entry.js +1 -4
- package/dist/modes/interactive/components/custom-entry.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +1 -7
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
- package/dist/modes/interactive/components/daxnuts.js +6 -8
- package/dist/modes/interactive/components/daxnuts.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js +2 -2
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +0 -1
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +1 -7
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +2 -8
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +1 -9
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.js +2 -4
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -3
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +3 -9
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
- package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
- package/dist/modes/interactive/components/mermaid.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +14 -26
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +3 -11
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +9 -14
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +33 -57
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +10 -14
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +0 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +1 -3
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +0 -2
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +0 -2
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +0 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +19 -25
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +18 -34
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/trust-selector.js +0 -6
- package/dist/modes/interactive/components/trust-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +3 -6
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +0 -4
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +18 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +147 -137
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
- package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
- package/dist/modes/interactive/model-catalog-refresh.js +36 -0
- package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
- package/dist/modes/interactive/model-search.d.ts.map +1 -1
- package/dist/modes/interactive/model-search.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +2 -0
- package/dist/modes/interactive/theme/light.json +2 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +25 -18
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +9 -1
- package/dist/modes/interactive/theme/theme.d.ts +7 -5
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +12 -8
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +4 -1
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js +5 -2
- package/dist/modes/json-event.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/jsonl.d.ts.map +1 -1
- package/dist/modes/rpc/jsonl.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +9 -10
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/rpc-entry.d.ts.map +1 -1
- package/dist/rpc-entry.js.map +1 -1
- package/dist/server/create-harness.d.ts.map +1 -1
- package/dist/server/create-harness.js +2 -0
- package/dist/server/create-harness.js.map +1 -1
- package/dist/utils/abort.d.ts.map +1 -1
- package/dist/utils/abort.js.map +1 -1
- package/dist/utils/ansi.d.ts.map +1 -1
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +1 -1
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/deprecation.d.ts.map +1 -1
- package/dist/utils/deprecation.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/fs-watch.d.ts.map +1 -1
- package/dist/utils/fs-watch.js.map +1 -1
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/html.d.ts.map +1 -1
- package/dist/utils/html.js.map +1 -1
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-process.d.ts.map +1 -1
- package/dist/utils/image-process.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts.map +1 -1
- package/dist/utils/image-resize-core.js.map +1 -1
- package/dist/utils/image-resize-worker.d.ts.map +1 -1
- package/dist/utils/image-resize-worker.js.map +1 -1
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/json.d.ts.map +1 -1
- package/dist/utils/json.js.map +1 -1
- package/dist/utils/management-http.d.ts.map +1 -1
- package/dist/utils/management-http.js.map +1 -1
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/open-browser.d.ts.map +1 -1
- package/dist/utils/open-browser.js.map +1 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/photon.d.ts.map +1 -1
- package/dist/utils/photon.js.map +1 -1
- package/dist/utils/pi-user-agent.d.ts.map +1 -1
- package/dist/utils/pi-user-agent.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/sleep.d.ts.map +1 -1
- package/dist/utils/sleep.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +1 -1
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/dist/utils/tool-result-images.d.ts.map +1 -1
- package/dist/utils/tool-result-images.js.map +1 -1
- package/dist/utils/tools-manager.d.ts +10 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +14 -19
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js.map +1 -1
- package/dist/utils/windows-self-update.d.ts.map +1 -1
- package/dist/utils/windows-self-update.js.map +1 -1
- package/docs/compaction.md +3 -3
- package/docs/custom-provider.md +1 -1
- package/docs/environment-variables.md +1 -0
- package/docs/extensions.md +5 -1
- package/docs/json.md +6 -4
- package/docs/keybindings.md +8 -2
- package/docs/rpc.md +15 -4
- package/docs/sdk.md +9 -0
- package/docs/settings.md +31 -0
- package/docs/terminal-setup.md +23 -2
- package/docs/themes.md +23 -3
- package/docs/tui.md +2 -2
- package/docs/usage.md +3 -2
- package/examples/extensions/README.md +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +2 -2
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/minimal-mode.ts +6 -6
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +2 -2
- package/examples/extensions/subagent/README.md +24 -147
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +853 -661
- package/package.json +33 -33
- package/src/humain/mcp-adapter/UPSTREAM.md +1 -1
- package/src/humain/mcp-adapter/upstream.json +3 -3
- package/src/humain/mcp-adapter/vendor/CHANGELOG.md +36 -0
- package/src/humain/web-access/UPSTREAM.md +1 -1
- package/src/humain/web-access/upstream.json +4 -4
- package/examples/extensions/subagent/agents.ts +0 -126
- package/examples/extensions/subagent/index.ts +0 -1015
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/parallel.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA6CrE,UAAU,qBAAsB,SAAQ,aAAa;IACpD,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAqBD,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAyDD,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAmLD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,cAAc,CAAC,CAYpH;AAED,wBAAsB,mBAAmB,CACxC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAOlC","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { ExtractedContent, ExtractOptions } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst PARALLEL_SEARCH_URL = \"https://api.parallel.ai/v1/search\";\nconst PARALLEL_EXTRACT_URL = \"https://api.parallel.ai/v1/extract\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst MIN_PARALLEL_API_KEY_LENGTH = 8;\nconst MIN_USEFUL_CONTENT = 500;\nconst SEARCH_TIMEOUT_MS = 60_000;\n\nconst PLACEHOLDER_API_KEY_DENYLIST = new Set([\n\t\"replace_with_your_parallel_api_key\",\n\t\"parallel_api_key\",\n\t\"your-key\",\n\t\"your-key-here\",\n\t\"your-api-key-here\",\n\t\"dummy\",\n\t\"placeholder\",\n\t\"changeme\",\n\t\"insert-your-key\",\n\t\"insert-your-key-here\",\n\t\"api-key\",\n\t\"xxx\",\n]);\n\ninterface WebSearchConfig {\n\tparallelApiKey?: unknown;\n}\n\ninterface V1WebSearchResult {\n\turl: string;\n\ttitle?: string | null;\n\tpublish_date?: string | null;\n\texcerpts?: string[];\n}\n\ninterface V1ExtractResult {\n\turl: string;\n\ttitle?: string | null;\n\tpublish_date?: string | null;\n\texcerpts?: string[];\n\tfull_content?: string | null;\n}\n\ninterface ParallelSearchOptions 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\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\nexport function clearParallelConfigCache(): void {\n\tcachedConfig = null;\n}\n\nfunction normalizeApiKey(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst normalized = value.trim();\n\treturn normalized.length > 0 ? normalized : null;\n}\n\nfunction isPlaceholderApiKey(key: string): boolean {\n\tconst normalized = key.trim();\n\treturn normalized.length < MIN_PARALLEL_API_KEY_LENGTH || PLACEHOLDER_API_KEY_DENYLIST.has(normalized.toLowerCase());\n}\n\nasync function resolveApiKey(signal?: AbortSignal): Promise<string | null> {\n\tconst configKey = normalizeApiKey(loadConfig().parallelApiKey);\n\tif (configKey?.startsWith(\"$\") || configKey?.startsWith(\"!\")) {\n\t\tconst resolved = await resolveCredential({\n\t\t\tprovider: \"Parallel\",\n\t\t\tconfiguredValue: configKey,\n\t\t\tenvironmentValue: process.env.PARALLEL_API_KEY,\n\t\t\tsignal,\n\t\t});\n\t\treturn resolved && !isPlaceholderApiKey(resolved) ? resolved : null;\n\t}\n\n\tconst envKey = normalizeApiKey(process.env.PARALLEL_API_KEY);\n\tif (envKey && !isPlaceholderApiKey(envKey)) return envKey;\n\tif (configKey && !isPlaceholderApiKey(configKey)) return configKey;\n\treturn null;\n}\n\nfunction hasConfiguredApiKey(): boolean {\n\tconst configKey = normalizeApiKey(loadConfig().parallelApiKey);\n\tif (configKey?.startsWith(\"$\") || configKey?.startsWith(\"!\")) {\n\t\treturn hasCredentialSource({\n\t\t\tprovider: \"Parallel\",\n\t\t\tconfiguredValue: configKey,\n\t\t\tenvironmentValue: process.env.PARALLEL_API_KEY,\n\t\t});\n\t}\n\tconst envKey = normalizeApiKey(process.env.PARALLEL_API_KEY);\n\treturn (envKey !== null && !isPlaceholderApiKey(envKey)) || (configKey !== null && !isPlaceholderApiKey(configKey));\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveApiKey(signal);\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Parallel API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"parallelApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set PARALLEL_API_KEY environment variable\\n\" +\n\t\t\t\"Get a key at https://platform.parallel.ai\",\n\t\t);\n\t}\n\treturn key;\n}\n\nexport function hasParallelApiKey(): boolean {\n\treturn hasConfiguredApiKey();\n}\n\nexport function isParallelAvailable(): boolean {\n\treturn hasParallelApiKey();\n}\n\nfunction requestSignal(signal?: AbortSignal): AbortSignal {\n\tconst timeout = AbortSignal.timeout(SEARCH_TIMEOUT_MS);\n\treturn signal ? AbortSignal.any([signal, timeout]) : timeout;\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction activityContext(\n\turl: string,\n\tbody: Record<string, unknown>,\n): { type: \"api\" | \"fetch\"; query?: string; url?: string } {\n\tif (typeof body.objective === \"string\" && body.objective.trim().length > 0) {\n\t\treturn { type: \"api\", query: body.objective };\n\t}\n\n\tconst searchQueries = body.search_queries;\n\tif (Array.isArray(searchQueries) && typeof searchQueries[0] === \"string\") {\n\t\treturn { type: \"api\", query: searchQueries[0] };\n\t}\n\n\tconst urls = body.urls;\n\tif (Array.isArray(urls) && typeof urls[0] === \"string\") {\n\t\treturn { type: \"fetch\", url: urls[0] };\n\t}\n\n\treturn url.includes(\"/search\") ? { type: \"api\", query: \"Parallel search\" } : { type: \"fetch\", url };\n}\n\nfunction recencyToAfterDate(filter: string): string {\n\tconst now = new Date();\n\tconst offsets: Record<string, number> = { day: 1, week: 7, month: 30, year: 365 };\n\tconst days = offsets[filter] ?? 0;\n\treturn new Date(now.getTime() - days * 86_400_000).toISOString().slice(0, 10);\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): { include_domains?: string[]; exclude_domains?: string[] } {\n\tif (!domainFilter?.length) return {};\n\tconst include_domains: string[] = [];\n\tconst exclude_domains: 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(\"-\") ? exclude_domains : include_domains;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn {\n\t\t...(include_domains.length ? { include_domains } : {}),\n\t\t...(exclude_domains.length ? { exclude_domains } : {}),\n\t};\n}\n\nfunction buildSearchRequestBody(query: string, options: ParallelSearchOptions = {}): Record<string, unknown> {\n\tconst numResults = Math.max(1, Math.min(Math.floor(options.numResults ?? 5), 20));\n\tconst sourcePolicy = {\n\t\t...mapDomainFilter(options.domainFilter),\n\t\t...(options.recencyFilter ? { after_date: recencyToAfterDate(options.recencyFilter) } : {}),\n\t};\n\treturn {\n\t\tobjective: query,\n\t\tsearch_queries: [query],\n\t\tadvanced_settings: {\n\t\t\tmax_results: numResults,\n\t\t\t...(Object.keys(sourcePolicy).length > 0 ? { source_policy: sourcePolicy } : {}),\n\t\t},\n\t};\n}\n\nfunction normalizeExcerpts(value: unknown): string[] {\n\tif (!Array.isArray(value)) return [];\n\treturn value.filter((item): item is string => typeof item === \"string\" && item.trim().length > 0);\n}\n\nfunction mapSearchResults(results: V1WebSearchResult[] | undefined): SearchResponse[\"results\"] {\n\tif (!Array.isArray(results)) return [];\n\tconst mapped: SearchResponse[\"results\"] = [];\n\tfor (let i = 0; i < results.length; i++) {\n\t\tconst item = results[i];\n\t\tif (!item?.url) continue;\n\t\tconst excerpts = normalizeExcerpts(item.excerpts);\n\t\tmapped.push({\n\t\t\ttitle: item.title || `Source ${i + 1}`,\n\t\t\turl: item.url,\n\t\t\tsnippet: excerpts.length > 0 ? excerpts[0].replace(/\\s+/g, \" \").trim().slice(0, 200) : \"\",\n\t\t});\n\t}\n\treturn mapped;\n}\n\nfunction buildAnswerFromExcerpts(results: V1WebSearchResult[] | undefined): string {\n\tif (!Array.isArray(results)) return \"\";\n\tconst parts: string[] = [];\n\tfor (let i = 0; i < results.length; i++) {\n\t\tconst item = results[i];\n\t\tif (!item?.url) continue;\n\t\tconst excerpts = normalizeExcerpts(item.excerpts);\n\t\tif (excerpts.length === 0) continue;\n\t\tparts.push(`${excerpts.join(\" \")}\\nSource: ${item.title || `Source ${i + 1}`} (${item.url})`);\n\t}\n\treturn parts.join(\"\\n\\n\");\n}\n\nfunction mapInlineContent(results: V1WebSearchResult[] | undefined): ExtractedContent[] {\n\tif (!Array.isArray(results)) return [];\n\treturn results.flatMap((result) => {\n\t\tif (!result?.url) return [];\n\t\tconst excerpts = normalizeExcerpts(result.excerpts);\n\t\tif (excerpts.length === 0) return [];\n\t\treturn [{ url: result.url, title: result.title || \"\", content: excerpts.join(\"\\n\\n\"), error: null }];\n\t});\n}\n\nfunction resolveExtractContent(result: V1ExtractResult): string {\n\tconst fullContent = typeof result.full_content === \"string\" ? result.full_content.trim() : \"\";\n\treturn fullContent.length > 0 ? fullContent : normalizeExcerpts(result.excerpts).join(\"\\n\\n\");\n}\n\nfunction mapExtractResult(result: V1ExtractResult | undefined | null): ExtractedContent | null {\n\tif (!result?.url) return null;\n\tconst content = resolveExtractContent(result);\n\tif (content.length < MIN_USEFUL_CONTENT) return null;\n\treturn {\n\t\turl: result.url,\n\t\ttitle: typeof result.title === \"string\" ? result.title.trim() : \"\",\n\t\tcontent,\n\t\terror: null,\n\t};\n}\n\nfunction buildExtractRequestBody(url: string, options: ExtractOptions = {}, fullContent = false): Record<string, unknown> {\n\tconst body: Record<string, unknown> = { urls: [url] };\n\tconst prompt = options.prompt?.trim();\n\tif (prompt) body.objective = prompt;\n\tif (fullContent) body.advanced_settings = { full_content: true };\n\treturn body;\n}\n\nfunction findExtractResult(results: V1ExtractResult[] | undefined, url: string): V1ExtractResult | undefined {\n\tif (!Array.isArray(results)) return undefined;\n\treturn results.find(item => item?.url === url) ?? results[0];\n}\n\nfunction hasExtractUrlError(errors: unknown, url: string): boolean {\n\tif (!Array.isArray(errors)) return false;\n\treturn errors.some((entry) => {\n\t\tif (typeof entry === \"string\") return entry === url;\n\t\treturn typeof entry === \"object\" && entry !== null && (entry as { url?: unknown }).url === url;\n\t});\n}\n\nasync function fetchAndMapExtractResult(\n\turl: string,\n\tbody: Record<string, unknown>,\n\tsignal?: AbortSignal,\n): Promise<{ mapped: ExtractedContent | null; result: V1ExtractResult | undefined }> {\n\tconst data = await parallelFetch(PARALLEL_EXTRACT_URL, body, signal);\n\tif (hasExtractUrlError(data.errors, url)) return { mapped: null, result: undefined };\n\tconst result = findExtractResult(data.results as V1ExtractResult[] | undefined, url);\n\treturn { mapped: mapExtractResult(result), result };\n}\n\nexport async function searchWithParallel(query: string, options: ParallelSearchOptions = {}): Promise<SearchResponse> {\n\tconst data = await parallelFetch(PARALLEL_SEARCH_URL, buildSearchRequestBody(query, options), options.signal);\n\tconst results = data.results as V1WebSearchResult[] | undefined;\n\tconst response: SearchResponse = {\n\t\tanswer: buildAnswerFromExcerpts(results),\n\t\tresults: mapSearchResults(results),\n\t};\n\tif (options.includeContent) {\n\t\tconst inlineContent = mapInlineContent(results);\n\t\tif (inlineContent.length > 0) response.inlineContent = inlineContent;\n\t}\n\treturn response;\n}\n\nexport async function extractWithParallel(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions: ExtractOptions = {},\n): Promise<ExtractedContent | null> {\n\tconst initial = await fetchAndMapExtractResult(url, buildExtractRequestBody(url, options), signal);\n\tif (initial.mapped) return initial.mapped;\n\tif (!initial.result || resolveExtractContent(initial.result).length >= MIN_USEFUL_CONTENT) return null;\n\n\tconst retry = await fetchAndMapExtractResult(url, buildExtractRequestBody(url, options, true), signal);\n\treturn retry.mapped;\n}\n\nasync function parallelFetch(\n\turl: string,\n\tbody: Record<string, unknown>,\n\tsignal?: AbortSignal,\n): Promise<Record<string, unknown>> {\n\tconst apiKey = await getApiKey(signal);\n\tconst activityId = activityMonitor.logStart(activityContext(url, body));\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\t\"x-api-key\": 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),\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\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Parallel API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\n\ttry {\n\t\tconst data = await response.json() as Record<string, unknown>;\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\treturn data;\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Parallel API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/parallel.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA6CrE,UAAU,qBAAsB,SAAQ,aAAa;IACpD,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAqBD,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAaD,wBAAsB,qBAAqB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBxF;AA4BD,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAmLD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,cAAc,CAAC,CAYpH;AAED,wBAAsB,mBAAmB,CACxC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAOlC"}
|
|
@@ -53,7 +53,7 @@ function isPlaceholderApiKey(key) {
|
|
|
53
53
|
const normalized = key.trim();
|
|
54
54
|
return normalized.length < MIN_PARALLEL_API_KEY_LENGTH || PLACEHOLDER_API_KEY_DENYLIST.has(normalized.toLowerCase());
|
|
55
55
|
}
|
|
56
|
-
async function
|
|
56
|
+
export async function resolveParallelApiKey(signal) {
|
|
57
57
|
const configKey = normalizeApiKey(loadConfig().parallelApiKey);
|
|
58
58
|
if (configKey?.startsWith("$") || configKey?.startsWith("!")) {
|
|
59
59
|
const resolved = await resolveCredential({
|
|
@@ -84,7 +84,7 @@ function hasConfiguredApiKey() {
|
|
|
84
84
|
return (envKey !== null && !isPlaceholderApiKey(envKey)) || (configKey !== null && !isPlaceholderApiKey(configKey));
|
|
85
85
|
}
|
|
86
86
|
async function getApiKey(signal) {
|
|
87
|
-
const key = await
|
|
87
|
+
const key = await resolveParallelApiKey(signal);
|
|
88
88
|
if (!key) {
|
|
89
89
|
throw new Error("Parallel API key not found. Either:\n" +
|
|
90
90
|
` 1. Create ${CONFIG_PATH} with { "parallelApiKey": "your-key" }\n` +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/parallel.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { ExtractedContent, ExtractOptions } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst PARALLEL_SEARCH_URL = \"https://api.parallel.ai/v1/search\";\nconst PARALLEL_EXTRACT_URL = \"https://api.parallel.ai/v1/extract\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst MIN_PARALLEL_API_KEY_LENGTH = 8;\nconst MIN_USEFUL_CONTENT = 500;\nconst SEARCH_TIMEOUT_MS = 60_000;\n\nconst PLACEHOLDER_API_KEY_DENYLIST = new Set([\n\t\"replace_with_your_parallel_api_key\",\n\t\"parallel_api_key\",\n\t\"your-key\",\n\t\"your-key-here\",\n\t\"your-api-key-here\",\n\t\"dummy\",\n\t\"placeholder\",\n\t\"changeme\",\n\t\"insert-your-key\",\n\t\"insert-your-key-here\",\n\t\"api-key\",\n\t\"xxx\",\n]);\n\ninterface WebSearchConfig {\n\tparallelApiKey?: unknown;\n}\n\ninterface V1WebSearchResult {\n\turl: string;\n\ttitle?: string | null;\n\tpublish_date?: string | null;\n\texcerpts?: string[];\n}\n\ninterface V1ExtractResult {\n\turl: string;\n\ttitle?: string | null;\n\tpublish_date?: string | null;\n\texcerpts?: string[];\n\tfull_content?: string | null;\n}\n\ninterface ParallelSearchOptions 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\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\nexport function clearParallelConfigCache(): void {\n\tcachedConfig = null;\n}\n\nfunction normalizeApiKey(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst normalized = value.trim();\n\treturn normalized.length > 0 ? normalized : null;\n}\n\nfunction isPlaceholderApiKey(key: string): boolean {\n\tconst normalized = key.trim();\n\treturn normalized.length < MIN_PARALLEL_API_KEY_LENGTH || PLACEHOLDER_API_KEY_DENYLIST.has(normalized.toLowerCase());\n}\n\nasync function resolveApiKey(signal?: AbortSignal): Promise<string | null> {\n\tconst configKey = normalizeApiKey(loadConfig().parallelApiKey);\n\tif (configKey?.startsWith(\"$\") || configKey?.startsWith(\"!\")) {\n\t\tconst resolved = await resolveCredential({\n\t\t\tprovider: \"Parallel\",\n\t\t\tconfiguredValue: configKey,\n\t\t\tenvironmentValue: process.env.PARALLEL_API_KEY,\n\t\t\tsignal,\n\t\t});\n\t\treturn resolved && !isPlaceholderApiKey(resolved) ? resolved : null;\n\t}\n\n\tconst envKey = normalizeApiKey(process.env.PARALLEL_API_KEY);\n\tif (envKey && !isPlaceholderApiKey(envKey)) return envKey;\n\tif (configKey && !isPlaceholderApiKey(configKey)) return configKey;\n\treturn null;\n}\n\nfunction hasConfiguredApiKey(): boolean {\n\tconst configKey = normalizeApiKey(loadConfig().parallelApiKey);\n\tif (configKey?.startsWith(\"$\") || configKey?.startsWith(\"!\")) {\n\t\treturn hasCredentialSource({\n\t\t\tprovider: \"Parallel\",\n\t\t\tconfiguredValue: configKey,\n\t\t\tenvironmentValue: process.env.PARALLEL_API_KEY,\n\t\t});\n\t}\n\tconst envKey = normalizeApiKey(process.env.PARALLEL_API_KEY);\n\treturn (envKey !== null && !isPlaceholderApiKey(envKey)) || (configKey !== null && !isPlaceholderApiKey(configKey));\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveApiKey(signal);\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Parallel API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"parallelApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set PARALLEL_API_KEY environment variable\\n\" +\n\t\t\t\"Get a key at https://platform.parallel.ai\",\n\t\t);\n\t}\n\treturn key;\n}\n\nexport function hasParallelApiKey(): boolean {\n\treturn hasConfiguredApiKey();\n}\n\nexport function isParallelAvailable(): boolean {\n\treturn hasParallelApiKey();\n}\n\nfunction requestSignal(signal?: AbortSignal): AbortSignal {\n\tconst timeout = AbortSignal.timeout(SEARCH_TIMEOUT_MS);\n\treturn signal ? AbortSignal.any([signal, timeout]) : timeout;\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction activityContext(\n\turl: string,\n\tbody: Record<string, unknown>,\n): { type: \"api\" | \"fetch\"; query?: string; url?: string } {\n\tif (typeof body.objective === \"string\" && body.objective.trim().length > 0) {\n\t\treturn { type: \"api\", query: body.objective };\n\t}\n\n\tconst searchQueries = body.search_queries;\n\tif (Array.isArray(searchQueries) && typeof searchQueries[0] === \"string\") {\n\t\treturn { type: \"api\", query: searchQueries[0] };\n\t}\n\n\tconst urls = body.urls;\n\tif (Array.isArray(urls) && typeof urls[0] === \"string\") {\n\t\treturn { type: \"fetch\", url: urls[0] };\n\t}\n\n\treturn url.includes(\"/search\") ? { type: \"api\", query: \"Parallel search\" } : { type: \"fetch\", url };\n}\n\nfunction recencyToAfterDate(filter: string): string {\n\tconst now = new Date();\n\tconst offsets: Record<string, number> = { day: 1, week: 7, month: 30, year: 365 };\n\tconst days = offsets[filter] ?? 0;\n\treturn new Date(now.getTime() - days * 86_400_000).toISOString().slice(0, 10);\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): { include_domains?: string[]; exclude_domains?: string[] } {\n\tif (!domainFilter?.length) return {};\n\tconst include_domains: string[] = [];\n\tconst exclude_domains: 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(\"-\") ? exclude_domains : include_domains;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn {\n\t\t...(include_domains.length ? { include_domains } : {}),\n\t\t...(exclude_domains.length ? { exclude_domains } : {}),\n\t};\n}\n\nfunction buildSearchRequestBody(query: string, options: ParallelSearchOptions = {}): Record<string, unknown> {\n\tconst numResults = Math.max(1, Math.min(Math.floor(options.numResults ?? 5), 20));\n\tconst sourcePolicy = {\n\t\t...mapDomainFilter(options.domainFilter),\n\t\t...(options.recencyFilter ? { after_date: recencyToAfterDate(options.recencyFilter) } : {}),\n\t};\n\treturn {\n\t\tobjective: query,\n\t\tsearch_queries: [query],\n\t\tadvanced_settings: {\n\t\t\tmax_results: numResults,\n\t\t\t...(Object.keys(sourcePolicy).length > 0 ? { source_policy: sourcePolicy } : {}),\n\t\t},\n\t};\n}\n\nfunction normalizeExcerpts(value: unknown): string[] {\n\tif (!Array.isArray(value)) return [];\n\treturn value.filter((item): item is string => typeof item === \"string\" && item.trim().length > 0);\n}\n\nfunction mapSearchResults(results: V1WebSearchResult[] | undefined): SearchResponse[\"results\"] {\n\tif (!Array.isArray(results)) return [];\n\tconst mapped: SearchResponse[\"results\"] = [];\n\tfor (let i = 0; i < results.length; i++) {\n\t\tconst item = results[i];\n\t\tif (!item?.url) continue;\n\t\tconst excerpts = normalizeExcerpts(item.excerpts);\n\t\tmapped.push({\n\t\t\ttitle: item.title || `Source ${i + 1}`,\n\t\t\turl: item.url,\n\t\t\tsnippet: excerpts.length > 0 ? excerpts[0].replace(/\\s+/g, \" \").trim().slice(0, 200) : \"\",\n\t\t});\n\t}\n\treturn mapped;\n}\n\nfunction buildAnswerFromExcerpts(results: V1WebSearchResult[] | undefined): string {\n\tif (!Array.isArray(results)) return \"\";\n\tconst parts: string[] = [];\n\tfor (let i = 0; i < results.length; i++) {\n\t\tconst item = results[i];\n\t\tif (!item?.url) continue;\n\t\tconst excerpts = normalizeExcerpts(item.excerpts);\n\t\tif (excerpts.length === 0) continue;\n\t\tparts.push(`${excerpts.join(\" \")}\\nSource: ${item.title || `Source ${i + 1}`} (${item.url})`);\n\t}\n\treturn parts.join(\"\\n\\n\");\n}\n\nfunction mapInlineContent(results: V1WebSearchResult[] | undefined): ExtractedContent[] {\n\tif (!Array.isArray(results)) return [];\n\treturn results.flatMap((result) => {\n\t\tif (!result?.url) return [];\n\t\tconst excerpts = normalizeExcerpts(result.excerpts);\n\t\tif (excerpts.length === 0) return [];\n\t\treturn [{ url: result.url, title: result.title || \"\", content: excerpts.join(\"\\n\\n\"), error: null }];\n\t});\n}\n\nfunction resolveExtractContent(result: V1ExtractResult): string {\n\tconst fullContent = typeof result.full_content === \"string\" ? result.full_content.trim() : \"\";\n\treturn fullContent.length > 0 ? fullContent : normalizeExcerpts(result.excerpts).join(\"\\n\\n\");\n}\n\nfunction mapExtractResult(result: V1ExtractResult | undefined | null): ExtractedContent | null {\n\tif (!result?.url) return null;\n\tconst content = resolveExtractContent(result);\n\tif (content.length < MIN_USEFUL_CONTENT) return null;\n\treturn {\n\t\turl: result.url,\n\t\ttitle: typeof result.title === \"string\" ? result.title.trim() : \"\",\n\t\tcontent,\n\t\terror: null,\n\t};\n}\n\nfunction buildExtractRequestBody(url: string, options: ExtractOptions = {}, fullContent = false): Record<string, unknown> {\n\tconst body: Record<string, unknown> = { urls: [url] };\n\tconst prompt = options.prompt?.trim();\n\tif (prompt) body.objective = prompt;\n\tif (fullContent) body.advanced_settings = { full_content: true };\n\treturn body;\n}\n\nfunction findExtractResult(results: V1ExtractResult[] | undefined, url: string): V1ExtractResult | undefined {\n\tif (!Array.isArray(results)) return undefined;\n\treturn results.find(item => item?.url === url) ?? results[0];\n}\n\nfunction hasExtractUrlError(errors: unknown, url: string): boolean {\n\tif (!Array.isArray(errors)) return false;\n\treturn errors.some((entry) => {\n\t\tif (typeof entry === \"string\") return entry === url;\n\t\treturn typeof entry === \"object\" && entry !== null && (entry as { url?: unknown }).url === url;\n\t});\n}\n\nasync function fetchAndMapExtractResult(\n\turl: string,\n\tbody: Record<string, unknown>,\n\tsignal?: AbortSignal,\n): Promise<{ mapped: ExtractedContent | null; result: V1ExtractResult | undefined }> {\n\tconst data = await parallelFetch(PARALLEL_EXTRACT_URL, body, signal);\n\tif (hasExtractUrlError(data.errors, url)) return { mapped: null, result: undefined };\n\tconst result = findExtractResult(data.results as V1ExtractResult[] | undefined, url);\n\treturn { mapped: mapExtractResult(result), result };\n}\n\nexport async function searchWithParallel(query: string, options: ParallelSearchOptions = {}): Promise<SearchResponse> {\n\tconst data = await parallelFetch(PARALLEL_SEARCH_URL, buildSearchRequestBody(query, options), options.signal);\n\tconst results = data.results as V1WebSearchResult[] | undefined;\n\tconst response: SearchResponse = {\n\t\tanswer: buildAnswerFromExcerpts(results),\n\t\tresults: mapSearchResults(results),\n\t};\n\tif (options.includeContent) {\n\t\tconst inlineContent = mapInlineContent(results);\n\t\tif (inlineContent.length > 0) response.inlineContent = inlineContent;\n\t}\n\treturn response;\n}\n\nexport async function extractWithParallel(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions: ExtractOptions = {},\n): Promise<ExtractedContent | null> {\n\tconst initial = await fetchAndMapExtractResult(url, buildExtractRequestBody(url, options), signal);\n\tif (initial.mapped) return initial.mapped;\n\tif (!initial.result || resolveExtractContent(initial.result).length >= MIN_USEFUL_CONTENT) return null;\n\n\tconst retry = await fetchAndMapExtractResult(url, buildExtractRequestBody(url, options, true), signal);\n\treturn retry.mapped;\n}\n\nasync function parallelFetch(\n\turl: string,\n\tbody: Record<string, unknown>,\n\tsignal?: AbortSignal,\n): Promise<Record<string, unknown>> {\n\tconst apiKey = await getApiKey(signal);\n\tconst activityId = activityMonitor.logStart(activityContext(url, body));\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\t\"x-api-key\": 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),\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\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Parallel API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\n\ttry {\n\t\tconst data = await response.json() as Record<string, unknown>;\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\treturn data;\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Parallel API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"parallel.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/parallel.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { ExtractedContent, ExtractOptions } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst PARALLEL_SEARCH_URL = \"https://api.parallel.ai/v1/search\";\nconst PARALLEL_EXTRACT_URL = \"https://api.parallel.ai/v1/extract\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst MIN_PARALLEL_API_KEY_LENGTH = 8;\nconst MIN_USEFUL_CONTENT = 500;\nconst SEARCH_TIMEOUT_MS = 60_000;\n\nconst PLACEHOLDER_API_KEY_DENYLIST = new Set([\n\t\"replace_with_your_parallel_api_key\",\n\t\"parallel_api_key\",\n\t\"your-key\",\n\t\"your-key-here\",\n\t\"your-api-key-here\",\n\t\"dummy\",\n\t\"placeholder\",\n\t\"changeme\",\n\t\"insert-your-key\",\n\t\"insert-your-key-here\",\n\t\"api-key\",\n\t\"xxx\",\n]);\n\ninterface WebSearchConfig {\n\tparallelApiKey?: unknown;\n}\n\ninterface V1WebSearchResult {\n\turl: string;\n\ttitle?: string | null;\n\tpublish_date?: string | null;\n\texcerpts?: string[];\n}\n\ninterface V1ExtractResult {\n\turl: string;\n\ttitle?: string | null;\n\tpublish_date?: string | null;\n\texcerpts?: string[];\n\tfull_content?: string | null;\n}\n\ninterface ParallelSearchOptions 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\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\nexport function clearParallelConfigCache(): void {\n\tcachedConfig = null;\n}\n\nfunction normalizeApiKey(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst normalized = value.trim();\n\treturn normalized.length > 0 ? normalized : null;\n}\n\nfunction isPlaceholderApiKey(key: string): boolean {\n\tconst normalized = key.trim();\n\treturn normalized.length < MIN_PARALLEL_API_KEY_LENGTH || PLACEHOLDER_API_KEY_DENYLIST.has(normalized.toLowerCase());\n}\n\nexport async function resolveParallelApiKey(signal?: AbortSignal): Promise<string | null> {\n\tconst configKey = normalizeApiKey(loadConfig().parallelApiKey);\n\tif (configKey?.startsWith(\"$\") || configKey?.startsWith(\"!\")) {\n\t\tconst resolved = await resolveCredential({\n\t\t\tprovider: \"Parallel\",\n\t\t\tconfiguredValue: configKey,\n\t\t\tenvironmentValue: process.env.PARALLEL_API_KEY,\n\t\t\tsignal,\n\t\t});\n\t\treturn resolved && !isPlaceholderApiKey(resolved) ? resolved : null;\n\t}\n\n\tconst envKey = normalizeApiKey(process.env.PARALLEL_API_KEY);\n\tif (envKey && !isPlaceholderApiKey(envKey)) return envKey;\n\tif (configKey && !isPlaceholderApiKey(configKey)) return configKey;\n\treturn null;\n}\n\nfunction hasConfiguredApiKey(): boolean {\n\tconst configKey = normalizeApiKey(loadConfig().parallelApiKey);\n\tif (configKey?.startsWith(\"$\") || configKey?.startsWith(\"!\")) {\n\t\treturn hasCredentialSource({\n\t\t\tprovider: \"Parallel\",\n\t\t\tconfiguredValue: configKey,\n\t\t\tenvironmentValue: process.env.PARALLEL_API_KEY,\n\t\t});\n\t}\n\tconst envKey = normalizeApiKey(process.env.PARALLEL_API_KEY);\n\treturn (envKey !== null && !isPlaceholderApiKey(envKey)) || (configKey !== null && !isPlaceholderApiKey(configKey));\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveParallelApiKey(signal);\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Parallel API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"parallelApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set PARALLEL_API_KEY environment variable\\n\" +\n\t\t\t\"Get a key at https://platform.parallel.ai\",\n\t\t);\n\t}\n\treturn key;\n}\n\nexport function hasParallelApiKey(): boolean {\n\treturn hasConfiguredApiKey();\n}\n\nexport function isParallelAvailable(): boolean {\n\treturn hasParallelApiKey();\n}\n\nfunction requestSignal(signal?: AbortSignal): AbortSignal {\n\tconst timeout = AbortSignal.timeout(SEARCH_TIMEOUT_MS);\n\treturn signal ? AbortSignal.any([signal, timeout]) : timeout;\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction activityContext(\n\turl: string,\n\tbody: Record<string, unknown>,\n): { type: \"api\" | \"fetch\"; query?: string; url?: string } {\n\tif (typeof body.objective === \"string\" && body.objective.trim().length > 0) {\n\t\treturn { type: \"api\", query: body.objective };\n\t}\n\n\tconst searchQueries = body.search_queries;\n\tif (Array.isArray(searchQueries) && typeof searchQueries[0] === \"string\") {\n\t\treturn { type: \"api\", query: searchQueries[0] };\n\t}\n\n\tconst urls = body.urls;\n\tif (Array.isArray(urls) && typeof urls[0] === \"string\") {\n\t\treturn { type: \"fetch\", url: urls[0] };\n\t}\n\n\treturn url.includes(\"/search\") ? { type: \"api\", query: \"Parallel search\" } : { type: \"fetch\", url };\n}\n\nfunction recencyToAfterDate(filter: string): string {\n\tconst now = new Date();\n\tconst offsets: Record<string, number> = { day: 1, week: 7, month: 30, year: 365 };\n\tconst days = offsets[filter] ?? 0;\n\treturn new Date(now.getTime() - days * 86_400_000).toISOString().slice(0, 10);\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): { include_domains?: string[]; exclude_domains?: string[] } {\n\tif (!domainFilter?.length) return {};\n\tconst include_domains: string[] = [];\n\tconst exclude_domains: 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(\"-\") ? exclude_domains : include_domains;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn {\n\t\t...(include_domains.length ? { include_domains } : {}),\n\t\t...(exclude_domains.length ? { exclude_domains } : {}),\n\t};\n}\n\nfunction buildSearchRequestBody(query: string, options: ParallelSearchOptions = {}): Record<string, unknown> {\n\tconst numResults = Math.max(1, Math.min(Math.floor(options.numResults ?? 5), 20));\n\tconst sourcePolicy = {\n\t\t...mapDomainFilter(options.domainFilter),\n\t\t...(options.recencyFilter ? { after_date: recencyToAfterDate(options.recencyFilter) } : {}),\n\t};\n\treturn {\n\t\tobjective: query,\n\t\tsearch_queries: [query],\n\t\tadvanced_settings: {\n\t\t\tmax_results: numResults,\n\t\t\t...(Object.keys(sourcePolicy).length > 0 ? { source_policy: sourcePolicy } : {}),\n\t\t},\n\t};\n}\n\nfunction normalizeExcerpts(value: unknown): string[] {\n\tif (!Array.isArray(value)) return [];\n\treturn value.filter((item): item is string => typeof item === \"string\" && item.trim().length > 0);\n}\n\nfunction mapSearchResults(results: V1WebSearchResult[] | undefined): SearchResponse[\"results\"] {\n\tif (!Array.isArray(results)) return [];\n\tconst mapped: SearchResponse[\"results\"] = [];\n\tfor (let i = 0; i < results.length; i++) {\n\t\tconst item = results[i];\n\t\tif (!item?.url) continue;\n\t\tconst excerpts = normalizeExcerpts(item.excerpts);\n\t\tmapped.push({\n\t\t\ttitle: item.title || `Source ${i + 1}`,\n\t\t\turl: item.url,\n\t\t\tsnippet: excerpts.length > 0 ? excerpts[0].replace(/\\s+/g, \" \").trim().slice(0, 200) : \"\",\n\t\t});\n\t}\n\treturn mapped;\n}\n\nfunction buildAnswerFromExcerpts(results: V1WebSearchResult[] | undefined): string {\n\tif (!Array.isArray(results)) return \"\";\n\tconst parts: string[] = [];\n\tfor (let i = 0; i < results.length; i++) {\n\t\tconst item = results[i];\n\t\tif (!item?.url) continue;\n\t\tconst excerpts = normalizeExcerpts(item.excerpts);\n\t\tif (excerpts.length === 0) continue;\n\t\tparts.push(`${excerpts.join(\" \")}\\nSource: ${item.title || `Source ${i + 1}`} (${item.url})`);\n\t}\n\treturn parts.join(\"\\n\\n\");\n}\n\nfunction mapInlineContent(results: V1WebSearchResult[] | undefined): ExtractedContent[] {\n\tif (!Array.isArray(results)) return [];\n\treturn results.flatMap((result) => {\n\t\tif (!result?.url) return [];\n\t\tconst excerpts = normalizeExcerpts(result.excerpts);\n\t\tif (excerpts.length === 0) return [];\n\t\treturn [{ url: result.url, title: result.title || \"\", content: excerpts.join(\"\\n\\n\"), error: null }];\n\t});\n}\n\nfunction resolveExtractContent(result: V1ExtractResult): string {\n\tconst fullContent = typeof result.full_content === \"string\" ? result.full_content.trim() : \"\";\n\treturn fullContent.length > 0 ? fullContent : normalizeExcerpts(result.excerpts).join(\"\\n\\n\");\n}\n\nfunction mapExtractResult(result: V1ExtractResult | undefined | null): ExtractedContent | null {\n\tif (!result?.url) return null;\n\tconst content = resolveExtractContent(result);\n\tif (content.length < MIN_USEFUL_CONTENT) return null;\n\treturn {\n\t\turl: result.url,\n\t\ttitle: typeof result.title === \"string\" ? result.title.trim() : \"\",\n\t\tcontent,\n\t\terror: null,\n\t};\n}\n\nfunction buildExtractRequestBody(url: string, options: ExtractOptions = {}, fullContent = false): Record<string, unknown> {\n\tconst body: Record<string, unknown> = { urls: [url] };\n\tconst prompt = options.prompt?.trim();\n\tif (prompt) body.objective = prompt;\n\tif (fullContent) body.advanced_settings = { full_content: true };\n\treturn body;\n}\n\nfunction findExtractResult(results: V1ExtractResult[] | undefined, url: string): V1ExtractResult | undefined {\n\tif (!Array.isArray(results)) return undefined;\n\treturn results.find(item => item?.url === url) ?? results[0];\n}\n\nfunction hasExtractUrlError(errors: unknown, url: string): boolean {\n\tif (!Array.isArray(errors)) return false;\n\treturn errors.some((entry) => {\n\t\tif (typeof entry === \"string\") return entry === url;\n\t\treturn typeof entry === \"object\" && entry !== null && (entry as { url?: unknown }).url === url;\n\t});\n}\n\nasync function fetchAndMapExtractResult(\n\turl: string,\n\tbody: Record<string, unknown>,\n\tsignal?: AbortSignal,\n): Promise<{ mapped: ExtractedContent | null; result: V1ExtractResult | undefined }> {\n\tconst data = await parallelFetch(PARALLEL_EXTRACT_URL, body, signal);\n\tif (hasExtractUrlError(data.errors, url)) return { mapped: null, result: undefined };\n\tconst result = findExtractResult(data.results as V1ExtractResult[] | undefined, url);\n\treturn { mapped: mapExtractResult(result), result };\n}\n\nexport async function searchWithParallel(query: string, options: ParallelSearchOptions = {}): Promise<SearchResponse> {\n\tconst data = await parallelFetch(PARALLEL_SEARCH_URL, buildSearchRequestBody(query, options), options.signal);\n\tconst results = data.results as V1WebSearchResult[] | undefined;\n\tconst response: SearchResponse = {\n\t\tanswer: buildAnswerFromExcerpts(results),\n\t\tresults: mapSearchResults(results),\n\t};\n\tif (options.includeContent) {\n\t\tconst inlineContent = mapInlineContent(results);\n\t\tif (inlineContent.length > 0) response.inlineContent = inlineContent;\n\t}\n\treturn response;\n}\n\nexport async function extractWithParallel(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions: ExtractOptions = {},\n): Promise<ExtractedContent | null> {\n\tconst initial = await fetchAndMapExtractResult(url, buildExtractRequestBody(url, options), signal);\n\tif (initial.mapped) return initial.mapped;\n\tif (!initial.result || resolveExtractContent(initial.result).length >= MIN_USEFUL_CONTENT) return null;\n\n\tconst retry = await fetchAndMapExtractResult(url, buildExtractRequestBody(url, options, true), signal);\n\treturn retry.mapped;\n}\n\nasync function parallelFetch(\n\turl: string,\n\tbody: Record<string, unknown>,\n\tsignal?: AbortSignal,\n): Promise<Record<string, unknown>> {\n\tconst apiKey = await getApiKey(signal);\n\tconst activityId = activityMonitor.logStart(activityContext(url, body));\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\t\"x-api-key\": 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),\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\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Parallel API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\n\ttry {\n\t\tconst data = await response.json() as Record<string, unknown>;\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\treturn data;\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Parallel API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-extract.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/pdf-extract.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,EAMN,KAAK,WAAW,EAChB,MAAM,0BAA0B,CAAC;AAKlC,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAElE,eAAO,MAAM,mBAAmB,kBAK9B,CAAC;AAEH,MAAM,WAAW,SAAS;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,WAAW,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,eAAO,MAAM,sBAAsB,SAAU,CAAC;AAM9C,wBAAgB,aAAa,IAAI,SAAS,CA4DzC;AAsBD;;GAEG;AACH,wBAAsB,oBAAoB,CACzC,MAAM,EAAE,WAAW,EACnB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,iBAAsB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CA0H3B;AAyGD;;GAEG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAUhE","sourcesContent":["/**\n * PDF Content Extractor\n *\n * Converts PDFs to Markdown. The `auto` provider chain runs Datalab\n * (deterministic, layout-aware) first, then Gemini API, with unpdf as the\n * deterministic local fallback; the chain can also be pinned with\n * `pdf.provider`.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join, basename } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { CredentialResolutionError } from \"./credential-source.ts\";\nimport {\n\tDATALAB_MODE_VALUES,\n\tDEFAULT_DATALAB_TIMEOUT_MS,\n\tisDatalabApiAvailable,\n\tnormalizeDatalabMode,\n\textractPDFViaDatalab,\n\ttype DatalabMode,\n} from \"./datalab-pdf-extract.ts\";\nimport { isGeminiApiAvailable } from \"./gemini-api.ts\";\nimport { extractPDFViaGemini } from \"./gemini-pdf-extract.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nexport interface PDFExtractResult {\n\ttitle: string;\n\tpages: number;\n\tchars: number;\n\toutputPath: string;\n}\n\nexport interface PDFExtractOptions {\n\tmaxPages?: number;\n\toutputDir?: string;\n\tfilename?: string;\n\tsignal?: AbortSignal;\n\tgeminiTimeoutMs?: number;\n}\n\nexport type PDFProvider = \"auto\" | \"gemini\" | \"datalab\" | \"unpdf\";\n\nexport const PDF_PROVIDER_VALUES = new Set<PDFProvider>([\n\t\"auto\",\n\t\"gemini\",\n\t\"datalab\",\n\t\"unpdf\",\n]);\n\nexport interface PDFConfig {\n\tenabled: boolean;\n\tmaxSizeMB: number;\n\tprovider: PDFProvider;\n\tdatalabMode: DatalabMode;\n\tdatalabTimeoutMs: number;\n}\n\nexport const DEFAULT_PDF_MAX_SIZE_MB = 20;\nexport const MAX_PDF_MAX_SIZE_MB = 50;\nexport const MAX_DATALAB_TIMEOUT_MS = 300_000;\nconst DEFAULT_MAX_PAGES = 100;\nconst DEFAULT_OUTPUT_DIR = join(tmpdir(), \"pi-web-pdf\");\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst PAGE_MARKER_PATTERN = /^<!-- Page (\\d+) -->$/gm;\n\nexport function loadPDFConfig(): PDFConfig {\n\tif (!existsSync(CONFIG_PATH)) {\n\t\treturn {\n\t\t\tenabled: true,\n\t\t\tmaxSizeMB: DEFAULT_PDF_MAX_SIZE_MB,\n\t\t\tprovider: \"auto\",\n\t\t\tdatalabMode: normalizeDatalabMode(process.env.DATALAB_MODE),\n\t\t\tdatalabTimeoutMs: DEFAULT_DATALAB_TIMEOUT_MS,\n\t\t};\n\t}\n\n\tconst rawText = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(rawText) as unknown;\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\tconst root =\n\t\traw && typeof raw === \"object\" ? (raw as Record<string, unknown>) : {};\n\tconst pdf =\n\t\troot.pdf && typeof root.pdf === \"object\"\n\t\t\t? (root.pdf as Record<string, unknown>)\n\t\t\t: {};\n\tconst enabled = pdf.enabled !== false;\n\tconst configured = pdf.maxSizeMB;\n\tconst normalized =\n\t\ttypeof configured === \"number\" &&\n\t\tNumber.isFinite(configured) &&\n\t\tconfigured > 0\n\t\t\t? Math.min(configured, MAX_PDF_MAX_SIZE_MB)\n\t\t\t: DEFAULT_PDF_MAX_SIZE_MB;\n\n\tconst provider =\n\t\ttypeof pdf.provider === \"string\" &&\n\t\tPDF_PROVIDER_VALUES.has(pdf.provider as PDFProvider)\n\t\t\t? (pdf.provider as PDFProvider)\n\t\t\t: \"auto\";\n\tconst datalabMode =\n\t\ttypeof pdf.datalabMode === \"string\" &&\n\t\tDATALAB_MODE_VALUES.has(pdf.datalabMode as DatalabMode)\n\t\t\t? (pdf.datalabMode as DatalabMode)\n\t\t\t: normalizeDatalabMode(process.env.DATALAB_MODE);\n\tconst configuredTimeout = pdf.datalabTimeoutMs;\n\tconst datalabTimeoutMs =\n\t\ttypeof configuredTimeout === \"number\" &&\n\t\tNumber.isFinite(configuredTimeout) &&\n\t\tconfiguredTimeout > 0\n\t\t\t? Math.min(configuredTimeout, MAX_DATALAB_TIMEOUT_MS)\n\t\t\t: DEFAULT_DATALAB_TIMEOUT_MS;\n\n\treturn {\n\t\tenabled,\n\t\tmaxSizeMB: normalized,\n\t\tprovider,\n\t\tdatalabMode,\n\t\tdatalabTimeoutMs,\n\t};\n}\n\nasync function getUnpdf() {\n\tif (\n\t\ttypeof (Promise as PromiseConstructor & { try?: unknown }).try !==\n\t\t\"function\"\n\t) {\n\t\tconst { default: promiseTry } = await import(\"promise.try\");\n\t\tpromiseTry.shim();\n\t}\n\n\tconst [unpdf, pdfjs] = await Promise.all([\n\t\timport(\"unpdf\"),\n\t\timport(\"unpdf/pdfjs\"),\n\t]);\n\tconst { VerbosityLevel } = pdfjs as typeof pdfjs & {\n\t\tVerbosityLevel: { ERRORS: number };\n\t};\n\n\treturn { getDocumentProxy: unpdf.getDocumentProxy, VerbosityLevel };\n}\n\n/**\n * Extract text from a PDF buffer and save it to a Markdown file.\n */\nexport async function extractPDFToMarkdown(\n\tbuffer: ArrayBuffer,\n\turl: string,\n\toptions: PDFExtractOptions = {},\n): Promise<PDFExtractResult> {\n\tconst {\n\t\tmaxPages = DEFAULT_MAX_PAGES,\n\t\toutputDir = DEFAULT_OUTPUT_DIR,\n\t\tfilename,\n\t\tsignal,\n\t\tgeminiTimeoutMs,\n\t} = options;\n\n\tconst safeMaxPages = Number.isFinite(maxPages)\n\t\t? Math.max(1, Math.floor(maxPages))\n\t\t: DEFAULT_MAX_PAGES;\n\tconst urlTitle = extractTitleFromURL(url);\n\tconst pdfConfig = loadPDFConfig();\n\tconst provider = pdfConfig.provider;\n\n\tif (provider === \"auto\" || provider === \"datalab\") {\n\t\ttry {\n\t\t\tif (isDatalabApiAvailable()) {\n\t\t\t\tconst result = await extractPDFViaDatalab(buffer, {\n\t\t\t\t\tmaxPages: safeMaxPages,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tmode: pdfConfig.datalabMode,\n\t\t\t\t\ttimeoutMs: pdfConfig.datalabTimeoutMs,\n\t\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\t});\n\t\t\t\treturn writeMarkdownResult({\n\t\t\t\t\tmarkdownBody: result.markdown,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tpages: result.pages,\n\t\t\t\t\toutputDir,\n\t\t\t\t\tfilename,\n\t\t\t\t\turl,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (shouldRethrowExtractionError(err, signal)) throw err;\n\t\t}\n\t}\n\n\tif (provider === \"auto\" || provider === \"gemini\") {\n\t\ttry {\n\t\t\tif (isGeminiApiAvailable()) {\n\t\t\t\tconst markdownBody = await extractPDFViaGemini(buffer, {\n\t\t\t\t\tmaxPages: safeMaxPages,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\t\t...(geminiTimeoutMs !== undefined\n\t\t\t\t\t\t? { timeoutMs: geminiTimeoutMs }\n\t\t\t\t\t\t: {}),\n\t\t\t\t});\n\t\t\t\treturn writeMarkdownResult({\n\t\t\t\t\tmarkdownBody,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tpages: countPageMarkers(markdownBody),\n\t\t\t\t\toutputDir,\n\t\t\t\t\tfilename,\n\t\t\t\t\turl,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (shouldRethrowExtractionError(err, signal)) throw err;\n\t\t}\n\t}\n\n\tconst { getDocumentProxy, VerbosityLevel } = await getUnpdf();\n\tconst pdf = await getDocumentProxy(new Uint8Array(buffer), {\n\t\tverbosity: VerbosityLevel.ERRORS,\n\t});\n\tconst metadata = await pdf.getMetadata();\n\tconst metadataInfo =\n\t\tmetadata.info && typeof metadata.info === \"object\"\n\t\t\t? (metadata.info as Record<string, unknown>)\n\t\t\t: null;\n\n\tconst metaTitle =\n\t\ttypeof metadataInfo?.Title === \"string\" ? metadataInfo.Title : undefined;\n\tconst metaAuthor =\n\t\ttypeof metadataInfo?.Author === \"string\" ? metadataInfo.Author : undefined;\n\tconst title = metaTitle?.trim() || urlTitle;\n\tconst pagesToExtract = Math.min(pdf.numPages, safeMaxPages);\n\tconst truncated = pdf.numPages > safeMaxPages;\n\tconst pages: { pageNum: number; text: string }[] = [];\n\n\tfor (let i = 1; i <= pagesToExtract; i++) {\n\t\tconst page = await pdf.getPage(i);\n\t\tconst textContent = await page.getTextContent();\n\t\tconst pageText = textContent.items\n\t\t\t.map((item: unknown) => {\n\t\t\t\tconst textItem = item as { str?: string };\n\t\t\t\treturn textItem.str || \"\";\n\t\t\t})\n\t\t\t.join(\" \")\n\t\t\t.replace(/\\s+/g, \" \")\n\t\t\t.trim();\n\n\t\tif (pageText) {\n\t\t\tpages.push({ pageNum: i, text: pageText });\n\t\t}\n\t}\n\n\tconst bodyLines: string[] = [];\n\tfor (let i = 0; i < pages.length; i++) {\n\t\tif (i > 0) {\n\t\t\tbodyLines.push(\"\");\n\t\t\tbodyLines.push(`<!-- Page ${pages[i].pageNum} -->`);\n\t\t\tbodyLines.push(\"\");\n\t\t}\n\t\tbodyLines.push(pages[i].text);\n\t}\n\n\treturn writeMarkdownResult({\n\t\tmarkdownBody: bodyLines.join(\"\\n\"),\n\t\ttitle,\n\t\tpages: pdf.numPages,\n\t\toutputDir,\n\t\tfilename,\n\t\turl,\n\t\tmetaAuthor,\n\t\ttruncated,\n\t\tpagesToExtract,\n\t});\n}\n\nasync function writeMarkdownResult(options: {\n\tmarkdownBody: string;\n\ttitle: string;\n\tpages: number;\n\toutputDir: string;\n\tfilename?: string;\n\turl: string;\n\tmetaAuthor?: string;\n\ttruncated?: boolean;\n\tpagesToExtract?: number;\n}): Promise<PDFExtractResult> {\n\tconst lines: string[] = [];\n\tlines.push(`# ${options.title}`);\n\tlines.push(\"\");\n\tlines.push(`> Source: ${options.url}`);\n\tlines.push(\n\t\t`> Pages: ${options.pages}${options.truncated ? ` (extracted first ${options.pagesToExtract})` : \"\"}`,\n\t);\n\tif (options.metaAuthor) lines.push(`> Author: ${options.metaAuthor}`);\n\tlines.push(\"\");\n\tlines.push(\"---\");\n\tlines.push(\"\");\n\tif (options.markdownBody) lines.push(options.markdownBody);\n\n\tif (options.truncated) {\n\t\tlines.push(\"\");\n\t\tlines.push(\"---\");\n\t\tlines.push(\"\");\n\t\tlines.push(\n\t\t\t`*[Truncated: Only first ${options.pagesToExtract} of ${options.pages} pages extracted]*`,\n\t\t);\n\t}\n\n\tconst content = lines.join(\"\\n\");\n\tconst outputFilename =\n\t\toptions.filename || sanitizeFilename(options.title) + \".md\";\n\tconst outputPath = join(options.outputDir, outputFilename);\n\n\tawait mkdir(options.outputDir, { recursive: true });\n\tawait writeFile(outputPath, content, \"utf-8\");\n\n\treturn {\n\t\ttitle: options.title,\n\t\tpages: options.pages,\n\t\tchars: content.length,\n\t\toutputPath,\n\t};\n}\n\nfunction countPageMarkers(markdown: string): number {\n\treturn [...markdown.matchAll(PAGE_MARKER_PATTERN)].length;\n}\n\nfunction shouldRethrowExtractionError(\n\terr: unknown,\n\tsignal?: AbortSignal,\n): boolean {\n\tif (signal?.aborted) return true;\n\tif (err instanceof CredentialResolutionError) return true;\n\tconst message = err instanceof Error ? err.message : String(err);\n\treturn message.startsWith(\"Failed to parse \");\n}\n\n/**\n * Extract a reasonable title from URL\n */\nfunction extractTitleFromURL(url: string): string {\n\ttry {\n\t\tconst urlObj = new URL(url);\n\t\tconst pathname = urlObj.pathname;\n\n\t\tlet filename = basename(pathname, \".pdf\");\n\n\t\tif (urlObj.hostname.includes(\"arxiv.org\")) {\n\t\t\tconst match = pathname.match(/\\/(?:pdf|abs)\\/(\\d+\\.\\d+)/);\n\t\t\tif (match) {\n\t\t\t\tfilename = `arxiv-${match[1]}`;\n\t\t\t}\n\t\t}\n\n\t\tfilename = filename.replace(/[_-]+/g, \" \").replace(/\\s+/g, \" \").trim();\n\n\t\treturn filename || \"document\";\n\t} catch {\n\t\treturn \"document\";\n\t}\n}\n\n/**\n * Sanitize string for use as filename\n */\nfunction sanitizeFilename(name: string): string {\n\treturn (\n\t\tname\n\t\t\t.toLowerCase()\n\t\t\t.replace(/[^a-z0-9\\s-]/g, \"\")\n\t\t\t.replace(/\\s+/g, \"-\")\n\t\t\t.replace(/-+/g, \"-\")\n\t\t\t.slice(0, 100)\n\t\t\t.replace(/^-|-$/g, \"\") || \"document\"\n\t);\n}\n\n/**\n * Check if URL or content-type indicates a PDF\n */\nexport function isPDF(url: string, contentType?: string): boolean {\n\tif (contentType?.includes(\"application/pdf\")) {\n\t\treturn true;\n\t}\n\ttry {\n\t\tconst urlObj = new URL(url);\n\t\treturn urlObj.pathname.toLowerCase().endsWith(\".pdf\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pdf-extract.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/pdf-extract.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,EAMN,KAAK,WAAW,EAChB,MAAM,0BAA0B,CAAC;AAKlC,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAElE,eAAO,MAAM,mBAAmB,kBAK9B,CAAC;AAEH,MAAM,WAAW,SAAS;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,WAAW,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,eAAO,MAAM,sBAAsB,SAAU,CAAC;AAM9C,wBAAgB,aAAa,IAAI,SAAS,CAqEzC;AAsBD;;GAEG;AACH,wBAAsB,oBAAoB,CACzC,MAAM,EAAE,WAAW,EACnB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,iBAAsB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CA6H3B;AAyGD;;GAEG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAUhE"}
|
|
@@ -33,6 +33,7 @@ export function loadPDFConfig() {
|
|
|
33
33
|
return {
|
|
34
34
|
enabled: true,
|
|
35
35
|
maxSizeMB: DEFAULT_PDF_MAX_SIZE_MB,
|
|
36
|
+
maxPages: DEFAULT_MAX_PAGES,
|
|
36
37
|
provider: "auto",
|
|
37
38
|
datalabMode: normalizeDatalabMode(process.env.DATALAB_MODE),
|
|
38
39
|
datalabTimeoutMs: DEFAULT_DATALAB_TIMEOUT_MS,
|
|
@@ -58,6 +59,12 @@ export function loadPDFConfig() {
|
|
|
58
59
|
configured > 0
|
|
59
60
|
? Math.min(configured, MAX_PDF_MAX_SIZE_MB)
|
|
60
61
|
: DEFAULT_PDF_MAX_SIZE_MB;
|
|
62
|
+
const configuredMaxPages = pdf.maxPages;
|
|
63
|
+
const maxPages = typeof configuredMaxPages === "number" &&
|
|
64
|
+
Number.isFinite(configuredMaxPages) &&
|
|
65
|
+
configuredMaxPages > 0
|
|
66
|
+
? Math.max(1, Math.floor(configuredMaxPages))
|
|
67
|
+
: DEFAULT_MAX_PAGES;
|
|
61
68
|
const provider = typeof pdf.provider === "string" &&
|
|
62
69
|
PDF_PROVIDER_VALUES.has(pdf.provider)
|
|
63
70
|
? pdf.provider
|
|
@@ -75,6 +82,7 @@ export function loadPDFConfig() {
|
|
|
75
82
|
return {
|
|
76
83
|
enabled,
|
|
77
84
|
maxSizeMB: normalized,
|
|
85
|
+
maxPages,
|
|
78
86
|
provider,
|
|
79
87
|
datalabMode,
|
|
80
88
|
datalabTimeoutMs,
|
|
@@ -97,12 +105,14 @@ async function getUnpdf() {
|
|
|
97
105
|
* Extract text from a PDF buffer and save it to a Markdown file.
|
|
98
106
|
*/
|
|
99
107
|
export async function extractPDFToMarkdown(buffer, url, options = {}) {
|
|
100
|
-
const { maxPages
|
|
101
|
-
const safeMaxPages = Number.isFinite(maxPages)
|
|
102
|
-
? Math.max(1, Math.floor(maxPages))
|
|
103
|
-
: DEFAULT_MAX_PAGES;
|
|
104
|
-
const urlTitle = extractTitleFromURL(url);
|
|
108
|
+
const { maxPages, outputDir = DEFAULT_OUTPUT_DIR, filename, signal, geminiTimeoutMs, } = options;
|
|
105
109
|
const pdfConfig = loadPDFConfig();
|
|
110
|
+
const safeMaxPages = maxPages === undefined
|
|
111
|
+
? pdfConfig.maxPages
|
|
112
|
+
: Number.isFinite(maxPages)
|
|
113
|
+
? Math.max(1, Math.floor(maxPages))
|
|
114
|
+
: DEFAULT_MAX_PAGES;
|
|
115
|
+
const urlTitle = extractTitleFromURL(url);
|
|
106
116
|
const provider = pdfConfig.provider;
|
|
107
117
|
if (provider === "auto" || provider === "datalab") {
|
|
108
118
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-extract.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/pdf-extract.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PDF Content Extractor\n *\n * Converts PDFs to Markdown. The `auto` provider chain runs Datalab\n * (deterministic, layout-aware) first, then Gemini API, with unpdf as the\n * deterministic local fallback; the chain can also be pinned with\n * `pdf.provider`.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join, basename } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { CredentialResolutionError } from \"./credential-source.ts\";\nimport {\n\tDATALAB_MODE_VALUES,\n\tDEFAULT_DATALAB_TIMEOUT_MS,\n\tisDatalabApiAvailable,\n\tnormalizeDatalabMode,\n\textractPDFViaDatalab,\n\ttype DatalabMode,\n} from \"./datalab-pdf-extract.ts\";\nimport { isGeminiApiAvailable } from \"./gemini-api.ts\";\nimport { extractPDFViaGemini } from \"./gemini-pdf-extract.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nexport interface PDFExtractResult {\n\ttitle: string;\n\tpages: number;\n\tchars: number;\n\toutputPath: string;\n}\n\nexport interface PDFExtractOptions {\n\tmaxPages?: number;\n\toutputDir?: string;\n\tfilename?: string;\n\tsignal?: AbortSignal;\n\tgeminiTimeoutMs?: number;\n}\n\nexport type PDFProvider = \"auto\" | \"gemini\" | \"datalab\" | \"unpdf\";\n\nexport const PDF_PROVIDER_VALUES = new Set<PDFProvider>([\n\t\"auto\",\n\t\"gemini\",\n\t\"datalab\",\n\t\"unpdf\",\n]);\n\nexport interface PDFConfig {\n\tenabled: boolean;\n\tmaxSizeMB: number;\n\tprovider: PDFProvider;\n\tdatalabMode: DatalabMode;\n\tdatalabTimeoutMs: number;\n}\n\nexport const DEFAULT_PDF_MAX_SIZE_MB = 20;\nexport const MAX_PDF_MAX_SIZE_MB = 50;\nexport const MAX_DATALAB_TIMEOUT_MS = 300_000;\nconst DEFAULT_MAX_PAGES = 100;\nconst DEFAULT_OUTPUT_DIR = join(tmpdir(), \"pi-web-pdf\");\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst PAGE_MARKER_PATTERN = /^<!-- Page (\\d+) -->$/gm;\n\nexport function loadPDFConfig(): PDFConfig {\n\tif (!existsSync(CONFIG_PATH)) {\n\t\treturn {\n\t\t\tenabled: true,\n\t\t\tmaxSizeMB: DEFAULT_PDF_MAX_SIZE_MB,\n\t\t\tprovider: \"auto\",\n\t\t\tdatalabMode: normalizeDatalabMode(process.env.DATALAB_MODE),\n\t\t\tdatalabTimeoutMs: DEFAULT_DATALAB_TIMEOUT_MS,\n\t\t};\n\t}\n\n\tconst rawText = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(rawText) as unknown;\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\tconst root =\n\t\traw && typeof raw === \"object\" ? (raw as Record<string, unknown>) : {};\n\tconst pdf =\n\t\troot.pdf && typeof root.pdf === \"object\"\n\t\t\t? (root.pdf as Record<string, unknown>)\n\t\t\t: {};\n\tconst enabled = pdf.enabled !== false;\n\tconst configured = pdf.maxSizeMB;\n\tconst normalized =\n\t\ttypeof configured === \"number\" &&\n\t\tNumber.isFinite(configured) &&\n\t\tconfigured > 0\n\t\t\t? Math.min(configured, MAX_PDF_MAX_SIZE_MB)\n\t\t\t: DEFAULT_PDF_MAX_SIZE_MB;\n\n\tconst provider =\n\t\ttypeof pdf.provider === \"string\" &&\n\t\tPDF_PROVIDER_VALUES.has(pdf.provider as PDFProvider)\n\t\t\t? (pdf.provider as PDFProvider)\n\t\t\t: \"auto\";\n\tconst datalabMode =\n\t\ttypeof pdf.datalabMode === \"string\" &&\n\t\tDATALAB_MODE_VALUES.has(pdf.datalabMode as DatalabMode)\n\t\t\t? (pdf.datalabMode as DatalabMode)\n\t\t\t: normalizeDatalabMode(process.env.DATALAB_MODE);\n\tconst configuredTimeout = pdf.datalabTimeoutMs;\n\tconst datalabTimeoutMs =\n\t\ttypeof configuredTimeout === \"number\" &&\n\t\tNumber.isFinite(configuredTimeout) &&\n\t\tconfiguredTimeout > 0\n\t\t\t? Math.min(configuredTimeout, MAX_DATALAB_TIMEOUT_MS)\n\t\t\t: DEFAULT_DATALAB_TIMEOUT_MS;\n\n\treturn {\n\t\tenabled,\n\t\tmaxSizeMB: normalized,\n\t\tprovider,\n\t\tdatalabMode,\n\t\tdatalabTimeoutMs,\n\t};\n}\n\nasync function getUnpdf() {\n\tif (\n\t\ttypeof (Promise as PromiseConstructor & { try?: unknown }).try !==\n\t\t\"function\"\n\t) {\n\t\tconst { default: promiseTry } = await import(\"promise.try\");\n\t\tpromiseTry.shim();\n\t}\n\n\tconst [unpdf, pdfjs] = await Promise.all([\n\t\timport(\"unpdf\"),\n\t\timport(\"unpdf/pdfjs\"),\n\t]);\n\tconst { VerbosityLevel } = pdfjs as typeof pdfjs & {\n\t\tVerbosityLevel: { ERRORS: number };\n\t};\n\n\treturn { getDocumentProxy: unpdf.getDocumentProxy, VerbosityLevel };\n}\n\n/**\n * Extract text from a PDF buffer and save it to a Markdown file.\n */\nexport async function extractPDFToMarkdown(\n\tbuffer: ArrayBuffer,\n\turl: string,\n\toptions: PDFExtractOptions = {},\n): Promise<PDFExtractResult> {\n\tconst {\n\t\tmaxPages = DEFAULT_MAX_PAGES,\n\t\toutputDir = DEFAULT_OUTPUT_DIR,\n\t\tfilename,\n\t\tsignal,\n\t\tgeminiTimeoutMs,\n\t} = options;\n\n\tconst safeMaxPages = Number.isFinite(maxPages)\n\t\t? Math.max(1, Math.floor(maxPages))\n\t\t: DEFAULT_MAX_PAGES;\n\tconst urlTitle = extractTitleFromURL(url);\n\tconst pdfConfig = loadPDFConfig();\n\tconst provider = pdfConfig.provider;\n\n\tif (provider === \"auto\" || provider === \"datalab\") {\n\t\ttry {\n\t\t\tif (isDatalabApiAvailable()) {\n\t\t\t\tconst result = await extractPDFViaDatalab(buffer, {\n\t\t\t\t\tmaxPages: safeMaxPages,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tmode: pdfConfig.datalabMode,\n\t\t\t\t\ttimeoutMs: pdfConfig.datalabTimeoutMs,\n\t\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\t});\n\t\t\t\treturn writeMarkdownResult({\n\t\t\t\t\tmarkdownBody: result.markdown,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tpages: result.pages,\n\t\t\t\t\toutputDir,\n\t\t\t\t\tfilename,\n\t\t\t\t\turl,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (shouldRethrowExtractionError(err, signal)) throw err;\n\t\t}\n\t}\n\n\tif (provider === \"auto\" || provider === \"gemini\") {\n\t\ttry {\n\t\t\tif (isGeminiApiAvailable()) {\n\t\t\t\tconst markdownBody = await extractPDFViaGemini(buffer, {\n\t\t\t\t\tmaxPages: safeMaxPages,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\t\t...(geminiTimeoutMs !== undefined\n\t\t\t\t\t\t? { timeoutMs: geminiTimeoutMs }\n\t\t\t\t\t\t: {}),\n\t\t\t\t});\n\t\t\t\treturn writeMarkdownResult({\n\t\t\t\t\tmarkdownBody,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tpages: countPageMarkers(markdownBody),\n\t\t\t\t\toutputDir,\n\t\t\t\t\tfilename,\n\t\t\t\t\turl,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (shouldRethrowExtractionError(err, signal)) throw err;\n\t\t}\n\t}\n\n\tconst { getDocumentProxy, VerbosityLevel } = await getUnpdf();\n\tconst pdf = await getDocumentProxy(new Uint8Array(buffer), {\n\t\tverbosity: VerbosityLevel.ERRORS,\n\t});\n\tconst metadata = await pdf.getMetadata();\n\tconst metadataInfo =\n\t\tmetadata.info && typeof metadata.info === \"object\"\n\t\t\t? (metadata.info as Record<string, unknown>)\n\t\t\t: null;\n\n\tconst metaTitle =\n\t\ttypeof metadataInfo?.Title === \"string\" ? metadataInfo.Title : undefined;\n\tconst metaAuthor =\n\t\ttypeof metadataInfo?.Author === \"string\" ? metadataInfo.Author : undefined;\n\tconst title = metaTitle?.trim() || urlTitle;\n\tconst pagesToExtract = Math.min(pdf.numPages, safeMaxPages);\n\tconst truncated = pdf.numPages > safeMaxPages;\n\tconst pages: { pageNum: number; text: string }[] = [];\n\n\tfor (let i = 1; i <= pagesToExtract; i++) {\n\t\tconst page = await pdf.getPage(i);\n\t\tconst textContent = await page.getTextContent();\n\t\tconst pageText = textContent.items\n\t\t\t.map((item: unknown) => {\n\t\t\t\tconst textItem = item as { str?: string };\n\t\t\t\treturn textItem.str || \"\";\n\t\t\t})\n\t\t\t.join(\" \")\n\t\t\t.replace(/\\s+/g, \" \")\n\t\t\t.trim();\n\n\t\tif (pageText) {\n\t\t\tpages.push({ pageNum: i, text: pageText });\n\t\t}\n\t}\n\n\tconst bodyLines: string[] = [];\n\tfor (let i = 0; i < pages.length; i++) {\n\t\tif (i > 0) {\n\t\t\tbodyLines.push(\"\");\n\t\t\tbodyLines.push(`<!-- Page ${pages[i].pageNum} -->`);\n\t\t\tbodyLines.push(\"\");\n\t\t}\n\t\tbodyLines.push(pages[i].text);\n\t}\n\n\treturn writeMarkdownResult({\n\t\tmarkdownBody: bodyLines.join(\"\\n\"),\n\t\ttitle,\n\t\tpages: pdf.numPages,\n\t\toutputDir,\n\t\tfilename,\n\t\turl,\n\t\tmetaAuthor,\n\t\ttruncated,\n\t\tpagesToExtract,\n\t});\n}\n\nasync function writeMarkdownResult(options: {\n\tmarkdownBody: string;\n\ttitle: string;\n\tpages: number;\n\toutputDir: string;\n\tfilename?: string;\n\turl: string;\n\tmetaAuthor?: string;\n\ttruncated?: boolean;\n\tpagesToExtract?: number;\n}): Promise<PDFExtractResult> {\n\tconst lines: string[] = [];\n\tlines.push(`# ${options.title}`);\n\tlines.push(\"\");\n\tlines.push(`> Source: ${options.url}`);\n\tlines.push(\n\t\t`> Pages: ${options.pages}${options.truncated ? ` (extracted first ${options.pagesToExtract})` : \"\"}`,\n\t);\n\tif (options.metaAuthor) lines.push(`> Author: ${options.metaAuthor}`);\n\tlines.push(\"\");\n\tlines.push(\"---\");\n\tlines.push(\"\");\n\tif (options.markdownBody) lines.push(options.markdownBody);\n\n\tif (options.truncated) {\n\t\tlines.push(\"\");\n\t\tlines.push(\"---\");\n\t\tlines.push(\"\");\n\t\tlines.push(\n\t\t\t`*[Truncated: Only first ${options.pagesToExtract} of ${options.pages} pages extracted]*`,\n\t\t);\n\t}\n\n\tconst content = lines.join(\"\\n\");\n\tconst outputFilename =\n\t\toptions.filename || sanitizeFilename(options.title) + \".md\";\n\tconst outputPath = join(options.outputDir, outputFilename);\n\n\tawait mkdir(options.outputDir, { recursive: true });\n\tawait writeFile(outputPath, content, \"utf-8\");\n\n\treturn {\n\t\ttitle: options.title,\n\t\tpages: options.pages,\n\t\tchars: content.length,\n\t\toutputPath,\n\t};\n}\n\nfunction countPageMarkers(markdown: string): number {\n\treturn [...markdown.matchAll(PAGE_MARKER_PATTERN)].length;\n}\n\nfunction shouldRethrowExtractionError(\n\terr: unknown,\n\tsignal?: AbortSignal,\n): boolean {\n\tif (signal?.aborted) return true;\n\tif (err instanceof CredentialResolutionError) return true;\n\tconst message = err instanceof Error ? err.message : String(err);\n\treturn message.startsWith(\"Failed to parse \");\n}\n\n/**\n * Extract a reasonable title from URL\n */\nfunction extractTitleFromURL(url: string): string {\n\ttry {\n\t\tconst urlObj = new URL(url);\n\t\tconst pathname = urlObj.pathname;\n\n\t\tlet filename = basename(pathname, \".pdf\");\n\n\t\tif (urlObj.hostname.includes(\"arxiv.org\")) {\n\t\t\tconst match = pathname.match(/\\/(?:pdf|abs)\\/(\\d+\\.\\d+)/);\n\t\t\tif (match) {\n\t\t\t\tfilename = `arxiv-${match[1]}`;\n\t\t\t}\n\t\t}\n\n\t\tfilename = filename.replace(/[_-]+/g, \" \").replace(/\\s+/g, \" \").trim();\n\n\t\treturn filename || \"document\";\n\t} catch {\n\t\treturn \"document\";\n\t}\n}\n\n/**\n * Sanitize string for use as filename\n */\nfunction sanitizeFilename(name: string): string {\n\treturn (\n\t\tname\n\t\t\t.toLowerCase()\n\t\t\t.replace(/[^a-z0-9\\s-]/g, \"\")\n\t\t\t.replace(/\\s+/g, \"-\")\n\t\t\t.replace(/-+/g, \"-\")\n\t\t\t.slice(0, 100)\n\t\t\t.replace(/^-|-$/g, \"\") || \"document\"\n\t);\n}\n\n/**\n * Check if URL or content-type indicates a PDF\n */\nexport function isPDF(url: string, contentType?: string): boolean {\n\tif (contentType?.includes(\"application/pdf\")) {\n\t\treturn true;\n\t}\n\ttry {\n\t\tconst urlObj = new URL(url);\n\t\treturn urlObj.pathname.toLowerCase().endsWith(\".pdf\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pdf-extract.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/pdf-extract.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PDF Content Extractor\n *\n * Converts PDFs to Markdown. The `auto` provider chain runs Datalab\n * (deterministic, layout-aware) first, then Gemini API, with unpdf as the\n * deterministic local fallback; the chain can also be pinned with\n * `pdf.provider`.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join, basename } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { CredentialResolutionError } from \"./credential-source.ts\";\nimport {\n\tDATALAB_MODE_VALUES,\n\tDEFAULT_DATALAB_TIMEOUT_MS,\n\tisDatalabApiAvailable,\n\tnormalizeDatalabMode,\n\textractPDFViaDatalab,\n\ttype DatalabMode,\n} from \"./datalab-pdf-extract.ts\";\nimport { isGeminiApiAvailable } from \"./gemini-api.ts\";\nimport { extractPDFViaGemini } from \"./gemini-pdf-extract.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nexport interface PDFExtractResult {\n\ttitle: string;\n\tpages: number;\n\tchars: number;\n\toutputPath: string;\n}\n\nexport interface PDFExtractOptions {\n\tmaxPages?: number;\n\toutputDir?: string;\n\tfilename?: string;\n\tsignal?: AbortSignal;\n\tgeminiTimeoutMs?: number;\n}\n\nexport type PDFProvider = \"auto\" | \"gemini\" | \"datalab\" | \"unpdf\";\n\nexport const PDF_PROVIDER_VALUES = new Set<PDFProvider>([\n\t\"auto\",\n\t\"gemini\",\n\t\"datalab\",\n\t\"unpdf\",\n]);\n\nexport interface PDFConfig {\n\tenabled: boolean;\n\tmaxSizeMB: number;\n\tmaxPages: number;\n\tprovider: PDFProvider;\n\tdatalabMode: DatalabMode;\n\tdatalabTimeoutMs: number;\n}\n\nexport const DEFAULT_PDF_MAX_SIZE_MB = 20;\nexport const MAX_PDF_MAX_SIZE_MB = 50;\nexport const MAX_DATALAB_TIMEOUT_MS = 300_000;\nconst DEFAULT_MAX_PAGES = 100;\nconst DEFAULT_OUTPUT_DIR = join(tmpdir(), \"pi-web-pdf\");\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst PAGE_MARKER_PATTERN = /^<!-- Page (\\d+) -->$/gm;\n\nexport function loadPDFConfig(): PDFConfig {\n\tif (!existsSync(CONFIG_PATH)) {\n\t\treturn {\n\t\t\tenabled: true,\n\t\t\tmaxSizeMB: DEFAULT_PDF_MAX_SIZE_MB,\n\t\t\tmaxPages: DEFAULT_MAX_PAGES,\n\t\t\tprovider: \"auto\",\n\t\t\tdatalabMode: normalizeDatalabMode(process.env.DATALAB_MODE),\n\t\t\tdatalabTimeoutMs: DEFAULT_DATALAB_TIMEOUT_MS,\n\t\t};\n\t}\n\n\tconst rawText = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(rawText) as unknown;\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\tconst root =\n\t\traw && typeof raw === \"object\" ? (raw as Record<string, unknown>) : {};\n\tconst pdf =\n\t\troot.pdf && typeof root.pdf === \"object\"\n\t\t\t? (root.pdf as Record<string, unknown>)\n\t\t\t: {};\n\tconst enabled = pdf.enabled !== false;\n\tconst configured = pdf.maxSizeMB;\n\tconst normalized =\n\t\ttypeof configured === \"number\" &&\n\t\tNumber.isFinite(configured) &&\n\t\tconfigured > 0\n\t\t\t? Math.min(configured, MAX_PDF_MAX_SIZE_MB)\n\t\t\t: DEFAULT_PDF_MAX_SIZE_MB;\n\tconst configuredMaxPages = pdf.maxPages;\n\tconst maxPages =\n\t\ttypeof configuredMaxPages === \"number\" &&\n\t\tNumber.isFinite(configuredMaxPages) &&\n\t\tconfiguredMaxPages > 0\n\t\t\t? Math.max(1, Math.floor(configuredMaxPages))\n\t\t\t: DEFAULT_MAX_PAGES;\n\n\tconst provider =\n\t\ttypeof pdf.provider === \"string\" &&\n\t\tPDF_PROVIDER_VALUES.has(pdf.provider as PDFProvider)\n\t\t\t? (pdf.provider as PDFProvider)\n\t\t\t: \"auto\";\n\tconst datalabMode =\n\t\ttypeof pdf.datalabMode === \"string\" &&\n\t\tDATALAB_MODE_VALUES.has(pdf.datalabMode as DatalabMode)\n\t\t\t? (pdf.datalabMode as DatalabMode)\n\t\t\t: normalizeDatalabMode(process.env.DATALAB_MODE);\n\tconst configuredTimeout = pdf.datalabTimeoutMs;\n\tconst datalabTimeoutMs =\n\t\ttypeof configuredTimeout === \"number\" &&\n\t\tNumber.isFinite(configuredTimeout) &&\n\t\tconfiguredTimeout > 0\n\t\t\t? Math.min(configuredTimeout, MAX_DATALAB_TIMEOUT_MS)\n\t\t\t: DEFAULT_DATALAB_TIMEOUT_MS;\n\n\treturn {\n\t\tenabled,\n\t\tmaxSizeMB: normalized,\n\t\tmaxPages,\n\t\tprovider,\n\t\tdatalabMode,\n\t\tdatalabTimeoutMs,\n\t};\n}\n\nasync function getUnpdf() {\n\tif (\n\t\ttypeof (Promise as PromiseConstructor & { try?: unknown }).try !==\n\t\t\"function\"\n\t) {\n\t\tconst { default: promiseTry } = await import(\"promise.try\");\n\t\tpromiseTry.shim();\n\t}\n\n\tconst [unpdf, pdfjs] = await Promise.all([\n\t\timport(\"unpdf\"),\n\t\timport(\"unpdf/pdfjs\"),\n\t]);\n\tconst { VerbosityLevel } = pdfjs as typeof pdfjs & {\n\t\tVerbosityLevel: { ERRORS: number };\n\t};\n\n\treturn { getDocumentProxy: unpdf.getDocumentProxy, VerbosityLevel };\n}\n\n/**\n * Extract text from a PDF buffer and save it to a Markdown file.\n */\nexport async function extractPDFToMarkdown(\n\tbuffer: ArrayBuffer,\n\turl: string,\n\toptions: PDFExtractOptions = {},\n): Promise<PDFExtractResult> {\n\tconst {\n\t\tmaxPages,\n\t\toutputDir = DEFAULT_OUTPUT_DIR,\n\t\tfilename,\n\t\tsignal,\n\t\tgeminiTimeoutMs,\n\t} = options;\n\n\tconst pdfConfig = loadPDFConfig();\n\tconst safeMaxPages =\n\t\tmaxPages === undefined\n\t\t\t? pdfConfig.maxPages\n\t\t\t: Number.isFinite(maxPages)\n\t\t\t\t? Math.max(1, Math.floor(maxPages))\n\t\t\t\t: DEFAULT_MAX_PAGES;\n\tconst urlTitle = extractTitleFromURL(url);\n\tconst provider = pdfConfig.provider;\n\n\tif (provider === \"auto\" || provider === \"datalab\") {\n\t\ttry {\n\t\t\tif (isDatalabApiAvailable()) {\n\t\t\t\tconst result = await extractPDFViaDatalab(buffer, {\n\t\t\t\t\tmaxPages: safeMaxPages,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tmode: pdfConfig.datalabMode,\n\t\t\t\t\ttimeoutMs: pdfConfig.datalabTimeoutMs,\n\t\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\t});\n\t\t\t\treturn writeMarkdownResult({\n\t\t\t\t\tmarkdownBody: result.markdown,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tpages: result.pages,\n\t\t\t\t\toutputDir,\n\t\t\t\t\tfilename,\n\t\t\t\t\turl,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (shouldRethrowExtractionError(err, signal)) throw err;\n\t\t}\n\t}\n\n\tif (provider === \"auto\" || provider === \"gemini\") {\n\t\ttry {\n\t\t\tif (isGeminiApiAvailable()) {\n\t\t\t\tconst markdownBody = await extractPDFViaGemini(buffer, {\n\t\t\t\t\tmaxPages: safeMaxPages,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\t\t...(geminiTimeoutMs !== undefined\n\t\t\t\t\t\t? { timeoutMs: geminiTimeoutMs }\n\t\t\t\t\t\t: {}),\n\t\t\t\t});\n\t\t\t\treturn writeMarkdownResult({\n\t\t\t\t\tmarkdownBody,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tpages: countPageMarkers(markdownBody),\n\t\t\t\t\toutputDir,\n\t\t\t\t\tfilename,\n\t\t\t\t\turl,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (shouldRethrowExtractionError(err, signal)) throw err;\n\t\t}\n\t}\n\n\tconst { getDocumentProxy, VerbosityLevel } = await getUnpdf();\n\tconst pdf = await getDocumentProxy(new Uint8Array(buffer), {\n\t\tverbosity: VerbosityLevel.ERRORS,\n\t});\n\tconst metadata = await pdf.getMetadata();\n\tconst metadataInfo =\n\t\tmetadata.info && typeof metadata.info === \"object\"\n\t\t\t? (metadata.info as Record<string, unknown>)\n\t\t\t: null;\n\n\tconst metaTitle =\n\t\ttypeof metadataInfo?.Title === \"string\" ? metadataInfo.Title : undefined;\n\tconst metaAuthor =\n\t\ttypeof metadataInfo?.Author === \"string\" ? metadataInfo.Author : undefined;\n\tconst title = metaTitle?.trim() || urlTitle;\n\tconst pagesToExtract = Math.min(pdf.numPages, safeMaxPages);\n\tconst truncated = pdf.numPages > safeMaxPages;\n\tconst pages: { pageNum: number; text: string }[] = [];\n\n\tfor (let i = 1; i <= pagesToExtract; i++) {\n\t\tconst page = await pdf.getPage(i);\n\t\tconst textContent = await page.getTextContent();\n\t\tconst pageText = textContent.items\n\t\t\t.map((item: unknown) => {\n\t\t\t\tconst textItem = item as { str?: string };\n\t\t\t\treturn textItem.str || \"\";\n\t\t\t})\n\t\t\t.join(\" \")\n\t\t\t.replace(/\\s+/g, \" \")\n\t\t\t.trim();\n\n\t\tif (pageText) {\n\t\t\tpages.push({ pageNum: i, text: pageText });\n\t\t}\n\t}\n\n\tconst bodyLines: string[] = [];\n\tfor (let i = 0; i < pages.length; i++) {\n\t\tif (i > 0) {\n\t\t\tbodyLines.push(\"\");\n\t\t\tbodyLines.push(`<!-- Page ${pages[i].pageNum} -->`);\n\t\t\tbodyLines.push(\"\");\n\t\t}\n\t\tbodyLines.push(pages[i].text);\n\t}\n\n\treturn writeMarkdownResult({\n\t\tmarkdownBody: bodyLines.join(\"\\n\"),\n\t\ttitle,\n\t\tpages: pdf.numPages,\n\t\toutputDir,\n\t\tfilename,\n\t\turl,\n\t\tmetaAuthor,\n\t\ttruncated,\n\t\tpagesToExtract,\n\t});\n}\n\nasync function writeMarkdownResult(options: {\n\tmarkdownBody: string;\n\ttitle: string;\n\tpages: number;\n\toutputDir: string;\n\tfilename?: string;\n\turl: string;\n\tmetaAuthor?: string;\n\ttruncated?: boolean;\n\tpagesToExtract?: number;\n}): Promise<PDFExtractResult> {\n\tconst lines: string[] = [];\n\tlines.push(`# ${options.title}`);\n\tlines.push(\"\");\n\tlines.push(`> Source: ${options.url}`);\n\tlines.push(\n\t\t`> Pages: ${options.pages}${options.truncated ? ` (extracted first ${options.pagesToExtract})` : \"\"}`,\n\t);\n\tif (options.metaAuthor) lines.push(`> Author: ${options.metaAuthor}`);\n\tlines.push(\"\");\n\tlines.push(\"---\");\n\tlines.push(\"\");\n\tif (options.markdownBody) lines.push(options.markdownBody);\n\n\tif (options.truncated) {\n\t\tlines.push(\"\");\n\t\tlines.push(\"---\");\n\t\tlines.push(\"\");\n\t\tlines.push(\n\t\t\t`*[Truncated: Only first ${options.pagesToExtract} of ${options.pages} pages extracted]*`,\n\t\t);\n\t}\n\n\tconst content = lines.join(\"\\n\");\n\tconst outputFilename =\n\t\toptions.filename || sanitizeFilename(options.title) + \".md\";\n\tconst outputPath = join(options.outputDir, outputFilename);\n\n\tawait mkdir(options.outputDir, { recursive: true });\n\tawait writeFile(outputPath, content, \"utf-8\");\n\n\treturn {\n\t\ttitle: options.title,\n\t\tpages: options.pages,\n\t\tchars: content.length,\n\t\toutputPath,\n\t};\n}\n\nfunction countPageMarkers(markdown: string): number {\n\treturn [...markdown.matchAll(PAGE_MARKER_PATTERN)].length;\n}\n\nfunction shouldRethrowExtractionError(\n\terr: unknown,\n\tsignal?: AbortSignal,\n): boolean {\n\tif (signal?.aborted) return true;\n\tif (err instanceof CredentialResolutionError) return true;\n\tconst message = err instanceof Error ? err.message : String(err);\n\treturn message.startsWith(\"Failed to parse \");\n}\n\n/**\n * Extract a reasonable title from URL\n */\nfunction extractTitleFromURL(url: string): string {\n\ttry {\n\t\tconst urlObj = new URL(url);\n\t\tconst pathname = urlObj.pathname;\n\n\t\tlet filename = basename(pathname, \".pdf\");\n\n\t\tif (urlObj.hostname.includes(\"arxiv.org\")) {\n\t\t\tconst match = pathname.match(/\\/(?:pdf|abs)\\/(\\d+\\.\\d+)/);\n\t\t\tif (match) {\n\t\t\t\tfilename = `arxiv-${match[1]}`;\n\t\t\t}\n\t\t}\n\n\t\tfilename = filename.replace(/[_-]+/g, \" \").replace(/\\s+/g, \" \").trim();\n\n\t\treturn filename || \"document\";\n\t} catch {\n\t\treturn \"document\";\n\t}\n}\n\n/**\n * Sanitize string for use as filename\n */\nfunction sanitizeFilename(name: string): string {\n\treturn (\n\t\tname\n\t\t\t.toLowerCase()\n\t\t\t.replace(/[^a-z0-9\\s-]/g, \"\")\n\t\t\t.replace(/\\s+/g, \"-\")\n\t\t\t.replace(/-+/g, \"-\")\n\t\t\t.slice(0, 100)\n\t\t\t.replace(/^-|-$/g, \"\") || \"document\"\n\t);\n}\n\n/**\n * Check if URL or content-type indicates a PDF\n */\nexport function isPDF(url: string, contentType?: string): boolean {\n\tif (contentType?.includes(\"application/pdf\")) {\n\t\treturn true;\n\t}\n\ttry {\n\t\tconst urlObj = new URL(url);\n\t\treturn urlObj.pathname.toLowerCase().endsWith(\".pdf\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perplexity.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/perplexity.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAcrD,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAkED,wBAAgB,qBAAqB,IAAI,OAAO,CAM/C;AAED,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CA8F9G"
|
|
1
|
+
{"version":3,"file":"perplexity.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/perplexity.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAcrD,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAkED,wBAAgB,qBAAqB,IAAI,OAAO,CAM/C;AAED,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CA8F9G"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perplexity.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/perplexity.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { ExtractedContent } from \"./extract.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst PERPLEXITY_API_URL = \"https://api.perplexity.ai/chat/completions\";\nconst CONFIG_PATH = getWebSearchConfigPath();\n\nconst RATE_LIMIT = {\n\tmaxRequests: 10,\n\twindowMs: 60 * 1000,\n};\n\nconst requestTimestamps: number[] = [];\n\nexport interface SearchResult {\n\ttitle: string;\n\turl: string;\n\tsnippet: string;\n}\n\nexport interface SearchResponse {\n\tanswer: string;\n\tresults: SearchResult[];\n\tinlineContent?: ExtractedContent[];\n}\n\nexport interface SearchOptions {\n\tnumResults?: number;\n\trecencyFilter?: \"day\" | \"week\" | \"month\" | \"year\";\n\tdomainFilter?: string[];\n\tsignal?: AbortSignal;\n}\n\ninterface WebSearchConfig {\n\tperplexityApiKey?: unknown;\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 content = readFileSync(CONFIG_PATH, \"utf-8\");\n\ttry {\n\t\tcachedConfig = JSON.parse(content) 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\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveCredential({\n\t\tprovider: \"Perplexity\",\n\t\tconfiguredValue: loadConfig().perplexityApiKey,\n\t\tenvironmentValue: process.env.PERPLEXITY_API_KEY,\n\t\tsignal,\n\t});\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Perplexity API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"perplexityApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set PERPLEXITY_API_KEY environment variable\\n\" +\n\t\t\t\"Get a key at https://perplexity.ai/settings/api\"\n\t\t);\n\t}\n\treturn key;\n}\n\nfunction checkRateLimit(): void {\n\tconst now = Date.now();\n\tconst windowStart = now - RATE_LIMIT.windowMs;\n\n\twhile (requestTimestamps.length > 0 && requestTimestamps[0] < windowStart) {\n\t\trequestTimestamps.shift();\n\t}\n\n\tif (requestTimestamps.length >= RATE_LIMIT.maxRequests) {\n\t\tconst waitMs = requestTimestamps[0] + RATE_LIMIT.windowMs - now;\n\t\tthrow new Error(`Rate limited. Try again in ${Math.ceil(waitMs / 1000)}s`);\n\t}\n\n\trequestTimestamps.push(now);\n}\n\nfunction validateDomainFilter(domains: string[]): string[] {\n\treturn domains.filter((d) => {\n\t\tconst domain = d.startsWith(\"-\") ? d.slice(1) : d;\n\t\treturn /^[a-zA-Z0-9][a-zA-Z0-9-_.]*\\.[a-zA-Z]{2,}$/.test(domain);\n\t});\n}\n\nexport function isPerplexityAvailable(): boolean {\n\treturn hasCredentialSource({\n\t\tprovider: \"Perplexity\",\n\t\tconfiguredValue: loadConfig().perplexityApiKey,\n\t\tenvironmentValue: process.env.PERPLEXITY_API_KEY,\n\t});\n}\n\nexport async function searchWithPerplexity(query: string, options: SearchOptions = {}): Promise<SearchResponse> {\n\tcheckRateLimit();\n\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\n\tactivityMonitor.updateRateLimit({\n\t\tused: requestTimestamps.length,\n\t\tmax: RATE_LIMIT.maxRequests,\n\t\toldestTimestamp: requestTimestamps[0] ?? null,\n\t\twindowMs: RATE_LIMIT.windowMs,\n\t});\n\n\tconst apiKey = await getApiKey(options.signal);\n\tconst numResults = typeof options.numResults === \"number\" && Number.isFinite(options.numResults)\n\t\t? Math.max(1, Math.min(Math.floor(options.numResults), 20))\n\t\t: 5;\n\n\tconst requestBody: Record<string, unknown> = {\n\t\tmodel: \"sonar\",\n\t\tmessages: [{ role: \"user\", content: query }],\n\t\tmax_tokens: 1024,\n\t\treturn_related_questions: false,\n\t};\n\n\tif (options.recencyFilter) {\n\t\trequestBody.search_recency_filter = options.recencyFilter;\n\t}\n\n\tif (options.domainFilter && options.domainFilter.length > 0) {\n\t\tconst validated = validateDomainFilter(options.domainFilter);\n\t\tif (validated.length > 0) {\n\t\t\trequestBody.search_domain_filter = validated;\n\t\t}\n\t}\n\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(PERPLEXITY_API_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(requestBody),\n\t\t\t...(options.signal ? { signal: options.signal } : {}),\n\t\t});\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, redactedMessage);\n\t\t}\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\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Perplexity API error ${response.status}: ${errorText}`);\n\t}\n\n\tlet data: Record<string, unknown>;\n\ttry {\n\t\tdata = (await response.json()) as Record<string, unknown>;\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Perplexity API returned invalid JSON: ${message}`);\n\t}\n\n\tconst answer = (data.choices as Array<{ message?: { content?: string } }>)?.[0]?.message?.content || \"\";\n\tconst citations = Array.isArray(data.citations) ? data.citations : [];\n\n\tconst results: SearchResult[] = [];\n\tfor (let i = 0; i < Math.min(citations.length, numResults); i++) {\n\t\tconst citation = citations[i];\n\t\tif (typeof citation === \"string\") {\n\t\t\tresults.push({ title: `Source ${i + 1}`, url: citation, snippet: \"\" });\n\t\t} else if (citation && typeof citation === \"object\" && typeof citation.url === \"string\") {\n\t\t\tresults.push({\n\t\t\t\ttitle: citation.title || `Source ${i + 1}`,\n\t\t\t\turl: citation.url,\n\t\t\t\tsnippet: \"\",\n\t\t\t});\n\t\t}\n\t}\n\n\tactivityMonitor.logComplete(activityId, response.status);\n\treturn { answer, results };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"perplexity.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/perplexity.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { ExtractedContent } from \"./extract.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst PERPLEXITY_API_URL = \"https://api.perplexity.ai/chat/completions\";\nconst CONFIG_PATH = getWebSearchConfigPath();\n\nconst RATE_LIMIT = {\n\tmaxRequests: 10,\n\twindowMs: 60 * 1000,\n};\n\nconst requestTimestamps: number[] = [];\n\nexport interface SearchResult {\n\ttitle: string;\n\turl: string;\n\tsnippet: string;\n}\n\nexport interface SearchResponse {\n\tanswer: string;\n\tresults: SearchResult[];\n\tinlineContent?: ExtractedContent[];\n}\n\nexport interface SearchOptions {\n\tnumResults?: number;\n\trecencyFilter?: \"day\" | \"week\" | \"month\" | \"year\";\n\tdomainFilter?: string[];\n\tsignal?: AbortSignal;\n}\n\ninterface WebSearchConfig {\n\tperplexityApiKey?: unknown;\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 content = readFileSync(CONFIG_PATH, \"utf-8\");\n\ttry {\n\t\tcachedConfig = JSON.parse(content) 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\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveCredential({\n\t\tprovider: \"Perplexity\",\n\t\tconfiguredValue: loadConfig().perplexityApiKey,\n\t\tenvironmentValue: process.env.PERPLEXITY_API_KEY,\n\t\tsignal,\n\t});\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Perplexity API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"perplexityApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set PERPLEXITY_API_KEY environment variable\\n\" +\n\t\t\t\"Get a key at https://perplexity.ai/settings/api\"\n\t\t);\n\t}\n\treturn key;\n}\n\nfunction checkRateLimit(): void {\n\tconst now = Date.now();\n\tconst windowStart = now - RATE_LIMIT.windowMs;\n\n\twhile (requestTimestamps.length > 0 && requestTimestamps[0] < windowStart) {\n\t\trequestTimestamps.shift();\n\t}\n\n\tif (requestTimestamps.length >= RATE_LIMIT.maxRequests) {\n\t\tconst waitMs = requestTimestamps[0] + RATE_LIMIT.windowMs - now;\n\t\tthrow new Error(`Rate limited. Try again in ${Math.ceil(waitMs / 1000)}s`);\n\t}\n\n\trequestTimestamps.push(now);\n}\n\nfunction validateDomainFilter(domains: string[]): string[] {\n\treturn domains.filter((d) => {\n\t\tconst domain = d.startsWith(\"-\") ? d.slice(1) : d;\n\t\treturn /^[a-zA-Z0-9][a-zA-Z0-9-_.]*\\.[a-zA-Z]{2,}$/.test(domain);\n\t});\n}\n\nexport function isPerplexityAvailable(): boolean {\n\treturn hasCredentialSource({\n\t\tprovider: \"Perplexity\",\n\t\tconfiguredValue: loadConfig().perplexityApiKey,\n\t\tenvironmentValue: process.env.PERPLEXITY_API_KEY,\n\t});\n}\n\nexport async function searchWithPerplexity(query: string, options: SearchOptions = {}): Promise<SearchResponse> {\n\tcheckRateLimit();\n\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\n\tactivityMonitor.updateRateLimit({\n\t\tused: requestTimestamps.length,\n\t\tmax: RATE_LIMIT.maxRequests,\n\t\toldestTimestamp: requestTimestamps[0] ?? null,\n\t\twindowMs: RATE_LIMIT.windowMs,\n\t});\n\n\tconst apiKey = await getApiKey(options.signal);\n\tconst numResults = typeof options.numResults === \"number\" && Number.isFinite(options.numResults)\n\t\t? Math.max(1, Math.min(Math.floor(options.numResults), 20))\n\t\t: 5;\n\n\tconst requestBody: Record<string, unknown> = {\n\t\tmodel: \"sonar\",\n\t\tmessages: [{ role: \"user\", content: query }],\n\t\tmax_tokens: 1024,\n\t\treturn_related_questions: false,\n\t};\n\n\tif (options.recencyFilter) {\n\t\trequestBody.search_recency_filter = options.recencyFilter;\n\t}\n\n\tif (options.domainFilter && options.domainFilter.length > 0) {\n\t\tconst validated = validateDomainFilter(options.domainFilter);\n\t\tif (validated.length > 0) {\n\t\t\trequestBody.search_domain_filter = validated;\n\t\t}\n\t}\n\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(PERPLEXITY_API_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(requestBody),\n\t\t\t...(options.signal ? { signal: options.signal } : {}),\n\t\t});\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, redactedMessage);\n\t\t}\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\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Perplexity API error ${response.status}: ${errorText}`);\n\t}\n\n\tlet data: Record<string, unknown>;\n\ttry {\n\t\tdata = (await response.json()) as Record<string, unknown>;\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Perplexity API returned invalid JSON: ${message}`);\n\t}\n\n\tconst answer = (data.choices as Array<{ message?: { content?: string } }>)?.[0]?.message?.content || \"\";\n\tconst citations = Array.isArray(data.citations) ? data.citations : [];\n\n\tconst results: SearchResult[] = [];\n\tfor (let i = 0; i < Math.min(citations.length, numResults); i++) {\n\t\tconst citation = citations[i];\n\t\tif (typeof citation === \"string\") {\n\t\t\tresults.push({ title: `Source ${i + 1}`, url: citation, snippet: \"\" });\n\t\t} else if (citation && typeof citation === \"object\" && typeof citation.url === \"string\") {\n\t\t\tresults.push({\n\t\t\t\ttitle: citation.title || `Source ${i + 1}`,\n\t\t\t\turl: citation.url,\n\t\t\t\tsnippet: \"\",\n\t\t\t});\n\t\t}\n\t}\n\n\tactivityMonitor.logComplete(activityId, response.status);\n\treturn { answer, results };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"querit.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/querit.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA0DrE,UAAU,mBAAoB,SAAQ,aAAa;IAClD,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AA4CD,wBAAgB,iBAAiB,IAAI,OAAO,CAM3C;AA4OD,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAAC,cAAc,CAAC,CA+BzB;AAED,wBAAsB,iBAAiB,CACtC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA0BlC","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 QUERIT_SEARCH_URL = \"https://api.querit.ai/v1/search\";\nconst QUERIT_CONTENTS_URL = \"https://api.querit.ai/v1/contents\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\nconst CONTENTS_TIMEOUT_MS = 60_000;\nconst MAX_CONTENT_URLS = 10;\n\ninterface WebSearchConfig {\n\tqueritApiKey?: unknown;\n}\n\ninterface QueritSearchResult {\n\turl?: string | null;\n\ttitle?: string | null;\n\tsnippet?: string | null;\n\tpage_age?: string | null;\n\tsite_name?: string | null;\n}\n\ninterface QueritSearchResponse {\n\terror_code?: number | string;\n\terror_msg?: string;\n\tsearch_id?: number | string;\n\tresults?: { result?: QueritSearchResult[] };\n}\n\ninterface QueritContentMetadata {\n\ttitle?: string | null;\n\turl?: string | null;\n\tpublishTime?: string | null;\n\tsiteName?: string | null;\n\tsiteIcon?: string | null;\n}\n\ninterface QueritContentResult {\n\tid?: string | null;\n\turl?: string | null;\n\tcontent?: string | null;\n\textrasMeta?: QueritContentMetadata | null;\n}\n\ninterface QueritContentStatus {\n\tid?: string | null;\n\tstatus?: string | null;\n}\n\ninterface QueritContentsResponse {\n\terror_code?: number | string;\n\terror_msg?: string;\n\tsearch_id?: number | string;\n\tresults?: QueritContentResult[];\n\tstatuses?: QueritContentStatus[];\n\tsearchTime?: number;\n}\n\ninterface QueritSearchOptions 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: \"Querit\",\n\t\tconfiguredValue: loadConfig().queritApiKey,\n\t\tenvironmentValue: process.env.QUERIT_API_KEY,\n\t\tsignal,\n\t});\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Querit API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"queritApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set QUERIT_API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://www.querit.ai/en/dashboard/api-keys\",\n\t\t);\n\t}\n\treturn key;\n}\n\nexport function isQueritAvailable(): boolean {\n\treturn hasCredentialSource({\n\t\tprovider: \"Querit\",\n\t\tconfiguredValue: loadConfig().queritApiKey,\n\t\tenvironmentValue: process.env.QUERIT_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 mapDomainFilter(domainFilter: string[] | undefined): { include: string[]; exclude: string[] } {\n\tconst include: string[] = [];\n\tconst exclude: 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(\"-\") ? exclude : include;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn { include, exclude };\n}\n\nfunction mapRecencyFilter(value: SearchOptions[\"recencyFilter\"]): string | undefined {\n\tif (value === \"day\") return \"d1\";\n\tif (value === \"week\") return \"w1\";\n\tif (value === \"month\") return \"m1\";\n\tif (value === \"year\") return \"y1\";\n\treturn undefined;\n}\n\nfunction buildSearchBody(query: string, options: QueritSearchOptions): Record<string, unknown> {\n\tconst { include, exclude } = mapDomainFilter(options.domainFilter);\n\tconst date = mapRecencyFilter(options.recencyFilter);\n\tconst filters: Record<string, unknown> = {};\n\tif (include.length > 0 || exclude.length > 0) {\n\t\tfilters.sites = {\n\t\t\t...(include.length > 0 ? { include } : {}),\n\t\t\t...(exclude.length > 0 ? { exclude } : {}),\n\t\t};\n\t}\n\tif (date) filters.timeRange = { date };\n\treturn {\n\t\tquery,\n\t\tcount: normalizeNumResults(options.numResults),\n\t\t...(Object.keys(filters).length > 0 ? { filters } : {}),\n\t};\n}\n\nfunction normalizeTimeoutMs(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return CONTENTS_TIMEOUT_MS;\n\treturn Math.max(1, Math.floor(value));\n}\n\nfunction crawlTimeoutSeconds(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 10;\n\treturn Math.max(1, Math.min(Math.ceil(value / 1_000), 60));\n}\n\nfunction buildContentsBody(urls: string[], options: ExtractOptions = {}): Record<string, unknown> {\n\treturn {\n\t\turls,\n\t\tformat: \"markdown\",\n\t\tcrawlTimeout: crawlTimeoutSeconds(options.timeoutMs),\n\t\textrasMeta: true,\n\t};\n}\n\nasync function queritJsonRequest<T>(\n\tlabel: \"Search\" | \"Contents\",\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\tAccept: \"application/json\",\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 isRequestAbort = err instanceof Error\n\t\t\t? err.name === \"AbortError\" || err.name === \"TimeoutError\" || /abort|timeout/i.test(message)\n\t\t\t: /abort|timeout/i.test(message);\n\t\tif (!signal?.aborted && isRequestAbort) {\n\t\t\tconst timeoutError = new Error(`Querit ${label} API request timed out after ${Math.ceil(timeoutMs / 1_000)} seconds`);\n\t\t\ttimeoutError.name = \"TimeoutError\";\n\t\t\tthrow timeoutError;\n\t\t}\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(`Querit ${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(`Querit ${label} API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n}\n\nfunction assertApiSuccess(label: \"Search\" | \"Contents\", data: QueritSearchResponse | QueritContentsResponse): void {\n\tconst code = Number(data.error_code);\n\tif (!Number.isFinite(code) || code !== 200) {\n\t\tconst renderedCode = data.error_code === undefined ? \"unknown\" : String(data.error_code);\n\t\tconst message = typeof data.error_msg === \"string\" && data.error_msg.trim() ? `: ${data.error_msg.trim()}` : \"\";\n\t\tthrow new Error(`Querit ${label} API returned error ${renderedCode}${message}`);\n\t}\n}\n\nfunction mapSearchResults(data: QueritSearchResponse): SearchResponse[\"results\"] {\n\tconst items = data.results?.result;\n\tif (!Array.isArray(items)) {\n\t\tthrow new Error(\"Querit Search API returned an unexpected response shape\");\n\t}\n\treturn items.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\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 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\nfunction mapContentResult(result: QueritContentResult | undefined, requestedUrl: string): ExtractedContent | null {\n\tif (!result || typeof result.content !== \"string\" || result.content.trim().length === 0) return null;\n\tconst metadata = result.extrasMeta;\n\treturn {\n\t\turl: requestedUrl,\n\t\ttitle: metadata && typeof metadata.title === \"string\" ? metadata.title.trim() : \"\",\n\t\tcontent: result.content.trim(),\n\t\terror: null,\n\t};\n}\n\nfunction findContentResult(\n\tdata: QueritContentsResponse,\n\trequestedUrl: string,\n\tindex: number,\n\trequestedCount: number,\n): QueritContentResult | undefined {\n\tif (!Array.isArray(data.results)) return undefined;\n\tconst exact = data.results.find((item) => item?.url === requestedUrl || item?.extrasMeta?.url === requestedUrl);\n\tif (exact) return exact;\n\tif (requestedCount === 1) return data.results[0];\n\treturn data.results.length === requestedCount ? data.results[index] : undefined;\n}\n\nfunction failedContentStatus(data: QueritContentsResponse, result: QueritContentResult | undefined, index: number): boolean {\n\tif (!Array.isArray(data.statuses)) return false;\n\tconst status = result?.id\n\t\t? data.statuses.find((item) => item?.id === result.id)\n\t\t: data.statuses[index];\n\treturn status?.status === \"failed\";\n}\n\nasync function fetchContentsBatch(\n\turls: string[],\n\tapiKey: string,\n\tsignal?: AbortSignal,\n\toptions: ExtractOptions = {},\n): Promise<QueritContentsResponse> {\n\tconst data = await queritJsonRequest<QueritContentsResponse>(\n\t\t\"Contents\",\n\t\tQUERIT_CONTENTS_URL,\n\t\tapiKey,\n\t\tbuildContentsBody(urls, options),\n\t\tnormalizeTimeoutMs(options.timeoutMs),\n\t\tsignal,\n\t);\n\tassertApiSuccess(\"Contents\", data);\n\tif (!Array.isArray(data.results) || !Array.isArray(data.statuses)) {\n\t\tthrow new Error(\"Querit Contents API returned an unexpected response shape\");\n\t}\n\treturn data;\n}\n\nasync function fetchInlineContent(urls: string[], apiKey: string, signal?: AbortSignal): Promise<ExtractedContent[]> {\n\tconst content: ExtractedContent[] = [];\n\tfor (let offset = 0; offset < urls.length; offset += MAX_CONTENT_URLS) {\n\t\tconst batch = urls.slice(offset, offset + MAX_CONTENT_URLS);\n\t\tconst data = await fetchContentsBatch(batch, apiKey, signal);\n\t\tfor (let index = 0; index < batch.length; index++) {\n\t\t\tconst requestedUrl = batch[index];\n\t\t\tconst result = findContentResult(data, requestedUrl, index, batch.length);\n\t\t\tconst mapped = mapContentResult(result, requestedUrl);\n\t\t\tif (mapped) content.push(mapped);\n\t\t}\n\t}\n\treturn content;\n}\n\nexport async function searchWithQuerit(\n\tquery: string,\n\toptions: QueritSearchOptions = {},\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 queritJsonRequest<QueritSearchResponse>(\n\t\t\t\"Search\",\n\t\t\tQUERIT_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\tassertApiSuccess(\"Search\", data);\n\t\tconst results = mapSearchResults(data);\n\t\tconst response: SearchResponse = { answer: buildAnswer(results), results };\n\t\tif (options.includeContent && results.length > 0) {\n\t\t\tconst inlineContent = await fetchInlineContent(results.map((result) => result.url), apiKey, options.signal);\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 (options.signal?.aborted) 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 extractWithQuerit(\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 fetchContentsBatch([url], apiKey, signal, options);\n\t\tconst result = findContentResult(data, url, 0, 1);\n\t\tconst mapped = mapContentResult(result, url);\n\t\tif (mapped) {\n\t\t\tactivityMonitor.logComplete(activityId, 200);\n\t\t\treturn mapped;\n\t\t}\n\t\tif (failedContentStatus(data, result, 0)) {\n\t\t\tthrow new Error(`Querit Contents API failed to crawl ${url}`);\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn null;\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (signal?.aborted) 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"]}
|
|
1
|
+
{"version":3,"file":"querit.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/querit.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA0DrE,UAAU,mBAAoB,SAAQ,aAAa;IAClD,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AA4CD,wBAAgB,iBAAiB,IAAI,OAAO,CAM3C;AA4OD,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAAC,cAAc,CAAC,CA+BzB;AAED,wBAAsB,iBAAiB,CACtC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA0BlC"}
|