@humain/terminal 0.0.2 → 0.0.3-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +241 -24
- package/README.md +143 -119
- package/dist/cli/args.d.ts +4 -2
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +37 -39
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth-check.d.ts +19 -0
- package/dist/cli/auth-check.d.ts.map +1 -0
- package/dist/cli/auth-check.js +50 -0
- package/dist/cli/auth-check.js.map +1 -0
- package/dist/cli/auth-command.d.ts +24 -0
- package/dist/cli/auth-command.d.ts.map +1 -0
- package/dist/cli/auth-command.js +103 -0
- package/dist/cli/auth-command.js.map +1 -0
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +2 -2
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/credential-print.d.ts +5 -15
- package/dist/cli/credential-print.d.ts.map +1 -1
- package/dist/cli/credential-print.js +42 -83
- package/dist/cli/credential-print.js.map +1 -1
- package/dist/cli/experimental/auth.d.ts +16 -0
- package/dist/cli/experimental/auth.d.ts.map +1 -0
- package/dist/cli/experimental/auth.js +13 -0
- package/dist/cli/experimental/auth.js.map +1 -0
- package/dist/cli/experimental/cli.d.ts +6 -0
- package/dist/cli/experimental/cli.d.ts.map +1 -0
- package/dist/cli/experimental/cli.js +5 -0
- package/dist/cli/experimental/cli.js.map +1 -0
- package/dist/cli/experimental/command-options.d.ts +17 -0
- package/dist/cli/experimental/command-options.d.ts.map +1 -0
- package/dist/cli/experimental/command-options.js +35 -0
- package/dist/cli/experimental/command-options.js.map +1 -0
- package/dist/cli/experimental/command.d.ts +63 -0
- package/dist/cli/experimental/command.d.ts.map +1 -0
- package/dist/cli/experimental/command.js +130 -0
- package/dist/cli/experimental/command.js.map +1 -0
- package/dist/cli/experimental/commands/client.d.ts +13 -0
- package/dist/cli/experimental/commands/client.d.ts.map +1 -0
- package/dist/cli/experimental/commands/client.js +25 -0
- package/dist/cli/experimental/commands/client.js.map +1 -0
- package/dist/cli/experimental/commands/pi.d.ts +15 -0
- package/dist/cli/experimental/commands/pi.d.ts.map +1 -0
- package/dist/cli/experimental/commands/pi.js +28 -0
- package/dist/cli/experimental/commands/pi.js.map +1 -0
- package/dist/cli/experimental/commands/server.d.ts +13 -0
- package/dist/cli/experimental/commands/server.d.ts.map +1 -0
- package/dist/cli/experimental/commands/server.js +25 -0
- package/dist/cli/experimental/commands/server.js.map +1 -0
- package/dist/cli/experimental/transport-address.d.ts +10 -0
- package/dist/cli/experimental/transport-address.d.ts.map +1 -0
- package/dist/cli/experimental/transport-address.js +38 -0
- package/dist/cli/experimental/transport-address.js.map +1 -0
- package/dist/cli/list-models.d.ts +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js +2 -2
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/startup-ui.d.ts +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +2 -2
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +3 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/remote-session.d.ts +53 -0
- package/dist/client/remote-session.d.ts.map +1 -0
- package/dist/client/remote-session.js +340 -0
- package/dist/client/remote-session.js.map +1 -0
- package/dist/client/transcript.d.ts +12 -0
- package/dist/client/transcript.d.ts.map +1 -0
- package/dist/client/transcript.js +98 -0
- package/dist/client/transcript.js.map +1 -0
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -10
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +72 -70
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +25 -9
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +237 -39
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +60 -41
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +2 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +3 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +27 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +5 -0
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/keybindings.d.ts +45 -5
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-config.d.ts +29 -5
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +4 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -3
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +13 -10
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +4 -3
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +42 -10
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +30 -13
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +233 -73
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/models-store.d.ts +12 -7
- package/dist/core/models-store.d.ts.map +1 -1
- package/dist/core/models-store.js +83 -14
- package/dist/core/models-store.js.map +1 -1
- package/dist/core/package-manager.d.ts +6 -3
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +80 -61
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/pi-manifest.d.ts +8 -0
- package/dist/core/pi-manifest.d.ts.map +1 -0
- package/dist/core/pi-manifest.js +28 -0
- package/dist/core/pi-manifest.js.map +1 -0
- package/dist/core/provider-composer.d.ts +4 -1
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +36 -15
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +73 -67
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +2 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/runtime-credentials.d.ts +5 -5
- package/dist/core/runtime-credentials.d.ts.map +1 -1
- package/dist/core/runtime-credentials.js +11 -8
- package/dist/core/runtime-credentials.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +2 -2
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +3 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +12 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +40 -16
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +8 -0
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +5 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +16 -15
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts +4 -0
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +11 -7
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts +7 -0
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +16 -19
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +4 -0
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +5 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts +4 -0
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +5 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts +4 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +7 -3
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts +4 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +6 -2
- package/dist/core/tools/write.js.map +1 -1
- package/dist/extensions/llama/index.d.ts.map +1 -1
- package/dist/extensions/llama/index.js +11 -2
- package/dist/extensions/llama/index.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +21 -7
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/humain/agent-execution-protocol.d.ts +218 -0
- package/dist/humain/agent-execution-protocol.d.ts.map +1 -0
- package/dist/humain/agent-execution-protocol.js +204 -0
- package/dist/humain/agent-execution-protocol.js.map +1 -0
- package/dist/humain/agent-execution-runtime.d.ts +35 -0
- package/dist/humain/agent-execution-runtime.d.ts.map +1 -0
- package/dist/humain/agent-execution-runtime.js +170 -0
- package/dist/humain/agent-execution-runtime.js.map +1 -0
- package/dist/humain/index.d.ts.map +1 -1
- package/dist/humain/index.js +8 -7
- package/dist/humain/index.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/CHANGELOG.md +660 -0
- package/dist/humain/mcp-adapter/vendor/LICENSE +21 -0
- package/dist/humain/mcp-adapter/vendor/README.md +733 -0
- package/dist/humain/mcp-adapter/vendor/abort.ts +34 -0
- package/dist/humain/mcp-adapter/vendor/agent-dir.ts +60 -0
- package/dist/humain/mcp-adapter/vendor/agent-plugin-loader.ts +377 -0
- package/dist/humain/mcp-adapter/vendor/app-bridge.bundle.js +67 -0
- package/dist/humain/mcp-adapter/vendor/banner.png +0 -0
- package/dist/humain/mcp-adapter/vendor/cli.js +209 -0
- package/dist/humain/mcp-adapter/vendor/commands.ts +627 -0
- package/dist/humain/mcp-adapter/vendor/config.ts +1226 -0
- package/dist/humain/mcp-adapter/vendor/consent-manager.ts +64 -0
- package/dist/humain/mcp-adapter/vendor/direct-tools.ts +604 -0
- package/dist/humain/mcp-adapter/vendor/elicitation-handler.ts +348 -0
- package/dist/humain/mcp-adapter/vendor/error-signal.ts +21 -0
- package/dist/humain/mcp-adapter/vendor/errors.ts +223 -0
- package/dist/humain/mcp-adapter/vendor/glimpse-ui.ts +80 -0
- package/dist/humain/mcp-adapter/vendor/host-html-template.ts +461 -0
- package/dist/humain/mcp-adapter/vendor/index.bundle.d.mts +4 -0
- package/dist/humain/mcp-adapter/vendor/index.bundle.mjs +15923 -0
- package/dist/humain/mcp-adapter/vendor/index.ts +898 -0
- package/dist/humain/mcp-adapter/vendor/init.ts +649 -0
- package/dist/humain/mcp-adapter/vendor/json-schema-validator.ts +69 -0
- package/dist/humain/mcp-adapter/vendor/lifecycle.ts +147 -0
- package/dist/humain/mcp-adapter/vendor/logger.ts +169 -0
- package/dist/humain/mcp-adapter/vendor/mcp-auth-flow.ts +993 -0
- package/dist/humain/mcp-adapter/vendor/mcp-auth.ts +1000 -0
- package/dist/humain/mcp-adapter/vendor/mcp-callback-server.ts +510 -0
- package/dist/humain/mcp-adapter/vendor/mcp-code.ts +354 -0
- package/dist/humain/mcp-adapter/vendor/mcp-keyring-helper.cjs +89 -0
- package/dist/humain/mcp-adapter/vendor/mcp-oauth-provider.ts +616 -0
- package/dist/humain/mcp-adapter/vendor/mcp-output-guard.ts +408 -0
- package/dist/humain/mcp-adapter/vendor/mcp-panel.ts +1015 -0
- package/dist/humain/mcp-adapter/vendor/mcp-probe.ts +187 -0
- package/dist/humain/mcp-adapter/vendor/mcp-script-worker.mjs +130 -0
- package/dist/humain/mcp-adapter/vendor/mcp-setup-panel.ts +666 -0
- package/dist/humain/mcp-adapter/vendor/mcp-status.ts +109 -0
- package/dist/humain/mcp-adapter/vendor/mcp-trace.ts +306 -0
- package/dist/humain/mcp-adapter/vendor/metadata-cache.ts +353 -0
- package/dist/humain/mcp-adapter/vendor/npx-resolver.ts +543 -0
- package/dist/humain/mcp-adapter/vendor/oauth-handler.ts +30 -0
- package/dist/humain/mcp-adapter/vendor/oauth.ts +48 -0
- package/dist/humain/mcp-adapter/vendor/onboarding-state.ts +76 -0
- package/dist/humain/mcp-adapter/vendor/package.json +178 -0
- package/dist/humain/mcp-adapter/vendor/panel-keys.ts +53 -0
- package/dist/humain/mcp-adapter/vendor/prompts.ts +353 -0
- package/dist/humain/mcp-adapter/vendor/proxy-modes.ts +1331 -0
- package/dist/humain/mcp-adapter/vendor/resource-tools.ts +17 -0
- package/dist/humain/mcp-adapter/vendor/runtime-owner.ts +91 -0
- package/dist/humain/mcp-adapter/vendor/sampling-handler.ts +284 -0
- package/dist/humain/mcp-adapter/vendor/search-ranking.ts +206 -0
- package/dist/humain/mcp-adapter/vendor/server-manager.ts +1124 -0
- package/dist/humain/mcp-adapter/vendor/session-recovery.ts +151 -0
- package/dist/humain/mcp-adapter/vendor/skills/mcp-scripting/SKILL.md +38 -0
- package/dist/humain/mcp-adapter/vendor/state.ts +62 -0
- package/dist/humain/mcp-adapter/vendor/tool-approval.ts +182 -0
- package/dist/humain/mcp-adapter/vendor/tool-metadata.ts +276 -0
- package/dist/humain/mcp-adapter/vendor/tool-registrar.ts +253 -0
- package/dist/humain/mcp-adapter/vendor/tool-result-renderer.ts +423 -0
- package/dist/humain/mcp-adapter/vendor/ts-shape.ts +149 -0
- package/dist/humain/mcp-adapter/vendor/types.ts +859 -0
- package/dist/humain/mcp-adapter/vendor/ui-app-bridge-helpers.ts +40 -0
- package/dist/humain/mcp-adapter/vendor/ui-resource-handler.ts +250 -0
- package/dist/humain/mcp-adapter/vendor/ui-server.ts +866 -0
- package/dist/humain/mcp-adapter/vendor/ui-session.ts +570 -0
- package/dist/humain/mcp-adapter/vendor/ui-stream-types.ts +89 -0
- package/dist/humain/mcp-adapter/vendor/ui-tool-visibility.ts +25 -0
- package/dist/humain/mcp-adapter/vendor/unix-socket-transport.ts +85 -0
- package/dist/humain/mcp-adapter/vendor/utils.ts +310 -0
- package/dist/humain/mcp-adapter.d.ts +3 -0
- package/dist/humain/mcp-adapter.d.ts.map +1 -0
- package/dist/humain/mcp-adapter.js +5 -0
- package/dist/humain/mcp-adapter.js.map +1 -0
- package/dist/humain/pi-agent-execution-host.d.ts +34 -0
- package/dist/humain/pi-agent-execution-host.d.ts.map +1 -0
- package/dist/humain/pi-agent-execution-host.js +77 -0
- package/dist/humain/pi-agent-execution-host.js.map +1 -0
- package/dist/humain/web-access/host.d.ts +4 -0
- package/dist/humain/web-access/host.d.ts.map +1 -0
- package/dist/humain/web-access/host.js +3 -0
- package/dist/humain/web-access/host.js.map +1 -0
- package/dist/humain/web-access/index.d.ts +3 -0
- package/dist/humain/web-access/index.d.ts.map +1 -0
- package/dist/humain/web-access/index.js +5 -0
- package/dist/humain/web-access/index.js.map +1 -0
- package/dist/humain/web-access/vendor/activity.d.ts +34 -0
- package/dist/humain/web-access/vendor/activity.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/activity.js +68 -0
- package/dist/humain/web-access/vendor/activity.js.map +1 -0
- package/dist/humain/web-access/vendor/anysearch.d.ts +8 -0
- package/dist/humain/web-access/vendor/anysearch.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/anysearch.js +167 -0
- package/dist/humain/web-access/vendor/anysearch.js.map +1 -0
- package/dist/humain/web-access/vendor/bocha.d.ts +4 -0
- package/dist/humain/web-access/vendor/bocha.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/bocha.js +219 -0
- package/dist/humain/web-access/vendor/bocha.js.map +1 -0
- package/dist/humain/web-access/vendor/brave.d.ts +4 -0
- package/dist/humain/web-access/vendor/brave.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/brave.js +194 -0
- package/dist/humain/web-access/vendor/brave.js.map +1 -0
- package/dist/humain/web-access/vendor/brightdata-unlocker.d.ts +12 -0
- package/dist/humain/web-access/vendor/brightdata-unlocker.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/brightdata-unlocker.js +230 -0
- package/dist/humain/web-access/vendor/brightdata-unlocker.js.map +1 -0
- package/dist/humain/web-access/vendor/brightdata.d.ts +8 -0
- package/dist/humain/web-access/vendor/brightdata.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/brightdata.js +519 -0
- package/dist/humain/web-access/vendor/brightdata.js.map +1 -0
- package/dist/humain/web-access/vendor/chrome-cookies.d.ts +10 -0
- package/dist/humain/web-access/vendor/chrome-cookies.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/chrome-cookies.js +438 -0
- package/dist/humain/web-access/vendor/chrome-cookies.js.map +1 -0
- package/dist/humain/web-access/vendor/content-find.d.ts +11 -0
- package/dist/humain/web-access/vendor/content-find.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/content-find.js +117 -0
- package/dist/humain/web-access/vendor/content-find.js.map +1 -0
- package/dist/humain/web-access/vendor/credential-source.d.ts +28 -0
- package/dist/humain/web-access/vendor/credential-source.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/credential-source.js +151 -0
- package/dist/humain/web-access/vendor/credential-source.js.map +1 -0
- package/dist/humain/web-access/vendor/curator-page.d.ts +29 -0
- package/dist/humain/web-access/vendor/curator-page.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/curator-page.js +3554 -0
- package/dist/humain/web-access/vendor/curator-page.js.map +1 -0
- package/dist/humain/web-access/vendor/curator-server.d.ts +93 -0
- package/dist/humain/web-access/vendor/curator-server.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/curator-server.js +688 -0
- package/dist/humain/web-access/vendor/curator-server.js.map +1 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.d.ts +60 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.js +416 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/declared-web-links.d.ts +16 -0
- package/dist/humain/web-access/vendor/declared-web-links.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/declared-web-links.js +168 -0
- package/dist/humain/web-access/vendor/declared-web-links.js.map +1 -0
- package/dist/humain/web-access/vendor/duckduckgo.d.ts +4 -0
- package/dist/humain/web-access/vendor/duckduckgo.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/duckduckgo.js +123 -0
- package/dist/humain/web-access/vendor/duckduckgo.js.map +1 -0
- package/dist/humain/web-access/vendor/exa.d.ts +10 -0
- package/dist/humain/web-access/vendor/exa.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/exa.js +426 -0
- package/dist/humain/web-access/vendor/exa.js.map +1 -0
- package/dist/humain/web-access/vendor/extract.d.ts +46 -0
- package/dist/humain/web-access/vendor/extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/extract.js +1064 -0
- package/dist/humain/web-access/vendor/extract.js.map +1 -0
- package/dist/humain/web-access/vendor/feature-config.d.ts +3 -0
- package/dist/humain/web-access/vendor/feature-config.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/feature-config.js +27 -0
- package/dist/humain/web-access/vendor/feature-config.js.map +1 -0
- package/dist/humain/web-access/vendor/fetch-params.d.ts +25 -0
- package/dist/humain/web-access/vendor/fetch-params.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/fetch-params.js +57 -0
- package/dist/humain/web-access/vendor/fetch-params.js.map +1 -0
- package/dist/humain/web-access/vendor/firecrawl.d.ts +12 -0
- package/dist/humain/web-access/vendor/firecrawl.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/firecrawl.js +239 -0
- package/dist/humain/web-access/vendor/firecrawl.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-api.d.ts +27 -0
- package/dist/humain/web-access/vendor/gemini-api.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-api.js +230 -0
- package/dist/humain/web-access/vendor/gemini-api.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-pdf-extract.d.ts +9 -0
- package/dist/humain/web-access/vendor/gemini-pdf-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-pdf-extract.js +85 -0
- package/dist/humain/web-access/vendor/gemini-pdf-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-search.d.ts +40 -0
- package/dist/humain/web-access/vendor/gemini-search.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-search.js +814 -0
- package/dist/humain/web-access/vendor/gemini-search.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-url-context.d.ts +4 -0
- package/dist/humain/web-access/vendor/gemini-url-context.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-url-context.js +101 -0
- package/dist/humain/web-access/vendor/gemini-url-context.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-web-config.d.ts +4 -0
- package/dist/humain/web-access/vendor/gemini-web-config.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-web-config.js +42 -0
- package/dist/humain/web-access/vendor/gemini-web-config.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-web.d.ts +18 -0
- package/dist/humain/web-access/vendor/gemini-web.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-web.js +385 -0
- package/dist/humain/web-access/vendor/gemini-web.js.map +1 -0
- package/dist/humain/web-access/vendor/github-api.d.ts +7 -0
- package/dist/humain/web-access/vendor/github-api.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/github-api.js +160 -0
- package/dist/humain/web-access/vendor/github-api.js.map +1 -0
- package/dist/humain/web-access/vendor/github-extract.d.ts +13 -0
- package/dist/humain/web-access/vendor/github-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/github-extract.js +635 -0
- package/dist/humain/web-access/vendor/github-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/index.d.ts +4 -0
- package/dist/humain/web-access/vendor/index.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/index.js +3002 -0
- package/dist/humain/web-access/vendor/index.js.map +1 -0
- package/dist/humain/web-access/vendor/jina-search.d.ts +8 -0
- package/dist/humain/web-access/vendor/jina-search.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/jina-search.js +255 -0
- package/dist/humain/web-access/vendor/jina-search.js.map +1 -0
- package/dist/humain/web-access/vendor/kagi.d.ts +15 -0
- package/dist/humain/web-access/vendor/kagi.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/kagi.js +262 -0
- package/dist/humain/web-access/vendor/kagi.js.map +1 -0
- package/dist/humain/web-access/vendor/ollama.d.ts +15 -0
- package/dist/humain/web-access/vendor/ollama.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/ollama.js +216 -0
- package/dist/humain/web-access/vendor/ollama.js.map +1 -0
- package/dist/humain/web-access/vendor/openai-search.d.ts +15 -0
- package/dist/humain/web-access/vendor/openai-search.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/openai-search.js +459 -0
- package/dist/humain/web-access/vendor/openai-search.js.map +1 -0
- package/dist/humain/web-access/vendor/page-query.d.ts +16 -0
- package/dist/humain/web-access/vendor/page-query.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/page-query.js +79 -0
- package/dist/humain/web-access/vendor/page-query.js.map +1 -0
- package/dist/humain/web-access/vendor/parallel.d.ts +12 -0
- package/dist/humain/web-access/vendor/parallel.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/parallel.js +343 -0
- package/dist/humain/web-access/vendor/parallel.js.map +1 -0
- package/dist/humain/web-access/vendor/pdf-extract.d.ts +44 -0
- package/dist/humain/web-access/vendor/pdf-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/pdf-extract.js +298 -0
- package/dist/humain/web-access/vendor/pdf-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/perplexity.d.ts +20 -0
- package/dist/humain/web-access/vendor/perplexity.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/perplexity.js +159 -0
- package/dist/humain/web-access/vendor/perplexity.js.map +1 -0
- package/dist/humain/web-access/vendor/querit.d.ts +10 -0
- package/dist/humain/web-access/vendor/querit.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/querit.js +335 -0
- package/dist/humain/web-access/vendor/querit.js.map +1 -0
- package/dist/humain/web-access/vendor/render-search-error.d.ts +57 -0
- package/dist/humain/web-access/vendor/render-search-error.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/render-search-error.js +130 -0
- package/dist/humain/web-access/vendor/render-search-error.js.map +1 -0
- package/dist/humain/web-access/vendor/rsc-extract.d.ts +12 -0
- package/dist/humain/web-access/vendor/rsc-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/rsc-extract.js +329 -0
- package/dist/humain/web-access/vendor/rsc-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/search1api.d.ts +10 -0
- package/dist/humain/web-access/vendor/search1api.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/search1api.js +251 -0
- package/dist/humain/web-access/vendor/search1api.js.map +1 -0
- package/dist/humain/web-access/vendor/searchinfinity.d.ts +8 -0
- package/dist/humain/web-access/vendor/searchinfinity.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/searchinfinity.js +229 -0
- package/dist/humain/web-access/vendor/searchinfinity.js.map +1 -0
- package/dist/humain/web-access/vendor/searxng.d.ts +4 -0
- package/dist/humain/web-access/vendor/searxng.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/searxng.js +238 -0
- package/dist/humain/web-access/vendor/searxng.js.map +1 -0
- package/dist/humain/web-access/vendor/serpbase.d.ts +4 -0
- package/dist/humain/web-access/vendor/serpbase.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/serpbase.js +211 -0
- package/dist/humain/web-access/vendor/serpbase.js.map +1 -0
- package/dist/humain/web-access/vendor/serpdive.d.ts +8 -0
- package/dist/humain/web-access/vendor/serpdive.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/serpdive.js +267 -0
- package/dist/humain/web-access/vendor/serpdive.js.map +1 -0
- package/dist/humain/web-access/vendor/source-check.d.ts +99 -0
- package/dist/humain/web-access/vendor/source-check.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/source-check.js +205 -0
- package/dist/humain/web-access/vendor/source-check.js.map +1 -0
- package/dist/humain/web-access/vendor/ssrf-protection.d.ts +50 -0
- package/dist/humain/web-access/vendor/ssrf-protection.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/ssrf-protection.js +466 -0
- package/dist/humain/web-access/vendor/ssrf-protection.js.map +1 -0
- package/dist/humain/web-access/vendor/storage.d.ts +55 -0
- package/dist/humain/web-access/vendor/storage.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/storage.js +485 -0
- package/dist/humain/web-access/vendor/storage.js.map +1 -0
- package/dist/humain/web-access/vendor/summary-model-scope.d.ts +25 -0
- package/dist/humain/web-access/vendor/summary-model-scope.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/summary-model-scope.js +98 -0
- package/dist/humain/web-access/vendor/summary-model-scope.js.map +1 -0
- package/dist/humain/web-access/vendor/summary-review.d.ts +24 -0
- package/dist/humain/web-access/vendor/summary-review.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/summary-review.js +341 -0
- package/dist/humain/web-access/vendor/summary-review.js.map +1 -0
- package/dist/humain/web-access/vendor/tavily.d.ts +8 -0
- package/dist/humain/web-access/vendor/tavily.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/tavily.js +194 -0
- package/dist/humain/web-access/vendor/tavily.js.map +1 -0
- package/dist/humain/web-access/vendor/tinyfish.d.ts +11 -0
- package/dist/humain/web-access/vendor/tinyfish.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/tinyfish.js +331 -0
- package/dist/humain/web-access/vendor/tinyfish.js.map +1 -0
- package/dist/humain/web-access/vendor/utils.d.ts +20 -0
- package/dist/humain/web-access/vendor/utils.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/utils.js +91 -0
- package/dist/humain/web-access/vendor/utils.js.map +1 -0
- package/dist/humain/web-access/vendor/video-extract.d.ts +16 -0
- package/dist/humain/web-access/vendor/video-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/video-extract.js +335 -0
- package/dist/humain/web-access/vendor/video-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/xai-search.d.ts +13 -0
- package/dist/humain/web-access/vendor/xai-search.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/xai-search.js +331 -0
- package/dist/humain/web-access/vendor/xai-search.js.map +1 -0
- package/dist/humain/web-access/vendor/youtube-extract.d.ts +27 -0
- package/dist/humain/web-access/vendor/youtube-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/youtube-extract.js +282 -0
- package/dist/humain/web-access/vendor/youtube-extract.js.map +1 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +2 -2
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +169 -102
- package/dist/main.js.map +1 -1
- package/dist/modes/agent-exec-mode.d.ts +14 -0
- package/dist/modes/agent-exec-mode.d.ts.map +1 -0
- package/dist/modes/agent-exec-mode.js +92 -0
- package/dist/modes/agent-exec-mode.js.map +1 -0
- package/dist/modes/index.d.ts +4 -2
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +2 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +5 -2
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +13 -4
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +7 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -0
- package/dist/modes/interactive/components/earendil-announcement.js +40 -0
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/markdown-transform.d.ts +3 -0
- package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -0
- package/dist/modes/interactive/components/markdown-transform.js +19 -0
- package/dist/modes/interactive/components/markdown-transform.js.map +1 -0
- package/dist/modes/interactive/components/mermaid.d.ts +11 -0
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
- package/dist/modes/interactive/components/mermaid.js +75 -0
- package/dist/modes/interactive/components/mermaid.js.map +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +16 -4
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +4 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +26 -0
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +8 -2
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +30 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +3 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +9 -2
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +45 -9
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +581 -211
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +1 -0
- package/dist/modes/interactive/theme/light.json +1 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +3 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +10 -1
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +5 -1
- package/dist/modes/interactive/theme/theme.d.ts +2 -2
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +24 -6
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +28 -0
- package/dist/modes/json-event.d.ts.map +1 -0
- package/dist/modes/json-event.js +12 -0
- package/dist/modes/json-event.js.map +1 -0
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +12 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +12 -5
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +55 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +13 -3
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +15 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +11 -9
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/rpc-entry.d.ts.map +1 -1
- package/dist/rpc-entry.js +3 -2
- package/dist/rpc-entry.js.map +1 -1
- package/dist/server/create-harness.d.ts +26 -0
- package/dist/server/create-harness.d.ts.map +1 -0
- package/dist/server/create-harness.js +104 -0
- package/dist/server/create-harness.js.map +1 -0
- package/dist/utils/abort.d.ts +5 -0
- package/dist/utils/abort.d.ts.map +1 -0
- package/dist/utils/abort.js +48 -0
- package/dist/utils/abort.js.map +1 -0
- package/dist/utils/clipboard.d.ts +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +22 -2
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/management-http.d.ts +23 -0
- package/dist/utils/management-http.d.ts.map +1 -0
- package/dist/utils/management-http.js +50 -0
- package/dist/utils/management-http.js.map +1 -0
- package/dist/utils/paths.d.ts +3 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +23 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/tool-result-images.d.ts +19 -0
- package/dist/utils/tool-result-images.d.ts.map +1 -0
- package/dist/utils/tool-result-images.js +45 -0
- package/dist/utils/tool-result-images.js.map +1 -0
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +13 -25
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts +4 -0
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +23 -5
- package/dist/utils/version-check.js.map +1 -1
- package/docs/compaction.md +2 -2
- package/docs/custom-provider.md +7 -5
- package/docs/extensions.md +30 -5
- package/docs/humain-terminal.md +21 -1
- package/docs/json.md +24 -19
- package/docs/keybindings.md +46 -14
- package/docs/models.md +32 -11
- package/docs/providers.md +9 -1
- package/docs/quickstart.md +39 -37
- package/docs/rpc.md +31 -11
- package/docs/sdk.md +21 -2
- package/docs/security.md +21 -21
- package/docs/session-format.md +14 -14
- package/docs/settings.md +4 -1
- package/docs/themes.md +5 -3
- package/docs/usage.md +7 -0
- package/examples/extensions/custom-compaction.ts +3 -18
- package/examples/extensions/custom-provider-anthropic/index.ts +5 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +5 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/doom-overlay/wad-finder.ts +7 -3
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/handoff.ts +4 -13
- package/examples/extensions/qna.ts +5 -9
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/summarize.ts +9 -20
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/rpc-extension-ui.ts +11 -2
- package/examples/sdk/02-custom-model.ts +2 -3
- package/examples/sdk/09-api-keys-and-oauth.ts +1 -1
- package/examples/sdk/12-full-control.ts +1 -1
- package/examples/sdk/README.md +1 -1
- package/npm-shrinkwrap.json +2771 -535
- package/package.json +40 -11
- package/src/humain/mcp-adapter/UPSTREAM.md +15 -0
- package/src/humain/mcp-adapter/upstream.json +7 -0
- package/src/humain/mcp-adapter/vendor/CHANGELOG.md +660 -0
- package/src/humain/mcp-adapter/vendor/LICENSE +21 -0
- package/src/humain/web-access/UPSTREAM.md +17 -0
- package/src/humain/web-access/upstream.json +23 -0
- package/src/humain/web-access/vendor/LICENSE +21 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tinyfish.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/tinyfish.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 TINYFISH_SEARCH_URL = \"https://api.search.tinyfish.ai\";\nconst TINYFISH_FETCH_URL = \"https://api.fetch.tinyfish.ai\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\nconst FETCH_TIMEOUT_MS = 150_000;\nconst MAX_FETCH_URLS = 10;\nconst MAX_FETCH_PER_URL_TIMEOUT_MS = 110_000;\n\ninterface WebSearchConfig {\n\ttinyfishApiKey?: unknown;\n}\n\ninterface TinyFishSearchResult {\n\tposition?: number;\n\tsite_name?: string | null;\n\ttitle?: string | null;\n\tsnippet?: string | null;\n\turl?: string | null;\n\tdate?: string | null;\n\tpublisher?: string | null;\n}\n\ninterface TinyFishSearchResponse {\n\tquery?: string;\n\tresults?: TinyFishSearchResult[];\n\ttotal_results?: number;\n\tpage?: number;\n}\n\ninterface TinyFishFetchResult {\n\turl?: string;\n\tfinal_url?: string;\n\ttitle?: string | null;\n\ttext?: string | Record<string, unknown> | null;\n\tformat?: string;\n}\n\ninterface TinyFishFetchError {\n\turl?: string;\n\terror?: string;\n\tstatus?: number;\n}\n\ninterface TinyFishFetchResponse {\n\tresults?: TinyFishFetchResult[];\n\terrors?: TinyFishFetchError[];\n}\n\ninterface TinyFishSearchOptions 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 clearTinyFishConfigCache(): void {\n\tcachedConfig = null;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveCredential({\n\t\tprovider: \"TinyFish\",\n\t\tconfiguredValue: loadConfig().tinyfishApiKey,\n\t\tenvironmentValue: process.env.TINYFISH_API_KEY,\n\t\tsignal,\n\t});\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"TinyFish API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"tinyfishApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set TINYFISH_API_KEY environment variable\\n\" +\n\t\t\t\"Get a key at https://agent.tinyfish.ai/api-keys\",\n\t\t);\n\t}\n\treturn key;\n}\n\nexport function isTinyFishAvailable(): boolean {\n\treturn hasCredentialSource({\n\t\tprovider: \"TinyFish\",\n\t\tconfiguredValue: loadConfig().tinyfishApiKey,\n\t\tenvironmentValue: process.env.TINYFISH_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 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): { includeDomains: string[]; excludeDomains: string[] } {\n\tconst includeDomains: string[] = [];\n\tconst excludeDomains: 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(\"-\") ? excludeDomains : includeDomains;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn { includeDomains, excludeDomains };\n}\n\nfunction recencyMinutes(filter: SearchOptions[\"recencyFilter\"]): number | undefined {\n\tif (!filter) return undefined;\n\tconst minutes: Record<NonNullable<SearchOptions[\"recencyFilter\"]>, number> = {\n\t\tday: 1_440,\n\t\tweek: 10_080,\n\t\tmonth: 43_200,\n\t\tyear: 525_600,\n\t};\n\treturn minutes[filter];\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 buildSearchUrl(query: string, options: SearchOptions, page: number): string {\n\tconst params = new URLSearchParams({ query });\n\tconst { includeDomains, excludeDomains } = mapDomainFilter(options.domainFilter);\n\tif (includeDomains.length > 0) params.set(\"include_domains\", includeDomains.join(\",\"));\n\tif (excludeDomains.length > 0) params.set(\"exclude_domains\", excludeDomains.join(\",\"));\n\tconst recency = recencyMinutes(options.recencyFilter);\n\tif (recency !== undefined) params.set(\"recency_minutes\", String(recency));\n\tif (page > 0) params.set(\"page\", String(page));\n\treturn `${TINYFISH_SEARCH_URL}?${params.toString()}`;\n}\n\nasync function tinyFishJsonRequest<T>(\n\tlabel: \"Search\" | \"Fetch\",\n\turl: string,\n\tapiKey: string,\n\tinit: RequestInit,\n\ttimeoutMs: number,\n\tsignal?: AbortSignal,\n): Promise<T> {\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(url, {\n\t\t\t...init,\n\t\t\theaders: {\n\t\t\t\t\"X-API-Key\": apiKey,\n\t\t\t\t...(init.body ? { \"Content-Type\": \"application/json\" } : {}),\n\t\t\t\t...init.headers,\n\t\t\t},\n\t\t\tsignal: requestSignal(signal, timeoutMs),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tconst raw = await response.text();\n\tif (!response.ok) {\n\t\tthrow new Error(`TinyFish ${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(`TinyFish ${label} API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n}\n\nfunction mapSearchResults(results: TinyFishSearchResult[] | undefined): SearchResponse[\"results\"] {\n\tif (!Array.isArray(results)) return [];\n\treturn results.flatMap((item) => {\n\t\tif (!item || typeof item.url !== \"string\" || item.url.trim().length === 0) return [];\n\t\tconst url = item.url.trim();\n\t\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 deduplicateResults(results: SearchResponse[\"results\"], limit: number): SearchResponse[\"results\"] {\n\tconst seen = new Set<string>();\n\tconst unique: SearchResponse[\"results\"] = [];\n\tfor (const result of results) {\n\t\tif (seen.has(result.url)) continue;\n\t\tseen.add(result.url);\n\t\tunique.push(result);\n\t\tif (unique.length >= limit) break;\n\t}\n\treturn unique;\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 fetchPerUrlTimeout(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return MAX_FETCH_PER_URL_TIMEOUT_MS;\n\treturn Math.max(1, Math.min(Math.floor(value), MAX_FETCH_PER_URL_TIMEOUT_MS));\n}\n\nfunction fetchBody(urls: string[], options: ExtractOptions = {}): Record<string, unknown> {\n\tconst body: Record<string, unknown> = {\n\t\turls,\n\t\tformat: \"markdown\",\n\t\tper_url_timeout_ms: fetchPerUrlTimeout(options.timeoutMs),\n\t};\n\tconst purpose = options.prompt?.trim();\n\tif (purpose) body.purpose = purpose.slice(0, 2_000);\n\treturn body;\n}\n\nfunction findFetchError(errors: TinyFishFetchError[] | undefined, url: string): TinyFishFetchError | undefined {\n\tif (!Array.isArray(errors)) return undefined;\n\treturn errors.find(item => item?.url === url) ?? errors[0];\n}\n\nfunction fetchResultContent(result: TinyFishFetchResult): string {\n\tif (typeof result.text === \"string\") return result.text.trim();\n\tif (result.text && typeof result.text === \"object\") return JSON.stringify(result.text, null, 2);\n\treturn \"\";\n}\n\nfunction mapFetchResult(result: TinyFishFetchResult | undefined, requestedUrl: string): ExtractedContent | null {\n\tif (!result) return null;\n\tconst content = fetchResultContent(result);\n\tif (!content) return null;\n\treturn {\n\t\turl: requestedUrl,\n\t\ttitle: typeof result.title === \"string\" ? result.title.trim() : \"\",\n\t\tcontent,\n\t\terror: null,\n\t};\n}\n\nasync function fetchBatch(\n\turls: string[],\n\tapiKey: string,\n\tsignal?: AbortSignal,\n\toptions: ExtractOptions = {},\n): Promise<TinyFishFetchResponse> {\n\treturn tinyFishJsonRequest<TinyFishFetchResponse>(\n\t\t\"Fetch\",\n\t\tTINYFISH_FETCH_URL,\n\t\tapiKey,\n\t\t{ method: \"POST\", body: JSON.stringify(fetchBody(urls, options)) },\n\t\tFETCH_TIMEOUT_MS,\n\t\tsignal,\n\t);\n}\n\nasync function fetchInlineContent(\n\turls: string[],\n\tapiKey: string,\n\tsignal?: AbortSignal,\n): Promise<ExtractedContent[]> {\n\tconst content: ExtractedContent[] = [];\n\tfor (let offset = 0; offset < urls.length; offset += MAX_FETCH_URLS) {\n\t\tconst batch = urls.slice(offset, offset + MAX_FETCH_URLS);\n\t\tconst data = await fetchBatch(batch, apiKey, signal);\n\t\tif (!Array.isArray(data.results) || !Array.isArray(data.errors)) {\n\t\t\tthrow new Error(\"TinyFish Fetch API returned an unexpected response shape\");\n\t\t}\n\t\tfor (const url of batch) {\n\t\t\tconst result = Array.isArray(data.results)\n\t\t\t\t? data.results.find(item => item?.url === url || item?.final_url === url)\n\t\t\t\t: undefined;\n\t\t\tconst mapped = mapFetchResult(result, url);\n\t\t\tif (mapped) content.push(mapped);\n\t\t}\n\t}\n\treturn content;\n}\n\nexport async function searchWithTinyFish(query: string, options: TinyFishSearchOptions = {}): Promise<SearchResponse> {\n\tconst apiKey = await getApiKey(options.signal);\n\tconst numResults = normalizeNumResults(options.numResults);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\ttry {\n\t\tconst combined: SearchResponse[\"results\"] = [];\n\t\tconst pages = numResults > 10 ? 2 : 1;\n\t\tfor (let page = 0; page < pages; page++) {\n\t\t\tconst data = await tinyFishJsonRequest<TinyFishSearchResponse>(\n\t\t\t\t\"Search\",\n\t\t\t\tbuildSearchUrl(query, options, page),\n\t\t\t\tapiKey,\n\t\t\t\t{ method: \"GET\" },\n\t\t\t\tSEARCH_TIMEOUT_MS,\n\t\t\t\toptions.signal,\n\t\t\t);\n\t\t\tif (!Array.isArray(data.results)) throw new Error(\"TinyFish Search API returned an unexpected response shape\");\n\t\t\tcombined.push(...mapSearchResults(data.results));\n\t\t\tif (data.results.length < 10) break;\n\t\t}\n\n\t\tconst results = deduplicateResults(combined, numResults);\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 (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n\nexport async function extractWithTinyFish(\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 fetchBatch([url], apiKey, signal, options);\n\t\tif (!Array.isArray(data.results) || !Array.isArray(data.errors)) {\n\t\t\tthrow new Error(\"TinyFish Fetch API returned an unexpected response shape\");\n\t\t}\n\t\tconst result = data.results.find(item => item?.url === url || item?.final_url === url) ?? data.results[0];\n\t\tconst mapped = mapFetchResult(result, url);\n\t\tif (mapped) {\n\t\t\tactivityMonitor.logComplete(activityId, 200);\n\t\t\treturn mapped;\n\t\t}\n\t\tconst fetchError = findFetchError(data.errors, url);\n\t\tif (fetchError) {\n\t\t\tconst status = typeof fetchError.status === \"number\" ? ` (HTTP ${fetchError.status})` : \"\";\n\t\t\tthrow new Error(`TinyFish Fetch failed for ${url}: ${fetchError.error || \"unknown error\"}${status}`);\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 (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare function getWebSearchConfigDir(): string;
|
|
2
|
+
export declare function getWebSearchConfigPath(): string;
|
|
3
|
+
export interface CuratorNetworkConfig {
|
|
4
|
+
/** Whether remote access was opted into via curatorRemote. */
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
host: string;
|
|
7
|
+
bind: string;
|
|
8
|
+
}
|
|
9
|
+
/** Resolves the curator server bind address and URL host from `curatorRemote`. */
|
|
10
|
+
export declare function resolveCuratorNetworkConfig(): CuratorNetworkConfig;
|
|
11
|
+
export declare function formatSeconds(s: number): string;
|
|
12
|
+
export declare function readExecError(err: unknown): {
|
|
13
|
+
code?: string;
|
|
14
|
+
stderr: string;
|
|
15
|
+
message: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function isTimeoutError(err: unknown): boolean;
|
|
18
|
+
export declare function trimErrorText(text: string): string;
|
|
19
|
+
export declare function mapFfmpegError(err: unknown): string;
|
|
20
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/utils.ts"],"names":[],"mappings":"AAKA,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED,MAAM,WAAW,oBAAoB;IACpC,8DAA8D;IAC9D,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAUD,kFAAkF;AAClF,wBAAgB,2BAA2B,IAAI,oBAAoB,CAyBlE;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM/C;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAa9F;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAOpD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAOnD","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { hostname } from \"node:os\";\nimport { join } from \"node:path\";\nimport { getAgentDir } from \"../host.ts\";\n\nexport function getWebSearchConfigDir(): string {\n\treturn getAgentDir();\n}\n\nexport function getWebSearchConfigPath(): string {\n\treturn join(getWebSearchConfigDir(), \"web-search.json\");\n}\n\nexport interface CuratorNetworkConfig {\n\t/** Whether remote access was opted into via curatorRemote. */\n\tenabled: boolean;\n\thost: string;\n\tbind: string;\n}\n\nconst LOCAL_CURATOR_NETWORK_DEFAULTS: CuratorNetworkConfig = { enabled: false, host: \"localhost\", bind: \"127.0.0.1\" };\n\nfunction trimmedString(value: unknown): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst trimmed = value.trim();\n\treturn trimmed.length > 0 ? trimmed : undefined;\n}\n\n/** Resolves the curator server bind address and URL host from `curatorRemote`. */\nexport function resolveCuratorNetworkConfig(): CuratorNetworkConfig {\n\tconst configPath = getWebSearchConfigPath();\n\tif (!existsSync(configPath)) return LOCAL_CURATOR_NETWORK_DEFAULTS;\n\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(readFileSync(configPath, \"utf-8\"));\n\t} catch {\n\t\treturn LOCAL_CURATOR_NETWORK_DEFAULTS;\n\t}\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return LOCAL_CURATOR_NETWORK_DEFAULTS;\n\n\tconst curatorRemote = (raw as Record<string, unknown>).curatorRemote;\n\tif (curatorRemote === true) return { enabled: true, host: hostname(), bind: \"0.0.0.0\" };\n\n\tif (curatorRemote && typeof curatorRemote === \"object\" && !Array.isArray(curatorRemote)) {\n\t\tconst obj = curatorRemote as Record<string, unknown>;\n\t\treturn {\n\t\t\tenabled: true,\n\t\t\thost: trimmedString(obj.host) ?? hostname(),\n\t\t\tbind: trimmedString(obj.bind) ?? \"0.0.0.0\",\n\t\t};\n\t}\n\n\treturn LOCAL_CURATOR_NETWORK_DEFAULTS;\n}\n\nexport function formatSeconds(s: number): string {\n\tconst h = Math.floor(s / 3600);\n\tconst m = Math.floor((s % 3600) / 60);\n\tconst sec = s % 60;\n\tif (h > 0) return `${h}:${String(m).padStart(2, \"0\")}:${String(sec).padStart(2, \"0\")}`;\n\treturn `${m}:${String(sec).padStart(2, \"0\")}`;\n}\n\nexport function readExecError(err: unknown): { code?: string; stderr: string; message: string } {\n\tif (!err || typeof err !== \"object\") {\n\t\treturn { stderr: \"\", message: String(err) };\n\t}\n\tconst code = (err as { code?: string }).code;\n\tconst message = (err as { message?: string }).message ?? \"\";\n\tconst stderrRaw = (err as { stderr?: Buffer | string }).stderr;\n\tconst stderr = Buffer.isBuffer(stderrRaw)\n\t\t? stderrRaw.toString(\"utf-8\")\n\t\t: typeof stderrRaw === \"string\"\n\t\t\t? stderrRaw\n\t\t\t: \"\";\n\treturn { code, stderr, message };\n}\n\nexport function isTimeoutError(err: unknown): boolean {\n\tif (!err || typeof err !== \"object\") return false;\n\tif ((err as { killed?: boolean }).killed) return true;\n\tconst name = (err as { name?: string }).name;\n\tconst code = (err as { code?: string }).code;\n\tconst message = (err as { message?: string }).message ?? \"\";\n\treturn name === \"AbortError\" || code === \"ETIMEDOUT\" || message.toLowerCase().includes(\"timed out\");\n}\n\nexport function trimErrorText(text: string): string {\n\treturn text.replace(/\\s+/g, \" \").trim().slice(0, 200);\n}\n\nexport function mapFfmpegError(err: unknown): string {\n\tconst { code, stderr, message } = readExecError(err);\n\tif (code === \"ENOENT\") return \"ffmpeg is not installed. Install with: brew install ffmpeg\";\n\tif (isTimeoutError(err)) return \"ffmpeg timed out extracting frame\";\n\tif (stderr.includes(\"403\")) return \"Stream URL returned 403 — may have expired, try again\";\n\tconst snippet = trimErrorText(stderr || message);\n\treturn snippet ? `ffmpeg failed: ${snippet}` : \"ffmpeg failed\";\n}\n"]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { hostname } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { getAgentDir } from "../host.js";
|
|
5
|
+
export function getWebSearchConfigDir() {
|
|
6
|
+
return getAgentDir();
|
|
7
|
+
}
|
|
8
|
+
export function getWebSearchConfigPath() {
|
|
9
|
+
return join(getWebSearchConfigDir(), "web-search.json");
|
|
10
|
+
}
|
|
11
|
+
const LOCAL_CURATOR_NETWORK_DEFAULTS = { enabled: false, host: "localhost", bind: "127.0.0.1" };
|
|
12
|
+
function trimmedString(value) {
|
|
13
|
+
if (typeof value !== "string")
|
|
14
|
+
return undefined;
|
|
15
|
+
const trimmed = value.trim();
|
|
16
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
17
|
+
}
|
|
18
|
+
/** Resolves the curator server bind address and URL host from `curatorRemote`. */
|
|
19
|
+
export function resolveCuratorNetworkConfig() {
|
|
20
|
+
const configPath = getWebSearchConfigPath();
|
|
21
|
+
if (!existsSync(configPath))
|
|
22
|
+
return LOCAL_CURATOR_NETWORK_DEFAULTS;
|
|
23
|
+
let raw;
|
|
24
|
+
try {
|
|
25
|
+
raw = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return LOCAL_CURATOR_NETWORK_DEFAULTS;
|
|
29
|
+
}
|
|
30
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
31
|
+
return LOCAL_CURATOR_NETWORK_DEFAULTS;
|
|
32
|
+
const curatorRemote = raw.curatorRemote;
|
|
33
|
+
if (curatorRemote === true)
|
|
34
|
+
return { enabled: true, host: hostname(), bind: "0.0.0.0" };
|
|
35
|
+
if (curatorRemote && typeof curatorRemote === "object" && !Array.isArray(curatorRemote)) {
|
|
36
|
+
const obj = curatorRemote;
|
|
37
|
+
return {
|
|
38
|
+
enabled: true,
|
|
39
|
+
host: trimmedString(obj.host) ?? hostname(),
|
|
40
|
+
bind: trimmedString(obj.bind) ?? "0.0.0.0",
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return LOCAL_CURATOR_NETWORK_DEFAULTS;
|
|
44
|
+
}
|
|
45
|
+
export function formatSeconds(s) {
|
|
46
|
+
const h = Math.floor(s / 3600);
|
|
47
|
+
const m = Math.floor((s % 3600) / 60);
|
|
48
|
+
const sec = s % 60;
|
|
49
|
+
if (h > 0)
|
|
50
|
+
return `${h}:${String(m).padStart(2, "0")}:${String(sec).padStart(2, "0")}`;
|
|
51
|
+
return `${m}:${String(sec).padStart(2, "0")}`;
|
|
52
|
+
}
|
|
53
|
+
export function readExecError(err) {
|
|
54
|
+
if (!err || typeof err !== "object") {
|
|
55
|
+
return { stderr: "", message: String(err) };
|
|
56
|
+
}
|
|
57
|
+
const code = err.code;
|
|
58
|
+
const message = err.message ?? "";
|
|
59
|
+
const stderrRaw = err.stderr;
|
|
60
|
+
const stderr = Buffer.isBuffer(stderrRaw)
|
|
61
|
+
? stderrRaw.toString("utf-8")
|
|
62
|
+
: typeof stderrRaw === "string"
|
|
63
|
+
? stderrRaw
|
|
64
|
+
: "";
|
|
65
|
+
return { code, stderr, message };
|
|
66
|
+
}
|
|
67
|
+
export function isTimeoutError(err) {
|
|
68
|
+
if (!err || typeof err !== "object")
|
|
69
|
+
return false;
|
|
70
|
+
if (err.killed)
|
|
71
|
+
return true;
|
|
72
|
+
const name = err.name;
|
|
73
|
+
const code = err.code;
|
|
74
|
+
const message = err.message ?? "";
|
|
75
|
+
return name === "AbortError" || code === "ETIMEDOUT" || message.toLowerCase().includes("timed out");
|
|
76
|
+
}
|
|
77
|
+
export function trimErrorText(text) {
|
|
78
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
79
|
+
}
|
|
80
|
+
export function mapFfmpegError(err) {
|
|
81
|
+
const { code, stderr, message } = readExecError(err);
|
|
82
|
+
if (code === "ENOENT")
|
|
83
|
+
return "ffmpeg is not installed. Install with: brew install ffmpeg";
|
|
84
|
+
if (isTimeoutError(err))
|
|
85
|
+
return "ffmpeg timed out extracting frame";
|
|
86
|
+
if (stderr.includes("403"))
|
|
87
|
+
return "Stream URL returned 403 — may have expired, try again";
|
|
88
|
+
const snippet = trimErrorText(stderr || message);
|
|
89
|
+
return snippet ? `ffmpeg failed: ${snippet}` : "ffmpeg failed";
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { hostname } from \"node:os\";\nimport { join } from \"node:path\";\nimport { getAgentDir } from \"../host.ts\";\n\nexport function getWebSearchConfigDir(): string {\n\treturn getAgentDir();\n}\n\nexport function getWebSearchConfigPath(): string {\n\treturn join(getWebSearchConfigDir(), \"web-search.json\");\n}\n\nexport interface CuratorNetworkConfig {\n\t/** Whether remote access was opted into via curatorRemote. */\n\tenabled: boolean;\n\thost: string;\n\tbind: string;\n}\n\nconst LOCAL_CURATOR_NETWORK_DEFAULTS: CuratorNetworkConfig = { enabled: false, host: \"localhost\", bind: \"127.0.0.1\" };\n\nfunction trimmedString(value: unknown): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst trimmed = value.trim();\n\treturn trimmed.length > 0 ? trimmed : undefined;\n}\n\n/** Resolves the curator server bind address and URL host from `curatorRemote`. */\nexport function resolveCuratorNetworkConfig(): CuratorNetworkConfig {\n\tconst configPath = getWebSearchConfigPath();\n\tif (!existsSync(configPath)) return LOCAL_CURATOR_NETWORK_DEFAULTS;\n\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(readFileSync(configPath, \"utf-8\"));\n\t} catch {\n\t\treturn LOCAL_CURATOR_NETWORK_DEFAULTS;\n\t}\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return LOCAL_CURATOR_NETWORK_DEFAULTS;\n\n\tconst curatorRemote = (raw as Record<string, unknown>).curatorRemote;\n\tif (curatorRemote === true) return { enabled: true, host: hostname(), bind: \"0.0.0.0\" };\n\n\tif (curatorRemote && typeof curatorRemote === \"object\" && !Array.isArray(curatorRemote)) {\n\t\tconst obj = curatorRemote as Record<string, unknown>;\n\t\treturn {\n\t\t\tenabled: true,\n\t\t\thost: trimmedString(obj.host) ?? hostname(),\n\t\t\tbind: trimmedString(obj.bind) ?? \"0.0.0.0\",\n\t\t};\n\t}\n\n\treturn LOCAL_CURATOR_NETWORK_DEFAULTS;\n}\n\nexport function formatSeconds(s: number): string {\n\tconst h = Math.floor(s / 3600);\n\tconst m = Math.floor((s % 3600) / 60);\n\tconst sec = s % 60;\n\tif (h > 0) return `${h}:${String(m).padStart(2, \"0\")}:${String(sec).padStart(2, \"0\")}`;\n\treturn `${m}:${String(sec).padStart(2, \"0\")}`;\n}\n\nexport function readExecError(err: unknown): { code?: string; stderr: string; message: string } {\n\tif (!err || typeof err !== \"object\") {\n\t\treturn { stderr: \"\", message: String(err) };\n\t}\n\tconst code = (err as { code?: string }).code;\n\tconst message = (err as { message?: string }).message ?? \"\";\n\tconst stderrRaw = (err as { stderr?: Buffer | string }).stderr;\n\tconst stderr = Buffer.isBuffer(stderrRaw)\n\t\t? stderrRaw.toString(\"utf-8\")\n\t\t: typeof stderrRaw === \"string\"\n\t\t\t? stderrRaw\n\t\t\t: \"\";\n\treturn { code, stderr, message };\n}\n\nexport function isTimeoutError(err: unknown): boolean {\n\tif (!err || typeof err !== \"object\") return false;\n\tif ((err as { killed?: boolean }).killed) return true;\n\tconst name = (err as { name?: string }).name;\n\tconst code = (err as { code?: string }).code;\n\tconst message = (err as { message?: string }).message ?? \"\";\n\treturn name === \"AbortError\" || code === \"ETIMEDOUT\" || message.toLowerCase().includes(\"timed out\");\n}\n\nexport function trimErrorText(text: string): string {\n\treturn text.replace(/\\s+/g, \" \").trim().slice(0, 200);\n}\n\nexport function mapFfmpegError(err: unknown): string {\n\tconst { code, stderr, message } = readExecError(err);\n\tif (code === \"ENOENT\") return \"ffmpeg is not installed. Install with: brew install ffmpeg\";\n\tif (isTimeoutError(err)) return \"ffmpeg timed out extracting frame\";\n\tif (stderr.includes(\"403\")) return \"Stream URL returned 403 — may have expired, try again\";\n\tconst snippet = trimErrorText(stderr || message);\n\treturn snippet ? `ffmpeg failed: ${snippet}` : \"ffmpeg failed\";\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ExtractedContent, type ExtractOptions, type FrameResult } from "./extract.ts";
|
|
2
|
+
interface VideoFileInfo {
|
|
3
|
+
absolutePath: string;
|
|
4
|
+
mimeType: string;
|
|
5
|
+
sizeBytes: number;
|
|
6
|
+
maxSizeBytes: number;
|
|
7
|
+
withinUploadLimit: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function isVideoFile(input: string): VideoFileInfo | null;
|
|
10
|
+
export declare function extractVideo(info: VideoFileInfo, signal?: AbortSignal, options?: ExtractOptions): Promise<ExtractedContent | null>;
|
|
11
|
+
export declare function extractVideoFrame(filePath: string, seconds?: number): Promise<FrameResult>;
|
|
12
|
+
export declare function getLocalVideoDuration(filePath: string): Promise<number | {
|
|
13
|
+
error: string;
|
|
14
|
+
}>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=video-extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-extract.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/video-extract.ts"],"names":[],"mappings":"AAQA,OAAO,EAAuB,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AA+BjH,UAAU,aAAa;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,OAAO,CAAC;CAC3B;AAwDD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAuC/D;AAuBD,wBAAsB,YAAY,CACjC,IAAI,EAAE,aAAa,EACnB,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAkClC;AASD,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,MAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAWnG;AAED,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAcjG","sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport { existsSync, readFileSync, readdirSync, statSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { resolve, extname, basename, join, dirname } from \"node:path\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { canAttachImages } from \"./feature-config.ts\";\nimport { isGeminiWebAvailable, queryWithCookies } from \"./gemini-web.ts\";\nimport { queryGeminiApiWithVideo, getApiKey, fetchGeminiApi, getVersionedApiBase, getUploadBase, redactGeminiApiResponse } from \"./gemini-api.ts\";\nimport { extractHeadingTitle, type ExtractedContent, type ExtractOptions, type FrameResult } from \"./extract.ts\";\nimport { readExecError, trimErrorText, mapFfmpegError, getWebSearchConfigPath } from \"./utils.ts\";\n\nconst CONFIG_PATH = getWebSearchConfigPath();\n\nconst DEFAULT_VIDEO_PROMPT = `Extract the complete content of this video. Include:\n1. Video title (infer from content if not explicit), duration\n2. A brief summary (2-3 sentences)\n3. Full transcript with timestamps\n4. Descriptions of any code, terminal commands, diagrams, slides, or UI shown on screen\n\nFormat as markdown.`;\n\nconst VIDEO_EXTENSIONS: Record<string, string> = {\n\t\".mp4\": \"video/mp4\",\n\t\".mov\": \"video/quicktime\",\n\t\".webm\": \"video/webm\",\n\t\".avi\": \"video/x-msvideo\",\n\t\".mpeg\": \"video/mpeg\",\n\t\".mpg\": \"video/mpeg\",\n\t\".wmv\": \"video/x-ms-wmv\",\n\t\".flv\": \"video/x-flv\",\n\t\".3gp\": \"video/3gpp\",\n\t\".3gpp\": \"video/3gpp\",\n};\n\nfunction shouldRethrow(err: unknown): boolean {\n\tconst message = err instanceof Error ? err.message : String(err);\n\treturn message.startsWith(\"Failed to parse \");\n}\n\ninterface VideoFileInfo {\n\tabsolutePath: string;\n\tmimeType: string;\n\tsizeBytes: number;\n\tmaxSizeBytes: number;\n\twithinUploadLimit: boolean;\n}\n\ninterface VideoConfig {\n\tenabled: boolean;\n\tpreferredModel: string;\n\tmaxSizeMB: number;\n}\n\nfunction normalizePreferredModel(value: unknown, fallback: string): string {\n\tif (typeof value !== \"string\") return fallback;\n\tconst normalized = value.trim();\n\treturn normalized.length > 0 ? normalized : fallback;\n}\n\nfunction normalizeEnabled(value: unknown, fallback: boolean): boolean {\n\treturn typeof value === \"boolean\" ? value : fallback;\n}\n\nfunction normalizeMaxSizeMB(value: unknown, fallback: number): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n\treturn value > 0 ? value : fallback;\n}\n\nconst VIDEO_CONFIG_DEFAULTS: VideoConfig = {\n\tenabled: true,\n\tpreferredModel: \"gemini-3.6-flash\",\n\tmaxSizeMB: 50,\n};\n\nlet cachedVideoConfig: VideoConfig | null = null;\n\nfunction loadVideoConfig(): VideoConfig {\n\tif (cachedVideoConfig) return cachedVideoConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedVideoConfig = { ...VIDEO_CONFIG_DEFAULTS };\n\t\treturn cachedVideoConfig;\n\t}\n\n\tconst rawText = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet raw: { video?: { enabled?: boolean; preferredModel?: string; maxSizeMB?: number } };\n\ttry {\n\t\traw = JSON.parse(rawText) as { video?: { enabled?: boolean; preferredModel?: string; maxSizeMB?: number } };\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 v = raw.video ?? {};\n\tcachedVideoConfig = {\n\t\tenabled: normalizeEnabled(v.enabled, VIDEO_CONFIG_DEFAULTS.enabled),\n\t\tpreferredModel: normalizePreferredModel(v.preferredModel, VIDEO_CONFIG_DEFAULTS.preferredModel),\n\t\tmaxSizeMB: normalizeMaxSizeMB(v.maxSizeMB, VIDEO_CONFIG_DEFAULTS.maxSizeMB),\n\t};\n\treturn cachedVideoConfig;\n}\n\nexport function isVideoFile(input: string): VideoFileInfo | null {\n\tconst config = loadVideoConfig();\n\tif (!config.enabled) return null;\n\n\tconst isFilePath = input.startsWith(\"/\") || input.startsWith(\"./\") || input.startsWith(\"../\") || input.startsWith(\"file://\");\n\tif (!isFilePath) return null;\n\n\tlet filePath = input;\n\tif (input.startsWith(\"file://\")) {\n\t\ttry {\n\t\t\tfilePath = decodeURIComponent(new URL(input).pathname);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tconst ext = extname(filePath).toLowerCase();\n\tconst mimeType = VIDEO_EXTENSIONS[ext];\n\tif (!mimeType) return null;\n\n\tconst absolutePath = resolveFilePath(filePath);\n\tif (!absolutePath) return null;\n\n\tlet stat: ReturnType<typeof statSync>;\n\ttry {\n\t\tstat = statSync(absolutePath);\n\t} catch {\n\t\treturn null;\n\t}\n\tif (!stat.isFile()) return null;\n\n\tconst maxBytes = config.maxSizeMB * 1024 * 1024;\n\treturn {\n\t\tabsolutePath,\n\t\tmimeType,\n\t\tsizeBytes: stat.size,\n\t\tmaxSizeBytes: maxBytes,\n\t\twithinUploadLimit: stat.size <= maxBytes,\n\t};\n}\n\nfunction resolveFilePath(filePath: string): string | null {\n\tconst absolutePath = resolve(filePath);\n\tif (existsSync(absolutePath)) return absolutePath;\n\n\tconst dir = dirname(absolutePath);\n\tconst base = basename(absolutePath);\n\tif (!existsSync(dir)) return null;\n\n\ttry {\n\t\tconst normalizedBase = normalizeSpaces(base);\n\t\tconst match = readdirSync(dir).find(f => normalizeSpaces(f) === normalizedBase);\n\t\treturn match ? join(dir, match) : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction normalizeSpaces(s: string): string {\n\treturn s.replace(/[\\u00A0\\u2000-\\u200B\\u202F\\u205F\\u3000\\uFEFF]/g, \" \");\n}\n\nexport async function extractVideo(\n\tinfo: VideoFileInfo,\n\tsignal?: AbortSignal,\n\toptions?: ExtractOptions,\n): Promise<ExtractedContent | null> {\n\tconst config = loadVideoConfig();\n\tconst effectivePrompt = options?.prompt ?? DEFAULT_VIDEO_PROMPT;\n\tconst effectiveModel = options?.model ?? config.preferredModel;\n\tconst displayName = basename(info.absolutePath);\n\tif (!info.withinUploadLimit) {\n\t\tconst sizeMB = (info.sizeBytes / 1024 / 1024).toFixed(1);\n\t\tconst maxSizeMB = (info.maxSizeBytes / 1024 / 1024).toFixed(1);\n\t\tconst error = `Local video ${displayName} is ${sizeMB} MiB, above configured video.maxSizeMB (${maxSizeMB} MiB) for Gemini analysis. Use timestamp/frames for ffmpeg frame extraction, increase video.maxSizeMB, or compress the file.`;\n\t\treturn { url: info.absolutePath, title: displayName, content: error, error };\n\t}\n\tconst activityId = activityMonitor.logStart({ type: \"fetch\", url: `video:${displayName}` });\n\n\tconst result = await tryVideoGeminiApi(info, effectivePrompt, effectiveModel, signal)\n\t\t?? await tryVideoGeminiWeb(info, effectivePrompt, effectiveModel, signal);\n\n\tif (result) {\n\t\tif (canAttachImages()) {\n\t\t\tconst thumbnail = await extractVideoFrame(info.absolutePath);\n\t\t\tif (!(\"error\" in thumbnail)) {\n\t\t\t\tresult.thumbnail = thumbnail;\n\t\t\t}\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn result;\n\t}\n\n\tif (signal?.aborted) {\n\t\tactivityMonitor.logComplete(activityId, 0);\n\t\treturn null;\n\t}\n\n\tactivityMonitor.logError(activityId, \"all video extraction paths failed\");\n\treturn null;\n}\n\nfunction mapFfprobeError(err: unknown): string {\n\tconst { code, stderr, message } = readExecError(err);\n\tif (code === \"ENOENT\") return \"ffprobe is not installed. Install ffmpeg which includes ffprobe\";\n\tconst snippet = trimErrorText(stderr || message);\n\treturn snippet ? `ffprobe failed: ${snippet}` : \"ffprobe failed\";\n}\n\nexport async function extractVideoFrame(filePath: string, seconds: number = 1): Promise<FrameResult> {\n\ttry {\n\t\tconst buffer = execFileSync(\"ffmpeg\", [\n\t\t\t\"-ss\", String(seconds), \"-i\", filePath,\n\t\t\t\"-frames:v\", \"1\", \"-f\", \"image2pipe\", \"-vcodec\", \"mjpeg\", \"pipe:1\",\n\t\t], { maxBuffer: 5 * 1024 * 1024, timeout: 10000, stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n\t\tif (buffer.length === 0) return { error: \"ffmpeg failed: empty output\" };\n\t\treturn { data: buffer.toString(\"base64\"), mimeType: \"image/jpeg\" };\n\t} catch (err) {\n\t\treturn { error: mapFfmpegError(err) };\n\t}\n}\n\nexport async function getLocalVideoDuration(filePath: string): Promise<number | { error: string }> {\n\ttry {\n\t\tconst output = execFileSync(\"ffprobe\", [\n\t\t\t\"-v\", \"quiet\",\n\t\t\t\"-show_entries\", \"format=duration\",\n\t\t\t\"-of\", \"csv=p=0\",\n\t\t\tfilePath,\n\t\t], { timeout: 10000, encoding: \"utf-8\", stdio: [\"pipe\", \"pipe\", \"pipe\"] }).trim();\n\t\tconst duration = Number.parseFloat(output);\n\t\tif (!Number.isFinite(duration)) return { error: \"ffprobe failed: invalid duration output\" };\n\t\treturn duration;\n\t} catch (err) {\n\t\treturn { error: mapFfprobeError(err) };\n\t}\n}\n\nasync function tryVideoGeminiWeb(\n\tinfo: VideoFileInfo,\n\tprompt: string,\n\tmodel: string,\n\tsignal?: AbortSignal,\n): Promise<ExtractedContent | null> {\n\ttry {\n\t\tconst cookies = await isGeminiWebAvailable();\n\t\tif (!cookies) return null;\n\t\tif (signal?.aborted) return null;\n\n\t\tconst text = await queryWithCookies(prompt, cookies, {\n\t\t\tfiles: [info.absolutePath],\n\t\t\t...(model !== \"gemini-3.6-flash\" ? { model } : {}),\n\t\t\tsignal,\n\t\t\ttimeoutMs: 180000,\n\t\t});\n\n\t\treturn {\n\t\t\turl: info.absolutePath,\n\t\t\ttitle: extractVideoTitle(text, info.absolutePath),\n\t\t\tcontent: text,\n\t\t\terror: null,\n\t\t};\n\t} catch (err) {\n\t\tif (shouldRethrow(err)) throw err;\n\t\treturn null;\n\t}\n}\n\nasync function tryVideoGeminiApi(\n\tinfo: VideoFileInfo,\n\tprompt: string,\n\tmodel: string,\n\tsignal?: AbortSignal,\n): Promise<ExtractedContent | null> {\n\tconst apiKey = await getApiKey(signal);\n\tif (!apiKey) return null;\n\tif (signal?.aborted) return null;\n\n\tlet fileName: string | null = null;\n\ttry {\n\t\tconst uploaded = await uploadToFilesApi(info, apiKey, signal);\n\t\tfileName = uploaded.name;\n\n\t\tawait pollFileState(fileName, apiKey, signal, 120000);\n\n\t\tconst text = await queryGeminiApiWithVideo(prompt, uploaded.uri, {\n\t\t\tapiKey,\n\t\t\tmodel,\n\t\t\tmimeType: info.mimeType,\n\t\t\tsignal,\n\t\t\ttimeoutMs: 120000,\n\t\t});\n\n\t\treturn {\n\t\t\turl: info.absolutePath,\n\t\t\ttitle: extractVideoTitle(text, info.absolutePath),\n\t\t\tcontent: text,\n\t\t\terror: null,\n\t\t};\n\t} catch (err) {\n\t\tif (shouldRethrow(err)) throw err;\n\t\treturn null;\n\t} finally {\n\t\tif (fileName) deleteGeminiFile(fileName, apiKey);\n\t}\n}\n\nasync function uploadToFilesApi(\n\tinfo: VideoFileInfo,\n\tapiKey: string,\n\tsignal?: AbortSignal,\n): Promise<{ name: string; uri: string }> {\n\tconst displayName = basename(info.absolutePath);\n\n\tconst initRes = await fetchGeminiApi(`${getUploadBase()}/files`, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"X-Goog-Upload-Protocol\": \"resumable\",\n\t\t\t\"X-Goog-Upload-Command\": \"start\",\n\t\t\t\"X-Goog-Upload-Header-Content-Length\": String(info.sizeBytes),\n\t\t\t\"X-Goog-Upload-Header-Content-Type\": info.mimeType,\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t},\n\t\tbody: JSON.stringify({ file: { display_name: displayName } }),\n\t\tsignal,\n\t}, apiKey);\n\n\tif (!initRes.ok) {\n\t\tconst text = redactGeminiApiResponse(initRes, await initRes.text(), apiKey);\n\t\tthrow new Error(`File upload init failed: ${initRes.status} (${text.slice(0, 200)})`);\n\t}\n\n\tconst uploadUrl = initRes.headers.get(\"x-goog-upload-url\");\n\tif (!uploadUrl) throw new Error(\"No upload URL in response headers\");\n\n\tconst fileData = await readFile(info.absolutePath);\n\tconst uploadRes = await fetchGeminiApi(uploadUrl, {\n\t\tmethod: \"PUT\",\n\t\theaders: {\n\t\t\t\"Content-Length\": String(info.sizeBytes),\n\t\t\t\"X-Goog-Upload-Offset\": \"0\",\n\t\t\t\"X-Goog-Upload-Command\": \"upload, finalize\",\n\t\t},\n\t\tbody: fileData,\n\t\tsignal,\n\t}, apiKey);\n\n\tif (!uploadRes.ok) {\n\t\tconst text = redactGeminiApiResponse(uploadRes, await uploadRes.text(), apiKey);\n\t\tthrow new Error(`File upload failed: ${uploadRes.status} (${text.slice(0, 200)})`);\n\t}\n\n\tconst result = await uploadRes.json() as { file: { name: string; uri: string } };\n\treturn result.file;\n}\n\nasync function pollFileState(\n\tfileName: string,\n\tapiKey: string,\n\tsignal?: AbortSignal,\n\ttimeoutMs: number = 120000,\n): Promise<void> {\n\tconst deadline = Date.now() + timeoutMs;\n\n\twhile (Date.now() < deadline) {\n\t\tif (signal?.aborted) throw new Error(\"Aborted\");\n\n\t\tconst res = await fetchGeminiApi(`${getVersionedApiBase()}/${fileName}`, { signal }, apiKey);\n\t\tif (!res.ok) throw new Error(`File state check failed: ${res.status}`);\n\n\t\tconst data = await res.json() as { state: string };\n\t\tif (data.state === \"ACTIVE\") return;\n\t\tif (data.state === \"FAILED\") throw new Error(\"File processing failed\");\n\n\t\tawait new Promise(r => setTimeout(r, 5000));\n\t}\n\n\tthrow new Error(\"File processing timed out\");\n}\n\nfunction deleteGeminiFile(fileName: string, apiKey: string): void {\n\tvoid fetchGeminiApi(`${getVersionedApiBase()}/${fileName}`, { method: \"DELETE\" }, apiKey).catch((err) => {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tconsole.error(`Failed to delete Gemini file ${fileName}: ${message}`);\n\t});\n}\n\nfunction extractVideoTitle(text: string, filePath: string): string {\n\treturn extractHeadingTitle(text) ?? basename(filePath, extname(filePath));\n}\n"]}
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { resolve, extname, basename, join, dirname } from "node:path";
|
|
5
|
+
import { activityMonitor } from "./activity.js";
|
|
6
|
+
import { canAttachImages } from "./feature-config.js";
|
|
7
|
+
import { isGeminiWebAvailable, queryWithCookies } from "./gemini-web.js";
|
|
8
|
+
import { queryGeminiApiWithVideo, getApiKey, fetchGeminiApi, getVersionedApiBase, getUploadBase, redactGeminiApiResponse } from "./gemini-api.js";
|
|
9
|
+
import { extractHeadingTitle } from "./extract.js";
|
|
10
|
+
import { readExecError, trimErrorText, mapFfmpegError, getWebSearchConfigPath } from "./utils.js";
|
|
11
|
+
const CONFIG_PATH = getWebSearchConfigPath();
|
|
12
|
+
const DEFAULT_VIDEO_PROMPT = `Extract the complete content of this video. Include:
|
|
13
|
+
1. Video title (infer from content if not explicit), duration
|
|
14
|
+
2. A brief summary (2-3 sentences)
|
|
15
|
+
3. Full transcript with timestamps
|
|
16
|
+
4. Descriptions of any code, terminal commands, diagrams, slides, or UI shown on screen
|
|
17
|
+
|
|
18
|
+
Format as markdown.`;
|
|
19
|
+
const VIDEO_EXTENSIONS = {
|
|
20
|
+
".mp4": "video/mp4",
|
|
21
|
+
".mov": "video/quicktime",
|
|
22
|
+
".webm": "video/webm",
|
|
23
|
+
".avi": "video/x-msvideo",
|
|
24
|
+
".mpeg": "video/mpeg",
|
|
25
|
+
".mpg": "video/mpeg",
|
|
26
|
+
".wmv": "video/x-ms-wmv",
|
|
27
|
+
".flv": "video/x-flv",
|
|
28
|
+
".3gp": "video/3gpp",
|
|
29
|
+
".3gpp": "video/3gpp",
|
|
30
|
+
};
|
|
31
|
+
function shouldRethrow(err) {
|
|
32
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
33
|
+
return message.startsWith("Failed to parse ");
|
|
34
|
+
}
|
|
35
|
+
function normalizePreferredModel(value, fallback) {
|
|
36
|
+
if (typeof value !== "string")
|
|
37
|
+
return fallback;
|
|
38
|
+
const normalized = value.trim();
|
|
39
|
+
return normalized.length > 0 ? normalized : fallback;
|
|
40
|
+
}
|
|
41
|
+
function normalizeEnabled(value, fallback) {
|
|
42
|
+
return typeof value === "boolean" ? value : fallback;
|
|
43
|
+
}
|
|
44
|
+
function normalizeMaxSizeMB(value, fallback) {
|
|
45
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
46
|
+
return fallback;
|
|
47
|
+
return value > 0 ? value : fallback;
|
|
48
|
+
}
|
|
49
|
+
const VIDEO_CONFIG_DEFAULTS = {
|
|
50
|
+
enabled: true,
|
|
51
|
+
preferredModel: "gemini-3.6-flash",
|
|
52
|
+
maxSizeMB: 50,
|
|
53
|
+
};
|
|
54
|
+
let cachedVideoConfig = null;
|
|
55
|
+
function loadVideoConfig() {
|
|
56
|
+
if (cachedVideoConfig)
|
|
57
|
+
return cachedVideoConfig;
|
|
58
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
59
|
+
cachedVideoConfig = { ...VIDEO_CONFIG_DEFAULTS };
|
|
60
|
+
return cachedVideoConfig;
|
|
61
|
+
}
|
|
62
|
+
const rawText = readFileSync(CONFIG_PATH, "utf-8");
|
|
63
|
+
let raw;
|
|
64
|
+
try {
|
|
65
|
+
raw = JSON.parse(rawText);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
69
|
+
throw new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);
|
|
70
|
+
}
|
|
71
|
+
const v = raw.video ?? {};
|
|
72
|
+
cachedVideoConfig = {
|
|
73
|
+
enabled: normalizeEnabled(v.enabled, VIDEO_CONFIG_DEFAULTS.enabled),
|
|
74
|
+
preferredModel: normalizePreferredModel(v.preferredModel, VIDEO_CONFIG_DEFAULTS.preferredModel),
|
|
75
|
+
maxSizeMB: normalizeMaxSizeMB(v.maxSizeMB, VIDEO_CONFIG_DEFAULTS.maxSizeMB),
|
|
76
|
+
};
|
|
77
|
+
return cachedVideoConfig;
|
|
78
|
+
}
|
|
79
|
+
export function isVideoFile(input) {
|
|
80
|
+
const config = loadVideoConfig();
|
|
81
|
+
if (!config.enabled)
|
|
82
|
+
return null;
|
|
83
|
+
const isFilePath = input.startsWith("/") || input.startsWith("./") || input.startsWith("../") || input.startsWith("file://");
|
|
84
|
+
if (!isFilePath)
|
|
85
|
+
return null;
|
|
86
|
+
let filePath = input;
|
|
87
|
+
if (input.startsWith("file://")) {
|
|
88
|
+
try {
|
|
89
|
+
filePath = decodeURIComponent(new URL(input).pathname);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const ext = extname(filePath).toLowerCase();
|
|
96
|
+
const mimeType = VIDEO_EXTENSIONS[ext];
|
|
97
|
+
if (!mimeType)
|
|
98
|
+
return null;
|
|
99
|
+
const absolutePath = resolveFilePath(filePath);
|
|
100
|
+
if (!absolutePath)
|
|
101
|
+
return null;
|
|
102
|
+
let stat;
|
|
103
|
+
try {
|
|
104
|
+
stat = statSync(absolutePath);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
if (!stat.isFile())
|
|
110
|
+
return null;
|
|
111
|
+
const maxBytes = config.maxSizeMB * 1024 * 1024;
|
|
112
|
+
return {
|
|
113
|
+
absolutePath,
|
|
114
|
+
mimeType,
|
|
115
|
+
sizeBytes: stat.size,
|
|
116
|
+
maxSizeBytes: maxBytes,
|
|
117
|
+
withinUploadLimit: stat.size <= maxBytes,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function resolveFilePath(filePath) {
|
|
121
|
+
const absolutePath = resolve(filePath);
|
|
122
|
+
if (existsSync(absolutePath))
|
|
123
|
+
return absolutePath;
|
|
124
|
+
const dir = dirname(absolutePath);
|
|
125
|
+
const base = basename(absolutePath);
|
|
126
|
+
if (!existsSync(dir))
|
|
127
|
+
return null;
|
|
128
|
+
try {
|
|
129
|
+
const normalizedBase = normalizeSpaces(base);
|
|
130
|
+
const match = readdirSync(dir).find(f => normalizeSpaces(f) === normalizedBase);
|
|
131
|
+
return match ? join(dir, match) : null;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function normalizeSpaces(s) {
|
|
138
|
+
return s.replace(/[\u00A0\u2000-\u200B\u202F\u205F\u3000\uFEFF]/g, " ");
|
|
139
|
+
}
|
|
140
|
+
export async function extractVideo(info, signal, options) {
|
|
141
|
+
const config = loadVideoConfig();
|
|
142
|
+
const effectivePrompt = options?.prompt ?? DEFAULT_VIDEO_PROMPT;
|
|
143
|
+
const effectiveModel = options?.model ?? config.preferredModel;
|
|
144
|
+
const displayName = basename(info.absolutePath);
|
|
145
|
+
if (!info.withinUploadLimit) {
|
|
146
|
+
const sizeMB = (info.sizeBytes / 1024 / 1024).toFixed(1);
|
|
147
|
+
const maxSizeMB = (info.maxSizeBytes / 1024 / 1024).toFixed(1);
|
|
148
|
+
const error = `Local video ${displayName} is ${sizeMB} MiB, above configured video.maxSizeMB (${maxSizeMB} MiB) for Gemini analysis. Use timestamp/frames for ffmpeg frame extraction, increase video.maxSizeMB, or compress the file.`;
|
|
149
|
+
return { url: info.absolutePath, title: displayName, content: error, error };
|
|
150
|
+
}
|
|
151
|
+
const activityId = activityMonitor.logStart({ type: "fetch", url: `video:${displayName}` });
|
|
152
|
+
const result = await tryVideoGeminiApi(info, effectivePrompt, effectiveModel, signal)
|
|
153
|
+
?? await tryVideoGeminiWeb(info, effectivePrompt, effectiveModel, signal);
|
|
154
|
+
if (result) {
|
|
155
|
+
if (canAttachImages()) {
|
|
156
|
+
const thumbnail = await extractVideoFrame(info.absolutePath);
|
|
157
|
+
if (!("error" in thumbnail)) {
|
|
158
|
+
result.thumbnail = thumbnail;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
activityMonitor.logComplete(activityId, 200);
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
if (signal?.aborted) {
|
|
165
|
+
activityMonitor.logComplete(activityId, 0);
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
activityMonitor.logError(activityId, "all video extraction paths failed");
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
function mapFfprobeError(err) {
|
|
172
|
+
const { code, stderr, message } = readExecError(err);
|
|
173
|
+
if (code === "ENOENT")
|
|
174
|
+
return "ffprobe is not installed. Install ffmpeg which includes ffprobe";
|
|
175
|
+
const snippet = trimErrorText(stderr || message);
|
|
176
|
+
return snippet ? `ffprobe failed: ${snippet}` : "ffprobe failed";
|
|
177
|
+
}
|
|
178
|
+
export async function extractVideoFrame(filePath, seconds = 1) {
|
|
179
|
+
try {
|
|
180
|
+
const buffer = execFileSync("ffmpeg", [
|
|
181
|
+
"-ss", String(seconds), "-i", filePath,
|
|
182
|
+
"-frames:v", "1", "-f", "image2pipe", "-vcodec", "mjpeg", "pipe:1",
|
|
183
|
+
], { maxBuffer: 5 * 1024 * 1024, timeout: 10000, stdio: ["pipe", "pipe", "pipe"] });
|
|
184
|
+
if (buffer.length === 0)
|
|
185
|
+
return { error: "ffmpeg failed: empty output" };
|
|
186
|
+
return { data: buffer.toString("base64"), mimeType: "image/jpeg" };
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
return { error: mapFfmpegError(err) };
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
export async function getLocalVideoDuration(filePath) {
|
|
193
|
+
try {
|
|
194
|
+
const output = execFileSync("ffprobe", [
|
|
195
|
+
"-v", "quiet",
|
|
196
|
+
"-show_entries", "format=duration",
|
|
197
|
+
"-of", "csv=p=0",
|
|
198
|
+
filePath,
|
|
199
|
+
], { timeout: 10000, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
200
|
+
const duration = Number.parseFloat(output);
|
|
201
|
+
if (!Number.isFinite(duration))
|
|
202
|
+
return { error: "ffprobe failed: invalid duration output" };
|
|
203
|
+
return duration;
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
return { error: mapFfprobeError(err) };
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async function tryVideoGeminiWeb(info, prompt, model, signal) {
|
|
210
|
+
try {
|
|
211
|
+
const cookies = await isGeminiWebAvailable();
|
|
212
|
+
if (!cookies)
|
|
213
|
+
return null;
|
|
214
|
+
if (signal?.aborted)
|
|
215
|
+
return null;
|
|
216
|
+
const text = await queryWithCookies(prompt, cookies, {
|
|
217
|
+
files: [info.absolutePath],
|
|
218
|
+
...(model !== "gemini-3.6-flash" ? { model } : {}),
|
|
219
|
+
signal,
|
|
220
|
+
timeoutMs: 180000,
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
url: info.absolutePath,
|
|
224
|
+
title: extractVideoTitle(text, info.absolutePath),
|
|
225
|
+
content: text,
|
|
226
|
+
error: null,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
if (shouldRethrow(err))
|
|
231
|
+
throw err;
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
async function tryVideoGeminiApi(info, prompt, model, signal) {
|
|
236
|
+
const apiKey = await getApiKey(signal);
|
|
237
|
+
if (!apiKey)
|
|
238
|
+
return null;
|
|
239
|
+
if (signal?.aborted)
|
|
240
|
+
return null;
|
|
241
|
+
let fileName = null;
|
|
242
|
+
try {
|
|
243
|
+
const uploaded = await uploadToFilesApi(info, apiKey, signal);
|
|
244
|
+
fileName = uploaded.name;
|
|
245
|
+
await pollFileState(fileName, apiKey, signal, 120000);
|
|
246
|
+
const text = await queryGeminiApiWithVideo(prompt, uploaded.uri, {
|
|
247
|
+
apiKey,
|
|
248
|
+
model,
|
|
249
|
+
mimeType: info.mimeType,
|
|
250
|
+
signal,
|
|
251
|
+
timeoutMs: 120000,
|
|
252
|
+
});
|
|
253
|
+
return {
|
|
254
|
+
url: info.absolutePath,
|
|
255
|
+
title: extractVideoTitle(text, info.absolutePath),
|
|
256
|
+
content: text,
|
|
257
|
+
error: null,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
catch (err) {
|
|
261
|
+
if (shouldRethrow(err))
|
|
262
|
+
throw err;
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
finally {
|
|
266
|
+
if (fileName)
|
|
267
|
+
deleteGeminiFile(fileName, apiKey);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
async function uploadToFilesApi(info, apiKey, signal) {
|
|
271
|
+
const displayName = basename(info.absolutePath);
|
|
272
|
+
const initRes = await fetchGeminiApi(`${getUploadBase()}/files`, {
|
|
273
|
+
method: "POST",
|
|
274
|
+
headers: {
|
|
275
|
+
"X-Goog-Upload-Protocol": "resumable",
|
|
276
|
+
"X-Goog-Upload-Command": "start",
|
|
277
|
+
"X-Goog-Upload-Header-Content-Length": String(info.sizeBytes),
|
|
278
|
+
"X-Goog-Upload-Header-Content-Type": info.mimeType,
|
|
279
|
+
"Content-Type": "application/json",
|
|
280
|
+
},
|
|
281
|
+
body: JSON.stringify({ file: { display_name: displayName } }),
|
|
282
|
+
signal,
|
|
283
|
+
}, apiKey);
|
|
284
|
+
if (!initRes.ok) {
|
|
285
|
+
const text = redactGeminiApiResponse(initRes, await initRes.text(), apiKey);
|
|
286
|
+
throw new Error(`File upload init failed: ${initRes.status} (${text.slice(0, 200)})`);
|
|
287
|
+
}
|
|
288
|
+
const uploadUrl = initRes.headers.get("x-goog-upload-url");
|
|
289
|
+
if (!uploadUrl)
|
|
290
|
+
throw new Error("No upload URL in response headers");
|
|
291
|
+
const fileData = await readFile(info.absolutePath);
|
|
292
|
+
const uploadRes = await fetchGeminiApi(uploadUrl, {
|
|
293
|
+
method: "PUT",
|
|
294
|
+
headers: {
|
|
295
|
+
"Content-Length": String(info.sizeBytes),
|
|
296
|
+
"X-Goog-Upload-Offset": "0",
|
|
297
|
+
"X-Goog-Upload-Command": "upload, finalize",
|
|
298
|
+
},
|
|
299
|
+
body: fileData,
|
|
300
|
+
signal,
|
|
301
|
+
}, apiKey);
|
|
302
|
+
if (!uploadRes.ok) {
|
|
303
|
+
const text = redactGeminiApiResponse(uploadRes, await uploadRes.text(), apiKey);
|
|
304
|
+
throw new Error(`File upload failed: ${uploadRes.status} (${text.slice(0, 200)})`);
|
|
305
|
+
}
|
|
306
|
+
const result = await uploadRes.json();
|
|
307
|
+
return result.file;
|
|
308
|
+
}
|
|
309
|
+
async function pollFileState(fileName, apiKey, signal, timeoutMs = 120000) {
|
|
310
|
+
const deadline = Date.now() + timeoutMs;
|
|
311
|
+
while (Date.now() < deadline) {
|
|
312
|
+
if (signal?.aborted)
|
|
313
|
+
throw new Error("Aborted");
|
|
314
|
+
const res = await fetchGeminiApi(`${getVersionedApiBase()}/${fileName}`, { signal }, apiKey);
|
|
315
|
+
if (!res.ok)
|
|
316
|
+
throw new Error(`File state check failed: ${res.status}`);
|
|
317
|
+
const data = await res.json();
|
|
318
|
+
if (data.state === "ACTIVE")
|
|
319
|
+
return;
|
|
320
|
+
if (data.state === "FAILED")
|
|
321
|
+
throw new Error("File processing failed");
|
|
322
|
+
await new Promise(r => setTimeout(r, 5000));
|
|
323
|
+
}
|
|
324
|
+
throw new Error("File processing timed out");
|
|
325
|
+
}
|
|
326
|
+
function deleteGeminiFile(fileName, apiKey) {
|
|
327
|
+
void fetchGeminiApi(`${getVersionedApiBase()}/${fileName}`, { method: "DELETE" }, apiKey).catch((err) => {
|
|
328
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
329
|
+
console.error(`Failed to delete Gemini file ${fileName}: ${message}`);
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
function extractVideoTitle(text, filePath) {
|
|
333
|
+
return extractHeadingTitle(text) ?? basename(filePath, extname(filePath));
|
|
334
|
+
}
|
|
335
|
+
//# sourceMappingURL=video-extract.js.map
|