@humain/terminal 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/dist/bundle/chunks/{anthropic-messages-XULXUBIG.js → anthropic-messages-QFCEKGI3.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-JEG2XOYC.js → azure-openai-responses-G4ZMHV37.js} +1 -1
- package/dist/bundle/chunks/chunk-7T6XCLJF.js +22 -0
- package/dist/bundle/chunks/chunk-D6HHRSB5.js +103 -0
- package/dist/bundle/chunks/chunk-EY4DWHQU.js +2 -0
- package/dist/bundle/chunks/{chunk-RM336IEI.js → chunk-I47ZWR55.js} +486 -509
- package/dist/bundle/chunks/{chunk-JUPSJTFQ.js → chunk-K4JAZYQH.js} +1 -1
- package/dist/bundle/chunks/{chunk-HPPQHK3J.js → chunk-KKIB2TVR.js} +1 -1
- package/dist/bundle/chunks/chunk-LI2YVPWP.js +2 -0
- package/dist/bundle/chunks/{chunk-BZQ53VGE.js → chunk-XSR434CO.js} +1 -1
- package/dist/bundle/chunks/compat-QCV26HNS.js +2 -0
- package/dist/bundle/chunks/dist-PRPIUY3U.js +2 -0
- package/dist/bundle/chunks/esm-E7UVEYTO.js +4 -0
- package/dist/bundle/chunks/{extract-TRW5FBY6.js → extract-CTIFQZDJ.js} +15 -14
- package/dist/bundle/chunks/{google-generative-ai-OX6VSCA6.js → google-generative-ai-RSUU4MWO.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-GW76GSS2.js → google-vertex-CKQPOITO.js} +1 -1
- package/dist/bundle/chunks/host-WP3MVKS2.js +2 -0
- package/dist/bundle/chunks/{node-KOIP55YZ.js → node-NF43OPII.js} +1 -1
- package/dist/bundle/chunks/{node-XY3CBY3C.js → node-UMFM7CDZ.js} +1 -1
- package/dist/bundle/chunks/{openai-codex-responses-NPLWP6ZC.js → openai-codex-responses-S34V5ZSD.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-OT2GTJKC.js → openai-completions-T2IGVUEI.js} +1 -1
- package/dist/bundle/chunks/{openai-responses-5A6CR7GI.js → openai-responses-GYZODCT3.js} +1 -1
- package/dist/bundle/chunks/readability-LAGF34IB.js +3 -0
- package/dist/bundle/chunks/turndown.cjs-HRMZVRUL.js +2 -0
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli.js +1 -5
- package/dist/core/agent-session.js +2 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js +21 -8
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/subagent-env.d.ts +18 -0
- package/dist/core/tools/subagent-env.d.ts.map +1 -0
- package/dist/core/tools/subagent-env.js +43 -0
- package/dist/core/tools/subagent-env.js.map +1 -0
- package/dist/core/tools/subagent-scheduler.d.ts +31 -0
- package/dist/core/tools/subagent-scheduler.d.ts.map +1 -0
- package/dist/core/tools/subagent-scheduler.js +203 -0
- package/dist/core/tools/subagent-scheduler.js.map +1 -0
- package/dist/core/tools/subagent.d.ts +83 -3
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js +214 -76
- package/dist/core/tools/subagent.js.map +1 -1
- package/dist/humain/index.d.ts.map +1 -1
- package/dist/humain/index.js +2 -0
- package/dist/humain/index.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/CHANGELOG.md +78 -0
- package/dist/humain/mcp-adapter/vendor/README.md +125 -19
- package/dist/humain/mcp-adapter/vendor/agent-plugin-loader.ts +69 -30
- package/dist/humain/mcp-adapter/vendor/agent-plugin-provenance.ts +36 -0
- package/dist/humain/mcp-adapter/vendor/claude-plugin-loader.ts +365 -0
- package/dist/humain/mcp-adapter/vendor/commands.ts +13 -15
- package/dist/humain/mcp-adapter/vendor/config.ts +198 -30
- package/dist/humain/mcp-adapter/vendor/consent-manager.ts +40 -9
- package/dist/humain/mcp-adapter/vendor/direct-tool-surface.ts +250 -0
- package/dist/humain/mcp-adapter/vendor/direct-tools.ts +9 -228
- package/dist/humain/mcp-adapter/vendor/dist/agent-plugin-loader.js +74 -32
- package/dist/humain/mcp-adapter/vendor/dist/agent-plugin-loader.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/dist/agent-plugin-provenance.d.ts +1 -0
- package/dist/humain/mcp-adapter/vendor/dist/agent-plugin-provenance.js +31 -0
- package/dist/humain/mcp-adapter/vendor/dist/agent-plugin-provenance.js.map +1 -0
- package/dist/humain/mcp-adapter/vendor/dist/claude-plugin-loader.d.ts +9 -0
- package/dist/humain/mcp-adapter/vendor/dist/claude-plugin-loader.js +362 -0
- package/dist/humain/mcp-adapter/vendor/dist/claude-plugin-loader.js.map +1 -0
- package/dist/humain/mcp-adapter/vendor/dist/config.d.ts +3 -1
- package/dist/humain/mcp-adapter/vendor/dist/config.js +189 -27
- package/dist/humain/mcp-adapter/vendor/dist/config.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/dist/metadata-cache.js +7 -16
- package/dist/humain/mcp-adapter/vendor/dist/metadata-cache.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/dist/package-mcp-loader.js +5 -17
- package/dist/humain/mcp-adapter/vendor/dist/package-mcp-loader.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/dist/types.d.ts +30 -4
- package/dist/humain/mcp-adapter/vendor/dist/types.js +26 -0
- package/dist/humain/mcp-adapter/vendor/dist/types.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/dist/utils.d.ts +6 -0
- package/dist/humain/mcp-adapter/vendor/dist/utils.js +65 -6
- package/dist/humain/mcp-adapter/vendor/dist/utils.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/host-html-template.ts +20 -19
- package/dist/humain/mcp-adapter/vendor/http-ca.ts +84 -0
- package/dist/humain/mcp-adapter/vendor/index.bundle.mjs +37102 -15103
- package/dist/humain/mcp-adapter/vendor/index.ts +828 -164
- package/dist/humain/mcp-adapter/vendor/init.ts +48 -10
- package/dist/humain/mcp-adapter/vendor/lazy-loader.ts +7 -0
- package/dist/humain/mcp-adapter/vendor/mcp-auth-fetch.ts +113 -0
- package/dist/humain/mcp-adapter/vendor/mcp-auth-flow.ts +256 -77
- package/dist/humain/mcp-adapter/vendor/mcp-auth.ts +316 -54
- package/dist/humain/mcp-adapter/vendor/mcp-code.ts +45 -18
- package/dist/humain/mcp-adapter/vendor/mcp-install.ts +60 -0
- package/dist/humain/mcp-adapter/vendor/mcp-oauth-provider.ts +70 -6
- package/dist/humain/mcp-adapter/vendor/mcp-output-guard.ts +53 -42
- package/dist/humain/mcp-adapter/vendor/mcp-panel-theme.ts +105 -0
- package/dist/humain/mcp-adapter/vendor/mcp-panel.ts +366 -331
- package/dist/humain/mcp-adapter/vendor/mcp-references.ts +9 -14
- package/dist/humain/mcp-adapter/vendor/mcp-script-worker.mjs +3 -1
- package/dist/humain/mcp-adapter/vendor/mcp-setup-panel.ts +383 -341
- package/dist/humain/mcp-adapter/vendor/mcp-status.ts +5 -0
- package/dist/humain/mcp-adapter/vendor/metadata-cache.ts +7 -16
- package/dist/humain/mcp-adapter/vendor/namespace-tools.ts +61 -3
- package/dist/humain/mcp-adapter/vendor/oauth.ts +6 -2
- package/dist/humain/mcp-adapter/vendor/package-mcp-loader.ts +5 -17
- package/dist/humain/mcp-adapter/vendor/package.json +13 -3
- package/dist/humain/mcp-adapter/vendor/prompts.ts +35 -3
- package/dist/humain/mcp-adapter/vendor/proxy-modes.ts +108 -7
- package/dist/humain/mcp-adapter/vendor/runtime-owner.ts +16 -1
- package/dist/humain/mcp-adapter/vendor/sampling-handler.ts +9 -32
- package/dist/humain/mcp-adapter/vendor/sandbox-proxy-template.ts +20 -93
- package/dist/humain/mcp-adapter/vendor/server-manager.ts +227 -40
- package/dist/humain/mcp-adapter/vendor/session-approvals.ts +187 -0
- package/dist/humain/mcp-adapter/vendor/skills/mcp-scripting/SKILL.md +9 -1
- package/dist/humain/mcp-adapter/vendor/state.ts +10 -1
- package/dist/humain/mcp-adapter/vendor/tool-approval.ts +10 -22
- package/dist/humain/mcp-adapter/vendor/tool-metadata.ts +14 -0
- package/dist/humain/mcp-adapter/vendor/types.ts +57 -4
- package/dist/humain/mcp-adapter/vendor/ui-server.ts +36 -28
- package/dist/humain/mcp-adapter/vendor/utils.ts +64 -6
- package/dist/humain/node-http.d.ts +3 -0
- package/dist/humain/node-http.d.ts.map +1 -0
- package/dist/humain/node-http.js +119 -0
- package/dist/humain/node-http.js.map +1 -0
- package/dist/humain/node-provider.d.ts +4 -0
- package/dist/humain/node-provider.d.ts.map +1 -0
- package/dist/humain/node-provider.js +359 -0
- package/dist/humain/node-provider.js.map +1 -0
- package/dist/humain/web-access/vendor/abortable.d.ts +3 -0
- package/dist/humain/web-access/vendor/abortable.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/abortable.js +22 -0
- package/dist/humain/web-access/vendor/abortable.js.map +1 -0
- package/dist/humain/web-access/vendor/crawl4ai.d.ts +9 -0
- package/dist/humain/web-access/vendor/crawl4ai.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/crawl4ai.js +187 -0
- package/dist/humain/web-access/vendor/crawl4ai.js.map +1 -0
- package/dist/humain/web-access/vendor/credential-source.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/credential-source.js +1 -0
- package/dist/humain/web-access/vendor/credential-source.js.map +1 -1
- package/dist/humain/web-access/vendor/curator-page.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/curator-page.js +20 -2
- package/dist/humain/web-access/vendor/curator-page.js.map +1 -1
- package/dist/humain/web-access/vendor/curator-run.d.ts +11 -0
- package/dist/humain/web-access/vendor/curator-run.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/curator-run.js +38 -0
- package/dist/humain/web-access/vendor/curator-run.js.map +1 -0
- package/dist/humain/web-access/vendor/curator-server.d.ts +1 -0
- package/dist/humain/web-access/vendor/curator-server.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/curator-server.js +2 -0
- package/dist/humain/web-access/vendor/curator-server.js.map +1 -1
- package/dist/humain/web-access/vendor/duckduckgo.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/duckduckgo.js +1 -1
- package/dist/humain/web-access/vendor/duckduckgo.js.map +1 -1
- package/dist/humain/web-access/vendor/extract.d.ts +1 -1
- package/dist/humain/web-access/vendor/extract.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/extract.js +58 -11
- package/dist/humain/web-access/vendor/extract.js.map +1 -1
- package/dist/humain/web-access/vendor/fetch-params.js +1 -1
- package/dist/humain/web-access/vendor/fetch-params.js.map +1 -1
- package/dist/humain/web-access/vendor/gemini-search.d.ts +2 -2
- package/dist/humain/web-access/vendor/gemini-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/gemini-search.js +12 -5
- package/dist/humain/web-access/vendor/gemini-search.js.map +1 -1
- package/dist/humain/web-access/vendor/index.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/index.js +23 -19
- package/dist/humain/web-access/vendor/index.js.map +1 -1
- package/dist/humain/web-access/vendor/openai-search.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/openai-search.js +40 -14
- package/dist/humain/web-access/vendor/openai-search.js.map +1 -1
- package/dist/humain/web-access/vendor/page-query.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/page-query.js +6 -2
- package/dist/humain/web-access/vendor/page-query.js.map +1 -1
- package/dist/humain/web-access/vendor/query-rewrite.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/query-rewrite.js +6 -2
- package/dist/humain/web-access/vendor/query-rewrite.js.map +1 -1
- package/dist/humain/web-access/vendor/serpapi.d.ts +4 -0
- package/dist/humain/web-access/vendor/serpapi.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/serpapi.js +215 -0
- package/dist/humain/web-access/vendor/serpapi.js.map +1 -0
- package/dist/humain/web-access/vendor/ssrf-protection.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/ssrf-protection.js +5 -1
- package/dist/humain/web-access/vendor/ssrf-protection.js.map +1 -1
- package/dist/humain/web-access/vendor/storage.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/storage.js +9 -0
- package/dist/humain/web-access/vendor/storage.js.map +1 -1
- package/dist/humain/web-access/vendor/summary-review.d.ts +1 -1
- package/dist/humain/web-access/vendor/summary-review.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/summary-review.js +35 -24
- package/dist/humain/web-access/vendor/summary-review.js.map +1 -1
- package/dist/humain/web-access/vendor/utils.d.ts.map +1 -1
- package/dist/humain/web-access/vendor/utils.js +5 -3
- package/dist/humain/web-access/vendor/utils.js.map +1 -1
- package/dist/index.js +1 -51
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +16 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +7 -2
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +46 -21
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +10 -13
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/json-event.d.ts +8 -0
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js +17 -0
- package/dist/modes/json-event.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +3 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/docs/environment-variables.md +8 -0
- package/docs/humain-terminal.md +6 -0
- package/docs/json.md +16 -0
- package/docs/providers.md +19 -1
- package/npm-shrinkwrap.json +6 -6
- package/package.json +2 -2
- package/src/humain/mcp-adapter/UPSTREAM.md +56 -7
- package/src/humain/mcp-adapter/upstream.json +6 -4
- package/src/humain/mcp-adapter/vendor/CHANGELOG.md +78 -0
- package/src/humain/web-access/UPSTREAM.md +18 -8
- package/src/humain/web-access/upstream.json +6 -5
- package/dist/bundle/chunks/chunk-2LC3S3VV.js +0 -105
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-provider.js","sourceRoot":"","sources":["../../src/humain/node-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { setTimeout as delay } from \"node:timers/promises\";\nimport {\n\ttype Api,\n\ttype ApiKeyAuth,\n\ttype ApiKeyCredential,\n\ttype AuthContext,\n\ttype AuthResult,\n\tcreateProvider,\n\ttype Model,\n\ttype Provider,\n\ttype RefreshModelsContext,\n} from \"@earendil-works/pi-ai\";\nimport { anthropicMessagesApi } from \"@earendil-works/pi-ai/api/anthropic-messages.lazy\";\nimport { openAICompletionsApi } from \"@earendil-works/pi-ai/api/openai-completions.lazy\";\nimport { openAIResponsesApi } from \"@earendil-works/pi-ai/api/openai-responses.lazy\";\nimport { withHumainNodeHttp } from \"./node-http.ts\";\n\nexport const HUMAIN_NODE_PROVIDER = \"humain-node\";\n\nconst DEFAULT_BASE_URL = \"https://api.node.humain.com/v1\";\nconst API_KEY_ENV = \"HUMAIN_NODE_API_KEY\";\nconst BASE_URL_ENV = \"HUMAIN_NODE_BASE_URL\";\nconst RETRYABLE_STATUS_CODES = new Set([408, 425, 429, 500, 502, 503, 504]);\nconst PERMANENT_LIMIT_CODES = new Set([\n\t\"billing_hard_limit_reached\",\n\t\"insufficient_quota\",\n\t\"partner_credit_limit_exceeded\",\n\t\"quota_exceeded\",\n\t\"weekly_cap_exceeded\",\n]);\nconst REQUEST_TIMEOUT_MS = 5_000;\nconst MAX_RETRIES = 2;\nconst MAX_RETRY_DELAY_MS = 2_000;\nconst ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\n\ninterface NodeModelPayload {\n\tid: unknown;\n\tname?: unknown;\n\tdisplay_name?: unknown;\n\tnode: {\n\t\tapi_interface?: unknown;\n\t\tsupported_formats?: unknown;\n\t\tmax_context_tokens?: unknown;\n\t\tmax_output_tokens?: unknown;\n\t\tsupports_streaming?: unknown;\n\t\tsupports_function_calling?: unknown;\n\t\tsupports_images?: unknown;\n\t};\n}\n\ninterface NodeErrorPayload {\n\terror?: { code?: unknown; type?: unknown; message?: unknown };\n}\n\nfunction normalizeBaseUrl(value: string): string {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(value.trim());\n\t} catch {\n\t\tthrow new Error(\"Invalid HUMAIN Node base URL\");\n\t}\n\tconst local = url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\" || url.hostname === \"[::1]\";\n\tif (url.protocol !== \"https:\" && !(local && url.protocol === \"http:\")) {\n\t\tthrow new Error(\"HUMAIN Node base URL must use HTTPS (HTTP is allowed only for localhost)\");\n\t}\n\tif (url.username || url.password || url.search || url.hash) {\n\t\tthrow new Error(\"HUMAIN Node base URL must not contain credentials, a query, or a fragment\");\n\t}\n\turl.pathname = url.pathname.replace(/\\/+$/u, \"\") || \"/\";\n\treturn url.toString().replace(/\\/$/u, \"\");\n}\n\nfunction credentialBaseUrl(credential: ApiKeyCredential | undefined): string | undefined {\n\tconst value = credential?.env?.[BASE_URL_ENV];\n\treturn typeof value === \"string\" && value.trim() ? normalizeBaseUrl(value) : undefined;\n}\n\nasync function resolveBaseUrl(ctx: AuthContext, credential?: ApiKeyCredential): Promise<string> {\n\treturn credentialBaseUrl(credential) ?? normalizeBaseUrl((await ctx.env(BASE_URL_ENV)) ?? DEFAULT_BASE_URL);\n}\n\nfunction endpointApi(value: string): Api | undefined {\n\tconst normalized = value\n\t\t.trim()\n\t\t.toLowerCase()\n\t\t.replace(/^https?:\\/\\/[^/]+/u, \"\")\n\t\t.replace(/\\/+$/u, \"\");\n\tswitch (normalized) {\n\t\tcase \"responses\":\n\t\tcase \"/responses\":\n\t\tcase \"openai-responses\":\n\t\tcase \"openai_responses\":\n\t\t\treturn \"openai-responses\";\n\t\tcase \"chat/completions\":\n\t\tcase \"/chat/completions\":\n\t\tcase \"chat-completions\":\n\t\tcase \"chat_completions\":\n\t\tcase \"openai-completions\":\n\t\tcase \"openai_chat_completions\":\n\t\t\treturn \"openai-completions\";\n\t\tcase \"messages\":\n\t\tcase \"/messages\":\n\t\tcase \"anthropic-messages\":\n\t\tcase \"anthropic_messages\":\n\t\t\treturn \"anthropic-messages\";\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nfunction modelApi(id: string, node: NodeModelPayload[\"node\"]): Api {\n\tif (typeof node.api_interface === \"string\") {\n\t\tconst primary = endpointApi(node.api_interface);\n\t\tif (primary) return primary;\n\t}\n\tconst supported = Array.isArray(node.supported_formats)\n\t\t? node.supported_formats.flatMap((value) => (typeof value === \"string\" ? (endpointApi(value) ?? []) : []))\n\t\t: [];\n\tfor (const preferred of [\"openai-responses\", \"openai-completions\", \"anthropic-messages\"] as const) {\n\t\tif (supported.includes(preferred)) return preferred;\n\t}\n\tconst primary = typeof node.api_interface === \"string\" ? node.api_interface : \"missing\";\n\tthrow new Error(`HUMAIN Node model \"${id}\" has an unsupported API interface: ${primary}`);\n}\n\nfunction positiveInteger(value: unknown, field: string, id: string): number {\n\tif (typeof value !== \"number\" || !Number.isSafeInteger(value) || value <= 0) {\n\t\tthrow new Error(`HUMAIN Node model \"${id}\" has invalid ${field}`);\n\t}\n\treturn value;\n}\n\nfunction toModel(value: unknown, baseUrl: string): Model<Api> | undefined {\n\tif (typeof value !== \"object\" || value === null || !(\"id\" in value)) {\n\t\tthrow new Error(\"HUMAIN Node returned a malformed model entry\");\n\t}\n\tconst raw = value as Record<string, unknown>;\n\tif (raw.active === false) return undefined;\n\tconst node = typeof raw.node === \"object\" && raw.node !== null ? raw.node : raw;\n\tconst payload = { ...raw, node } as unknown as NodeModelPayload;\n\tif (typeof payload.id !== \"string\" || !payload.id.trim()) {\n\t\tthrow new Error(\"HUMAIN Node returned a malformed model entry\");\n\t}\n\tconst id = payload.id.trim();\n\tif (typeof payload.node.supports_streaming !== \"boolean\") {\n\t\tthrow new Error(`HUMAIN Node model \"${id}\" has invalid supports_streaming`);\n\t}\n\tif (typeof payload.node.supports_function_calling !== \"boolean\") {\n\t\tthrow new Error(`HUMAIN Node model \"${id}\" has invalid supports_function_calling`);\n\t}\n\tif (payload.node.supports_streaming === false || payload.node.supports_function_calling === false) return undefined;\n\tlet api: Api;\n\ttry {\n\t\tapi = modelApi(id, payload.node);\n\t} catch (error) {\n\t\tif (payload.node.api_interface === \"image_generations\" || payload.node.api_interface === \"realtime\")\n\t\t\treturn undefined;\n\t\tthrow error;\n\t}\n\tconst contextWindow = payload.node.max_context_tokens;\n\tconst maxTokens = payload.node.max_output_tokens;\n\tif (contextWindow === null || maxTokens === null || contextWindow === 0 || maxTokens === 0) return undefined;\n\treturn {\n\t\tid,\n\t\tname:\n\t\t\ttypeof payload.display_name === \"string\" && payload.display_name.trim()\n\t\t\t\t? payload.display_name.trim()\n\t\t\t\t: typeof payload.name === \"string\" && payload.name.trim()\n\t\t\t\t\t? payload.name.trim()\n\t\t\t\t\t: id,\n\t\tapi,\n\t\tprovider: HUMAIN_NODE_PROVIDER,\n\t\tbaseUrl,\n\t\treasoning: false,\n\t\tinput: payload.node.supports_images === true ? [\"text\", \"image\"] : [\"text\"],\n\t\tcost: ZERO_COST,\n\t\tcontextWindow: positiveInteger(contextWindow, \"max_context_tokens\", id),\n\t\tmaxTokens: positiveInteger(maxTokens, \"max_output_tokens\", id),\n\t\t...(api === \"openai-completions\"\n\t\t\t? {\n\t\t\t\t\tcompat: {\n\t\t\t\t\t\tsupportsStore: false,\n\t\t\t\t\t\tsupportsDeveloperRole: false,\n\t\t\t\t\t\tsupportsReasoningEffort: false,\n\t\t\t\t\t\tsupportsUsageInStreaming: true,\n\t\t\t\t\t\tsupportsStrictMode: false,\n\t\t\t\t\t\tsupportsLongCacheRetention: false,\n\t\t\t\t\t\tmaxTokensField: \"max_tokens\" as const,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\n\nfunction retryDelay(response: Response, attempt: number): number | undefined {\n\tconst retryAfter = response.headers.get(\"retry-after\");\n\tif (retryAfter) {\n\t\tconst seconds = Number(retryAfter);\n\t\tconst delay = Number.isFinite(seconds) ? seconds * 1_000 : Date.parse(retryAfter) - Date.now();\n\t\tif (Number.isFinite(delay)) {\n\t\t\tconst bounded = Math.max(0, delay);\n\t\t\treturn bounded <= MAX_RETRY_DELAY_MS ? bounded : undefined;\n\t\t}\n\t}\n\treturn 100 * 2 ** attempt;\n}\n\nfunction errorDetails(response: Response, payload: NodeErrorPayload): { code?: string; message: string } {\n\tconst error = payload.error;\n\tconst code = typeof error?.code === \"string\" ? error.code : undefined;\n\tconst type = typeof error?.type === \"string\" ? error.type : undefined;\n\tconst detail = typeof error?.message === \"string\" ? error.message : undefined;\n\tconst retryAfter = response.headers.get(\"retry-after\");\n\tconst requestId = response.headers.get(\"x-request-id\");\n\treturn {\n\t\tcode,\n\t\tmessage: [\n\t\t\t`HUMAIN Node model discovery failed: ${response.status}`,\n\t\t\tcode && `code=${code}`,\n\t\t\ttype && `type=${type}`,\n\t\t\tdetail,\n\t\t\tretryAfter && `Retry-After: ${retryAfter}`,\n\t\t\trequestId && `X-Request-ID: ${requestId}`,\n\t\t]\n\t\t\t.filter(Boolean)\n\t\t\t.join(\"; \"),\n\t};\n}\n\nasync function fetchModelsUnredacted(baseUrl: string, apiKey: string, signal: AbortSignal): Promise<Model<Api>[]> {\n\tfor (let attempt = 0; ; attempt++) {\n\t\tsignal.throwIfAborted();\n\t\tconst attemptSignal = AbortSignal.any([signal, AbortSignal.timeout(REQUEST_TIMEOUT_MS)]);\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await fetch(new URL(`${baseUrl}/models`), {\n\t\t\t\tsignal: attemptSignal,\n\t\t\t\tredirect: \"error\",\n\t\t\t\theaders: { Accept: \"application/json\", Authorization: `Bearer ${apiKey}` },\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (signal.aborted || attempt >= MAX_RETRIES) throw error;\n\t\t\tawait delay(100 * 2 ** attempt, undefined, { signal });\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst payload: unknown = await response.json().catch(() => ({}));\n\t\tif (!response.ok) {\n\t\t\tconst details = errorDetails(\n\t\t\t\tresponse,\n\t\t\t\ttypeof payload === \"object\" && payload !== null ? (payload as NodeErrorPayload) : {},\n\t\t\t);\n\t\t\tconst retryMs = retryDelay(response, attempt);\n\t\t\tif (\n\t\t\t\tattempt < MAX_RETRIES &&\n\t\t\t\tRETRYABLE_STATUS_CODES.has(response.status) &&\n\t\t\t\t!PERMANENT_LIMIT_CODES.has(details.code ?? \"\") &&\n\t\t\t\tretryMs !== undefined\n\t\t\t) {\n\t\t\t\tawait delay(retryMs, undefined, { signal });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new Error(details.message);\n\t\t}\n\t\tif (typeof payload !== \"object\" || payload === null) {\n\t\t\tthrow new Error(\"HUMAIN Node returned a malformed model catalog\");\n\t\t}\n\t\tconst entries =\n\t\t\t\"data\" in payload && Array.isArray(payload.data)\n\t\t\t\t? payload.data\n\t\t\t\t: \"items\" in payload && Array.isArray(payload.items)\n\t\t\t\t\t? payload.items\n\t\t\t\t\t: undefined;\n\t\tif (!entries) throw new Error(\"HUMAIN Node returned a malformed model catalog\");\n\t\tconst ids = new Set<string>();\n\t\tfor (const entry of entries) {\n\t\t\tif (typeof entry !== \"object\" || entry === null || !(\"id\" in entry) || typeof entry.id !== \"string\") continue;\n\t\t\tconst id = entry.id.trim();\n\t\t\tif (ids.has(id)) throw new Error(`HUMAIN Node returned duplicate model id \"${id}\"`);\n\t\t\tids.add(id);\n\t\t}\n\t\treturn entries.flatMap((entry) => toModel(entry, baseUrl) ?? []);\n\t}\n}\n\nasync function fetchModels(baseUrl: string, apiKey: string, signal: AbortSignal): Promise<Model<Api>[]> {\n\ttry {\n\t\treturn await fetchModelsUnredacted(baseUrl, apiKey, signal);\n\t} catch (error) {\n\t\tif (signal.aborted) throw signal.reason;\n\t\tconst message = (error instanceof Error ? error.message : String(error)).replaceAll(apiKey, \"[redacted]\");\n\t\tconst redacted = new Error(message);\n\t\tif (error instanceof Error) redacted.name = error.name;\n\t\tthrow redacted;\n\t}\n}\n\nexport function createHumainNodeProvider(env: NodeJS.ProcessEnv = process.env): Provider {\n\tlet models: readonly Model<Api>[] = [];\n\tlet activeScope: string | undefined;\n\tconst apiKeyAuth: ApiKeyAuth = {\n\t\tname: \"HUMAIN Node API key\",\n\t\tlogin: async (interaction) => {\n\t\t\tif (!env[API_KEY_ENV]?.trim()) {\n\t\t\t\tinteraction.notify({\n\t\t\t\t\ttype: \"info\",\n\t\t\t\t\tmessage: \"Create a HUMAIN Node API key in Node Users, then paste it below.\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst enteredKey = (\n\t\t\t\tawait interaction.prompt({\n\t\t\t\t\ttype: \"secret\",\n\t\t\t\t\tmessage: \"Enter HUMAIN Node API key (leave blank to use HUMAIN_NODE_API_KEY)\",\n\t\t\t\t})\n\t\t\t).trim();\n\t\t\tconst key = enteredKey || env[API_KEY_ENV]?.trim();\n\t\t\tif (!key) throw new Error(\"HUMAIN Node API key is required\");\n\t\t\tconst enteredUrl = await interaction.prompt({\n\t\t\t\ttype: \"text\",\n\t\t\t\tmessage: \"HUMAIN Node base URL\",\n\t\t\t\tplaceholder: env[BASE_URL_ENV] ?? DEFAULT_BASE_URL,\n\t\t\t});\n\t\t\tconst baseUrl = normalizeBaseUrl(enteredUrl.trim() || env[BASE_URL_ENV] || DEFAULT_BASE_URL);\n\t\t\tawait fetchModels(baseUrl, key, interaction.signal);\n\t\t\treturn {\n\t\t\t\ttype: \"api_key\" as const,\n\t\t\t\tkey: enteredKey.replaceAll(\"$\", () => \"$$\").replace(/^!/u, () => \"$!\") || undefined,\n\t\t\t\tenv: { [BASE_URL_ENV]: baseUrl },\n\t\t\t};\n\t\t},\n\t\tcheck: async ({ ctx, credential, signal }) => {\n\t\t\tsignal.throwIfAborted();\n\t\t\tconst key = credential?.key ?? (await ctx.env(API_KEY_ENV));\n\t\t\treturn key\n\t\t\t\t? { type: \"api_key\" as const, source: credential?.key ? \"stored credential\" : API_KEY_ENV }\n\t\t\t\t: undefined;\n\t\t},\n\t\tresolve: async ({ ctx, credential, signal }): Promise<AuthResult | undefined> => {\n\t\t\tsignal.throwIfAborted();\n\t\t\tconst key = credential?.key ?? (await ctx.env(API_KEY_ENV));\n\t\t\tif (!key) return undefined;\n\t\t\tconst baseUrl = await resolveBaseUrl(ctx, credential);\n\t\t\treturn {\n\t\t\t\tauth: { apiKey: key, baseUrl },\n\t\t\t\tenv: { ...credential?.env, [BASE_URL_ENV]: baseUrl },\n\t\t\t\tsource: credential?.key ? \"stored credential\" : API_KEY_ENV,\n\t\t\t};\n\t\t},\n\t};\n\tconst base = createProvider({\n\t\tid: HUMAIN_NODE_PROVIDER,\n\t\tname: \"HUMAIN Node\",\n\t\tbaseUrl: DEFAULT_BASE_URL,\n\t\tauth: { apiKey: apiKeyAuth },\n\t\tmodels: [],\n\t\tapi: {\n\t\t\t\"anthropic-messages\": withHumainNodeHttp(anthropicMessagesApi()),\n\t\t\t\"openai-completions\": withHumainNodeHttp(openAICompletionsApi()),\n\t\t\t\"openai-responses\": withHumainNodeHttp(openAIResponsesApi()),\n\t\t},\n\t});\n\treturn {\n\t\t...base,\n\t\tgetModels: () => models,\n\t\trefreshModels: async (context: RefreshModelsContext) => {\n\t\t\tconst credential = context.credential?.type === \"api_key\" ? context.credential : undefined;\n\t\t\tconst key = credential?.key;\n\t\t\tconst baseUrl = credential ? (credentialBaseUrl(credential) ?? DEFAULT_BASE_URL) : undefined;\n\t\t\tconst scope = key && baseUrl ? `${baseUrl}\\0${key}` : undefined;\n\t\t\tif (scope !== activeScope) {\n\t\t\t\tif (\n\t\t\t\t\t!(await context.publish({\n\t\t\t\t\t\tpersist: null,\n\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\tmodels = [];\n\t\t\t\t\t\t\tactiveScope = scope;\n\t\t\t\t\t\t},\n\t\t\t\t\t}))\n\t\t\t\t)\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!context.allowNetwork || context.signal.aborted || !key || !baseUrl) return;\n\t\t\tconst refreshed = await fetchModels(baseUrl, key, context.signal);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tawait context.publish({\n\t\t\t\tpersist: null,\n\t\t\t\tupdate: () => {\n\t\t\t\t\tmodels = refreshed;\n\t\t\t\t\tactiveScope = scope;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abortable.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/abortable.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,wBAAsB,cAAc,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAe/F"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Observe cancellation while awaiting work that cannot itself be cancelled (such as import()). */
|
|
2
|
+
export async function awaitWithAbort(operation, signal) {
|
|
3
|
+
if (!signal)
|
|
4
|
+
return operation;
|
|
5
|
+
let onAbort = () => { };
|
|
6
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
7
|
+
onAbort = () => reject(new Error("Aborted"));
|
|
8
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
9
|
+
if (signal.aborted)
|
|
10
|
+
onAbort();
|
|
11
|
+
});
|
|
12
|
+
try {
|
|
13
|
+
const result = await Promise.race([operation, aborted]);
|
|
14
|
+
if (signal.aborted)
|
|
15
|
+
throw new Error("Aborted");
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
signal.removeEventListener("abort", onAbort);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=abortable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abortable.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/abortable.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,MAAM,CAAC,KAAK,UAAU,cAAc,CAAI,SAAqB,EAAE,MAAoB;IAClF,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,IAAI,OAAO,GAAe,GAAG,EAAE,GAAE,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;QACvD,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IACH,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QACxD,IAAI,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;QAC/C,OAAO,MAAM,CAAC;IACf,CAAC;YAAS,CAAC;QACV,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;AACF,CAAC","sourcesContent":["/** Observe cancellation while awaiting work that cannot itself be cancelled (such as import()). */\nexport async function awaitWithAbort<T>(operation: Promise<T>, signal?: AbortSignal): Promise<T> {\n\tif (!signal) return operation;\n\tlet onAbort: () => void = () => {};\n\tconst aborted = new Promise<never>((_resolve, reject) => {\n\t\tonAbort = () => reject(new Error(\"Aborted\"));\n\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\tif (signal.aborted) onAbort();\n\t});\n\ttry {\n\t\tconst result = await Promise.race([operation, aborted]);\n\t\tif (signal.aborted) throw new Error(\"Aborted\");\n\t\treturn result;\n\t} finally {\n\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ExtractedContent, ExtractOptions } from "./extract.ts";
|
|
2
|
+
import { type SsrfConfig } from "./ssrf-protection.ts";
|
|
3
|
+
export interface Crawl4aiExtractOptions extends Pick<ExtractOptions, "timeoutMs" | "lookup"> {
|
|
4
|
+
ssrf?: SsrfConfig;
|
|
5
|
+
}
|
|
6
|
+
export declare function clearCrawl4aiConfigCache(): void;
|
|
7
|
+
export declare function isCrawl4aiAvailable(): boolean;
|
|
8
|
+
export declare function extractWithCrawl4ai(url: string, signal?: AbortSignal, options?: Crawl4aiExtractOptions): Promise<ExtractedContent | null>;
|
|
9
|
+
//# sourceMappingURL=crawl4ai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crawl4ai.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/crawl4ai.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAkE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAOvH,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,QAAQ,CAAC;IAC3F,IAAI,CAAC,EAAE,UAAU,CAAC;CAClB;AA8BD,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAgFD,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED,wBAAsB,mBAAmB,CACxC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,sBAAsB,GAC9B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAqElC"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import net from "node:net";
|
|
3
|
+
import { activityMonitor } from "./activity.js";
|
|
4
|
+
import { redactCredential, resolveCredential } from "./credential-source.js";
|
|
5
|
+
import { fetchRemoteUrl, loadSsrfConfig, validateRemoteUrl } from "./ssrf-protection.js";
|
|
6
|
+
import { getWebSearchConfigPath } from "./utils.js";
|
|
7
|
+
const CONFIG_PATH = getWebSearchConfigPath();
|
|
8
|
+
const EXTRACT_TIMEOUT_MS = 60_000;
|
|
9
|
+
const MARKDOWN_FILTER = "fit";
|
|
10
|
+
let cachedConfig = null;
|
|
11
|
+
function loadConfig() {
|
|
12
|
+
if (cachedConfig)
|
|
13
|
+
return cachedConfig;
|
|
14
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
15
|
+
cachedConfig = {};
|
|
16
|
+
return cachedConfig;
|
|
17
|
+
}
|
|
18
|
+
const raw = readFileSync(CONFIG_PATH, "utf8");
|
|
19
|
+
let parsed;
|
|
20
|
+
try {
|
|
21
|
+
parsed = JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
25
|
+
throw new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);
|
|
26
|
+
}
|
|
27
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
28
|
+
throw new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);
|
|
29
|
+
}
|
|
30
|
+
cachedConfig = parsed;
|
|
31
|
+
return cachedConfig;
|
|
32
|
+
}
|
|
33
|
+
export function clearCrawl4aiConfigCache() {
|
|
34
|
+
cachedConfig = null;
|
|
35
|
+
}
|
|
36
|
+
function normalizeBaseUrl(value) {
|
|
37
|
+
if (typeof value !== "string")
|
|
38
|
+
return null;
|
|
39
|
+
const trimmed = value.trim();
|
|
40
|
+
if (!trimmed)
|
|
41
|
+
return null;
|
|
42
|
+
let parsed;
|
|
43
|
+
try {
|
|
44
|
+
parsed = new URL(trimmed);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
throw new Error(`Invalid Crawl4AI base URL in ${CONFIG_PATH}: expected an HTTP or HTTPS URL`);
|
|
48
|
+
}
|
|
49
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
50
|
+
throw new Error(`Invalid Crawl4AI base URL in ${CONFIG_PATH}: expected an HTTP or HTTPS URL`);
|
|
51
|
+
}
|
|
52
|
+
if (parsed.username || parsed.password) {
|
|
53
|
+
throw new Error(`Invalid Crawl4AI base URL in ${CONFIG_PATH}: URL credentials are not allowed`);
|
|
54
|
+
}
|
|
55
|
+
parsed.pathname = parsed.pathname.replace(/\/+$/, "");
|
|
56
|
+
parsed.search = "";
|
|
57
|
+
parsed.hash = "";
|
|
58
|
+
return parsed.toString().replace(/\/+$/, "");
|
|
59
|
+
}
|
|
60
|
+
function getBaseUrl() {
|
|
61
|
+
return normalizeBaseUrl(process.env.CRAWL4AI_BASE_URL) ?? normalizeBaseUrl(loadConfig().crawl4aiBaseUrl);
|
|
62
|
+
}
|
|
63
|
+
function requireBaseUrl() {
|
|
64
|
+
const baseUrl = getBaseUrl();
|
|
65
|
+
if (!baseUrl) {
|
|
66
|
+
throw new Error("Crawl4AI base URL not configured. Either:\n" +
|
|
67
|
+
` 1. Set crawl4aiBaseUrl in ${CONFIG_PATH}\n` +
|
|
68
|
+
" 2. Set CRAWL4AI_BASE_URL environment variable");
|
|
69
|
+
}
|
|
70
|
+
return baseUrl;
|
|
71
|
+
}
|
|
72
|
+
async function getApiToken(signal) {
|
|
73
|
+
return resolveCredential({
|
|
74
|
+
provider: "Crawl4AI",
|
|
75
|
+
configuredValue: loadConfig().crawl4aiApiToken,
|
|
76
|
+
environmentValue: process.env.CRAWL4AI_API_TOKEN,
|
|
77
|
+
signal,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function requestSignal(timeoutMs, signal) {
|
|
81
|
+
const timeout = AbortSignal.timeout(timeoutMs);
|
|
82
|
+
return signal ? AbortSignal.any([timeout, signal]) : timeout;
|
|
83
|
+
}
|
|
84
|
+
function errorMessage(err) {
|
|
85
|
+
return err instanceof Error ? err.message : String(err);
|
|
86
|
+
}
|
|
87
|
+
function isAbortException(err) {
|
|
88
|
+
return err instanceof DOMException && (err.name === "AbortError" || err.name === "TimeoutError");
|
|
89
|
+
}
|
|
90
|
+
function ssrfOptions(options) {
|
|
91
|
+
return {
|
|
92
|
+
...(options?.ssrf ?? loadSsrfConfig()),
|
|
93
|
+
...(options?.lookup ? { lookup: options.lookup } : {}),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function isLoopbackApiUrl(url) {
|
|
97
|
+
const hostname = url.hostname.toLowerCase().replace(/^\[|\]$/g, "").replace(/\.$/, "");
|
|
98
|
+
if (hostname === "localhost" || hostname === "::1")
|
|
99
|
+
return true;
|
|
100
|
+
if (net.isIP(hostname) !== 4)
|
|
101
|
+
return false;
|
|
102
|
+
return hostname.split(".")[0] === "127";
|
|
103
|
+
}
|
|
104
|
+
function firstHeadingTitle(markdown) {
|
|
105
|
+
return /^[ \t]*#[ \t]+(\S.*?)[ \t\r]*$/m.exec(markdown)?.[1] ?? "";
|
|
106
|
+
}
|
|
107
|
+
export function isCrawl4aiAvailable() {
|
|
108
|
+
return getBaseUrl() !== null;
|
|
109
|
+
}
|
|
110
|
+
export async function extractWithCrawl4ai(url, signal, options) {
|
|
111
|
+
const baseUrl = requireBaseUrl();
|
|
112
|
+
const ssrf = ssrfOptions(options);
|
|
113
|
+
await validateRemoteUrl(url, ssrf);
|
|
114
|
+
const token = await getApiToken(signal);
|
|
115
|
+
const headers = { "Content-Type": "application/json" };
|
|
116
|
+
if (token)
|
|
117
|
+
headers.Authorization = `Bearer ${token}`;
|
|
118
|
+
const requestUrl = new URL(`${baseUrl}/md`);
|
|
119
|
+
const init = {
|
|
120
|
+
method: "POST",
|
|
121
|
+
headers,
|
|
122
|
+
body: JSON.stringify({ url, f: MARKDOWN_FILTER }),
|
|
123
|
+
signal: requestSignal(options?.timeoutMs ?? EXTRACT_TIMEOUT_MS, signal),
|
|
124
|
+
};
|
|
125
|
+
let seeOther = false;
|
|
126
|
+
const activityId = activityMonitor.logStart({ type: "fetch", url: requestUrl.toString() });
|
|
127
|
+
try {
|
|
128
|
+
const response = await fetchRemoteUrl(requestUrl, init, {
|
|
129
|
+
...ssrf,
|
|
130
|
+
allowLoopback: isLoopbackApiUrl(requestUrl),
|
|
131
|
+
onRedirect: ({ to, init: redirectInit, response }) => {
|
|
132
|
+
if (to.origin !== requestUrl.origin) {
|
|
133
|
+
throw new Error(`Crawl4AI refused cross-origin redirect to ${to.origin}`);
|
|
134
|
+
}
|
|
135
|
+
// 303 genuinely means "GET the other resource", and it is final: once a hop has turned the
|
|
136
|
+
// chain into a GET, no later hop may resurrect the extraction body.
|
|
137
|
+
if (response.status === 303)
|
|
138
|
+
seeOther = true;
|
|
139
|
+
// 301/302 are the hops a reverse proxy in front of a self-hosted instance actually emits, and
|
|
140
|
+
// fetchRemoteUrl turns those into a bodyless GET that /md cannot serve, so replay the POST.
|
|
141
|
+
// 307/308 already keep the method, so their init needs no help.
|
|
142
|
+
const replayPost = !seeOther && (response.status === 301 || response.status === 302);
|
|
143
|
+
return replayPost ? init : redirectInit;
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
if (!response.ok) {
|
|
147
|
+
const text = await response.text().catch(() => "");
|
|
148
|
+
throw new Error(`Crawl4AI md error ${response.status}: ${redactCredential(text, token).slice(0, 300)}`);
|
|
149
|
+
}
|
|
150
|
+
let data;
|
|
151
|
+
try {
|
|
152
|
+
data = await response.json();
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// The parser message quotes the offending body, which can echo the configured token, so it never
|
|
156
|
+
// reaches the thrown error or the activity log.
|
|
157
|
+
throw new Error("Crawl4AI md returned invalid JSON");
|
|
158
|
+
}
|
|
159
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
160
|
+
throw new Error("Crawl4AI md returned an unexpected response shape");
|
|
161
|
+
}
|
|
162
|
+
const envelope = data;
|
|
163
|
+
if (envelope.success === false) {
|
|
164
|
+
const detail = typeof envelope.error === "string" ? envelope.error : typeof envelope.detail === "string" ? envelope.detail : "";
|
|
165
|
+
throw new Error(`Crawl4AI md unsuccessful: ${redactCredential(detail.trim() || "unknown error", token)}`);
|
|
166
|
+
}
|
|
167
|
+
if (envelope.success !== true) {
|
|
168
|
+
throw new Error("Crawl4AI md returned an unexpected response shape");
|
|
169
|
+
}
|
|
170
|
+
if (typeof envelope.markdown !== "string") {
|
|
171
|
+
throw new Error("Crawl4AI md returned markdown in an unexpected shape");
|
|
172
|
+
}
|
|
173
|
+
activityMonitor.logComplete(activityId, response.status);
|
|
174
|
+
const content = envelope.markdown.trim();
|
|
175
|
+
if (!content)
|
|
176
|
+
return null;
|
|
177
|
+
return { url, title: firstHeadingTitle(content), content, error: null };
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
if (signal?.aborted || isAbortException(err))
|
|
181
|
+
activityMonitor.logComplete(activityId, 0);
|
|
182
|
+
else
|
|
183
|
+
activityMonitor.logError(activityId, errorMessage(err));
|
|
184
|
+
throw err;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=crawl4ai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crawl4ai.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/crawl4ai.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport net from \"node:net\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport type { ExtractedContent, ExtractOptions } from \"./extract.ts\";\nimport { fetchRemoteUrl, loadSsrfConfig, validateRemoteUrl, type Lookup, type SsrfConfig } from \"./ssrf-protection.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst EXTRACT_TIMEOUT_MS = 60_000;\nconst MARKDOWN_FILTER = \"fit\";\n\nexport interface Crawl4aiExtractOptions extends Pick<ExtractOptions, \"timeoutMs\" | \"lookup\"> {\n\tssrf?: SsrfConfig;\n}\n\ninterface Crawl4aiConfig {\n\tcrawl4aiBaseUrl?: unknown;\n\tcrawl4aiApiToken?: unknown;\n}\n\nlet cachedConfig: Crawl4aiConfig | null = null;\n\nfunction loadConfig(): Crawl4aiConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\tconst raw = readFileSync(CONFIG_PATH, \"utf8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as Crawl4aiConfig;\n\treturn cachedConfig;\n}\n\nexport function clearCrawl4aiConfigCache(): void {\n\tcachedConfig = null;\n}\n\nfunction normalizeBaseUrl(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst trimmed = value.trim();\n\tif (!trimmed) return null;\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(trimmed);\n\t} catch {\n\t\tthrow new Error(`Invalid Crawl4AI base URL in ${CONFIG_PATH}: expected an HTTP or HTTPS URL`);\n\t}\n\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\tthrow new Error(`Invalid Crawl4AI base URL in ${CONFIG_PATH}: expected an HTTP or HTTPS URL`);\n\t}\n\tif (parsed.username || parsed.password) {\n\t\tthrow new Error(`Invalid Crawl4AI base URL in ${CONFIG_PATH}: URL credentials are not allowed`);\n\t}\n\tparsed.pathname = parsed.pathname.replace(/\\/+$/, \"\");\n\tparsed.search = \"\";\n\tparsed.hash = \"\";\n\treturn parsed.toString().replace(/\\/+$/, \"\");\n}\n\nfunction getBaseUrl(): string | null {\n\treturn normalizeBaseUrl(process.env.CRAWL4AI_BASE_URL) ?? normalizeBaseUrl(loadConfig().crawl4aiBaseUrl);\n}\n\nfunction requireBaseUrl(): string {\n\tconst baseUrl = getBaseUrl();\n\tif (!baseUrl) {\n\t\tthrow new Error(\n\t\t\t\"Crawl4AI base URL not configured. Either:\\n\" +\n\t\t\t` 1. Set crawl4aiBaseUrl in ${CONFIG_PATH}\\n` +\n\t\t\t\" 2. Set CRAWL4AI_BASE_URL environment variable\",\n\t\t);\n\t}\n\treturn baseUrl;\n}\n\nasync function getApiToken(signal?: AbortSignal): Promise<string | null> {\n\treturn resolveCredential({\n\t\tprovider: \"Crawl4AI\",\n\t\tconfiguredValue: loadConfig().crawl4aiApiToken,\n\t\tenvironmentValue: process.env.CRAWL4AI_API_TOKEN,\n\t\tsignal,\n\t});\n}\n\nfunction requestSignal(timeoutMs: number, signal?: AbortSignal): AbortSignal {\n\tconst timeout = AbortSignal.timeout(timeoutMs);\n\treturn signal ? AbortSignal.any([timeout, signal]) : timeout;\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction isAbortException(err: unknown): boolean {\n\treturn err instanceof DOMException && (err.name === \"AbortError\" || err.name === \"TimeoutError\");\n}\n\nfunction ssrfOptions(options?: Crawl4aiExtractOptions): SsrfConfig & { lookup?: Lookup } {\n\treturn {\n\t\t...(options?.ssrf ?? loadSsrfConfig()),\n\t\t...(options?.lookup ? { lookup: options.lookup } : {}),\n\t};\n}\n\nfunction isLoopbackApiUrl(url: URL): boolean {\n\tconst hostname = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, \"\").replace(/\\.$/, \"\");\n\tif (hostname === \"localhost\" || hostname === \"::1\") return true;\n\tif (net.isIP(hostname) !== 4) return false;\n\treturn hostname.split(\".\")[0] === \"127\";\n}\n\nfunction firstHeadingTitle(markdown: string): string {\n\treturn /^[ \\t]*#[ \\t]+(\\S.*?)[ \\t\\r]*$/m.exec(markdown)?.[1] ?? \"\";\n}\n\nexport function isCrawl4aiAvailable(): boolean {\n\treturn getBaseUrl() !== null;\n}\n\nexport async function extractWithCrawl4ai(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions?: Crawl4aiExtractOptions,\n): Promise<ExtractedContent | null> {\n\tconst baseUrl = requireBaseUrl();\n\tconst ssrf = ssrfOptions(options);\n\tawait validateRemoteUrl(url, ssrf);\n\tconst token = await getApiToken(signal);\n\tconst headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n\tif (token) headers.Authorization = `Bearer ${token}`;\n\tconst requestUrl = new URL(`${baseUrl}/md`);\n\tconst init = {\n\t\tmethod: \"POST\",\n\t\theaders,\n\t\tbody: JSON.stringify({ url, f: MARKDOWN_FILTER }),\n\t\tsignal: requestSignal(options?.timeoutMs ?? EXTRACT_TIMEOUT_MS, signal),\n\t};\n\tlet seeOther = false;\n\tconst activityId = activityMonitor.logStart({ type: \"fetch\", url: requestUrl.toString() });\n\ttry {\n\t\tconst response = await fetchRemoteUrl(requestUrl, init, {\n\t\t\t...ssrf,\n\t\t\tallowLoopback: isLoopbackApiUrl(requestUrl),\n\t\t\tonRedirect: ({ to, init: redirectInit, response }) => {\n\t\t\t\tif (to.origin !== requestUrl.origin) {\n\t\t\t\t\tthrow new Error(`Crawl4AI refused cross-origin redirect to ${to.origin}`);\n\t\t\t\t}\n\t\t\t\t// 303 genuinely means \"GET the other resource\", and it is final: once a hop has turned the\n\t\t\t\t// chain into a GET, no later hop may resurrect the extraction body.\n\t\t\t\tif (response.status === 303) seeOther = true;\n\t\t\t\t// 301/302 are the hops a reverse proxy in front of a self-hosted instance actually emits, and\n\t\t\t\t// fetchRemoteUrl turns those into a bodyless GET that /md cannot serve, so replay the POST.\n\t\t\t\t// 307/308 already keep the method, so their init needs no help.\n\t\t\t\tconst replayPost = !seeOther && (response.status === 301 || response.status === 302);\n\t\t\t\treturn replayPost ? init : redirectInit;\n\t\t\t},\n\t\t});\n\t\tif (!response.ok) {\n\t\t\tconst text = await response.text().catch(() => \"\");\n\t\t\tthrow new Error(`Crawl4AI md error ${response.status}: ${redactCredential(text, token).slice(0, 300)}`);\n\t\t}\n\t\tlet data: unknown;\n\t\ttry {\n\t\t\tdata = await response.json();\n\t\t} catch {\n\t\t\t// The parser message quotes the offending body, which can echo the configured token, so it never\n\t\t\t// reaches the thrown error or the activity log.\n\t\t\tthrow new Error(\"Crawl4AI md returned invalid JSON\");\n\t\t}\n\t\tif (!data || typeof data !== \"object\" || Array.isArray(data)) {\n\t\t\tthrow new Error(\"Crawl4AI md returned an unexpected response shape\");\n\t\t}\n\t\tconst envelope = data as Record<string, unknown>;\n\t\tif (envelope.success === false) {\n\t\t\tconst detail = typeof envelope.error === \"string\" ? envelope.error : typeof envelope.detail === \"string\" ? envelope.detail : \"\";\n\t\t\tthrow new Error(`Crawl4AI md unsuccessful: ${redactCredential(detail.trim() || \"unknown error\", token)}`);\n\t\t}\n\t\tif (envelope.success !== true) {\n\t\t\tthrow new Error(\"Crawl4AI md returned an unexpected response shape\");\n\t\t}\n\t\tif (typeof envelope.markdown !== \"string\") {\n\t\t\tthrow new Error(\"Crawl4AI md returned markdown in an unexpected shape\");\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst content = envelope.markdown.trim();\n\t\tif (!content) return null;\n\t\treturn { url, title: firstHeadingTitle(content), content, error: null };\n\t} catch (err) {\n\t\tif (signal?.aborted || isAbortException(err)) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, errorMessage(err));\n\t\tthrow err;\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential-source.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/credential-source.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"credential-source.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/credential-source.ts"],"names":[],"mappings":"AA2BA,MAAM,MAAM,yBAAyB,GAClC,gBAAgB,GAChB,gBAAgB,GAChB,iBAAiB,GACjB,iBAAiB,GACjB,eAAe,GACf,wBAAwB,GACxB,0BAA0B,GAC1B,mBAAmB,GACnB,2BAA2B,CAAC;AAE/B,qBAAa,yBAA0B,SAAQ,KAAK;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,CAAC;IAE7C,YAAY,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,yBAAyB,EAShE;CACD;AAED,MAAM,WAAW,uBAAuB;IACvC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACxC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,MAAM,MAAM,uBAAuB,GAAG,CACrC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,wBAAwB,KAC7B,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAEtC,MAAM,WAAW,iBAAiB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACjD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACrC;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAE5F;AA+DD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAKvE;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwC1F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential-source.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/credential-source.ts"],"names":[],"mappings":"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","sourcesContent":["import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execAsync = promisify(exec);\nconst COMMAND_TIMEOUT_MS = 5_000;\nconst MAX_CREDENTIAL_BYTES = 16_384;\nconst ENV_SOURCE = /^\\$(?:([A-Za-z_][A-Za-z0-9_]*)|\\{([A-Za-z_][A-Za-z0-9_]*)\\})$/;\nconst OP_SESSION_NAME = /^OP_SESSION_[A-Za-z0-9_]+$/;\nconst COMMAND_ENVIRONMENT_NAMES = [\n\t\"HOME\",\n\t\"USER\",\n\t\"LOGNAME\",\n\t\"PATH\",\n\t\"LANG\",\n\t\"LC_ALL\",\n\t\"LC_CTYPE\",\n\t\"TERM\",\n\t\"TMPDIR\",\n\t\"XDG_CONFIG_HOME\",\n\t\"XDG_RUNTIME_DIR\",\n\t\"DBUS_SESSION_BUS_ADDRESS\",\n\t\"SSH_AUTH_SOCK\",\n\t\"WSL_DISTRO_NAME\",\n\t\"WSL_INTEROP\",\n] as const;\n\nexport type CredentialFailureCategory =\n\t| \"invalid-source\"\n\t| \"command-failed\"\n\t| \"command-timeout\"\n\t| \"command-aborted\"\n\t| \"command-empty\"\n\t| \"command-invalid-output\"\n\t| \"command-output-too-large\"\n\t| \"environment-empty\"\n\t| \"oauth-credential-rejected\";\n\nexport class CredentialResolutionError extends Error {\n\treadonly provider: string;\n\treadonly category: CredentialFailureCategory;\n\n\tconstructor(provider: string, category: CredentialFailureCategory) {\n\t\tconst suffix =\n\t\t\tcategory === \"command-aborted\" ? \"aborted\" :\n\t\t\tcategory === \"oauth-credential-rejected\" ? \"OAuth token exchange rejected the credentials\" :\n\t\t\tcategory;\n\t\tsuper(`${provider} credential resolution failed: ${suffix}`);\n\t\tthis.name = \"CredentialResolutionError\";\n\t\tthis.provider = provider;\n\t\tthis.category = category;\n\t}\n}\n\nexport interface CredentialCommandResult {\n\tstdout: string | Buffer;\n}\n\nexport interface CredentialCommandOptions {\n\tsignal?: AbortSignal;\n\ttimeoutMs: number;\n\tmaxOutputBytes: number;\n\tenvironment: Record<string, string>;\n}\n\nexport type CredentialCommandRunner = (\n\tcommand: string,\n\toptions: CredentialCommandOptions,\n) => Promise<CredentialCommandResult>;\n\nexport interface CredentialOptions {\n\tprovider: string;\n\tconfiguredValue?: unknown;\n\tenvironmentValue?: unknown;\n\tenvironment?: Record<string, string | undefined>;\n\tsignal?: AbortSignal;\n\trunCommand?: CredentialCommandRunner;\n}\n\nexport function redactCredential(text: string, credential: string | null | undefined): string {\n\treturn credential ? text.split(credential).join(\"[redacted]\") : text;\n}\n\nfunction normalize(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst normalized = value.trim();\n\treturn normalized.length > 0 ? normalized : null;\n}\n\nfunction commandEnvironment(source: Record<string, string | undefined>): Record<string, string> {\n\tconst environment: Record<string, string> = {};\n\tfor (const name of COMMAND_ENVIRONMENT_NAMES) {\n\t\tconst value = source[name];\n\t\tif (value !== undefined) environment[name] = value;\n\t}\n\tfor (const [name, value] of Object.entries(source)) {\n\t\tif (value !== undefined && OP_SESSION_NAME.test(name)) environment[name] = value;\n\t}\n\treturn environment;\n}\n\nfunction configuredSource(options: CredentialOptions): string | null {\n\treturn normalize(options.configuredValue);\n}\n\nfunction explicitEnvironmentName(source: string): string | null {\n\tconst match = source.match(ENV_SOURCE);\n\treturn match ? match[1] ?? match[2] : null;\n}\n\nfunction escapedSource(source: string): string | null {\n\tif (source.startsWith(\"$$\") || source.startsWith(\"$!\")) return source.slice(1);\n\treturn null;\n}\n\nfunction isMalformedExplicitSource(source: string): boolean {\n\treturn source.startsWith(\"$\") && escapedSource(source) === null && explicitEnvironmentName(source) === null;\n}\n\nasync function defaultRunCommand(\n\tcommand: string,\n\toptions: CredentialCommandOptions,\n): Promise<CredentialCommandResult> {\n\tconst result = await execAsync(command, {\n\t\tencoding: \"utf8\",\n\t\tenv: options.environment,\n\t\tmaxBuffer: options.maxOutputBytes + 1,\n\t\tsignal: options.signal,\n\t\ttimeout: options.timeoutMs,\n\t\twindowsHide: true,\n\t});\n\treturn { stdout: result.stdout };\n}\n\nfunction commandFailureCategory(error: unknown, signal?: AbortSignal): CredentialFailureCategory {\n\tif (signal?.aborted) return \"command-aborted\";\n\tif (error && typeof error === \"object\") {\n\t\tconst code = (error as { code?: string }).code;\n\t\tif (code === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\") return \"command-output-too-large\";\n\t\tif ((error as { killed?: boolean }).killed || code === \"ETIMEDOUT\") return \"command-timeout\";\n\t}\n\treturn \"command-failed\";\n}\n\nexport function hasCredentialSource(options: CredentialOptions): boolean {\n\tconst source = configuredSource(options);\n\tif (source?.startsWith(\"!\")) return true;\n\tif (source?.startsWith(\"$\")) return true;\n\treturn normalize(options.environmentValue) !== null || source !== null;\n}\n\nexport async function resolveCredential(options: CredentialOptions): Promise<string | null> {\n\tconst source = configuredSource(options);\n\tconst escaped = source ? escapedSource(source) : null;\n\tif (escaped !== null) return escaped;\n\tif (source?.startsWith(\"!\")) {\n\t\tconst command = source.slice(1).trim();\n\t\tif (!command) throw new CredentialResolutionError(options.provider, \"invalid-source\");\n\t\tlet result: CredentialCommandResult;\n\t\ttry {\n\t\t\tresult = await (options.runCommand ?? defaultRunCommand)(command, {\n\t\t\t\tsignal: options.signal,\n\t\t\t\ttimeoutMs: COMMAND_TIMEOUT_MS,\n\t\t\t\tmaxOutputBytes: MAX_CREDENTIAL_BYTES,\n\t\t\t\tenvironment: commandEnvironment(options.environment ?? process.env),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthrow new CredentialResolutionError(options.provider, commandFailureCategory(error, options.signal));\n\t\t}\n\t\tconst stdout = Buffer.isBuffer(result.stdout) ? result.stdout.toString(\"utf8\") : result.stdout;\n\t\tif (Buffer.byteLength(stdout, \"utf8\") > MAX_CREDENTIAL_BYTES) {\n\t\t\tthrow new CredentialResolutionError(options.provider, \"command-output-too-large\");\n\t\t}\n\t\tconst value = stdout.trim();\n\t\tif (!value) throw new CredentialResolutionError(options.provider, \"command-empty\");\n\t\tif (/[\\0-\\x1f\\x7f]/.test(value)) {\n\t\t\tthrow new CredentialResolutionError(options.provider, \"command-invalid-output\");\n\t\t}\n\t\treturn value;\n\t}\n\tif (source && isMalformedExplicitSource(source)) {\n\t\tthrow new CredentialResolutionError(options.provider, \"invalid-source\");\n\t}\n\tif (source?.startsWith(\"$\")) {\n\t\tconst name = explicitEnvironmentName(source);\n\t\tif (!name) throw new CredentialResolutionError(options.provider, \"invalid-source\");\n\t\tconst value = normalize((options.environment ?? process.env)[name]);\n\t\tif (!value) throw new CredentialResolutionError(options.provider, \"environment-empty\");\n\t\treturn value;\n\t}\n\treturn normalize(options.environmentValue) ?? source;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"credential-source.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/credential-source.ts"],"names":[],"mappings":"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","sourcesContent":["import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execAsync = promisify(exec);\nconst COMMAND_TIMEOUT_MS = 5_000;\nconst MAX_CREDENTIAL_BYTES = 16_384;\nconst ENV_SOURCE = /^\\$(?:([A-Za-z_][A-Za-z0-9_]*)|\\{([A-Za-z_][A-Za-z0-9_]*)\\})$/;\nconst OP_SESSION_NAME = /^OP_SESSION_[A-Za-z0-9_]+$/;\nconst COMMAND_ENVIRONMENT_NAMES = [\n\t\"HOME\",\n\t\"USER\",\n\t\"LOGNAME\",\n\t\"OP_SERVICE_ACCOUNT_TOKEN\",\n\t\"PATH\",\n\t\"LANG\",\n\t\"LC_ALL\",\n\t\"LC_CTYPE\",\n\t\"TERM\",\n\t\"TMPDIR\",\n\t\"XDG_CONFIG_HOME\",\n\t\"XDG_RUNTIME_DIR\",\n\t\"DBUS_SESSION_BUS_ADDRESS\",\n\t\"SSH_AUTH_SOCK\",\n\t\"WSL_DISTRO_NAME\",\n\t\"WSL_INTEROP\",\n] as const;\n\nexport type CredentialFailureCategory =\n\t| \"invalid-source\"\n\t| \"command-failed\"\n\t| \"command-timeout\"\n\t| \"command-aborted\"\n\t| \"command-empty\"\n\t| \"command-invalid-output\"\n\t| \"command-output-too-large\"\n\t| \"environment-empty\"\n\t| \"oauth-credential-rejected\";\n\nexport class CredentialResolutionError extends Error {\n\treadonly provider: string;\n\treadonly category: CredentialFailureCategory;\n\n\tconstructor(provider: string, category: CredentialFailureCategory) {\n\t\tconst suffix =\n\t\t\tcategory === \"command-aborted\" ? \"aborted\" :\n\t\t\tcategory === \"oauth-credential-rejected\" ? \"OAuth token exchange rejected the credentials\" :\n\t\t\tcategory;\n\t\tsuper(`${provider} credential resolution failed: ${suffix}`);\n\t\tthis.name = \"CredentialResolutionError\";\n\t\tthis.provider = provider;\n\t\tthis.category = category;\n\t}\n}\n\nexport interface CredentialCommandResult {\n\tstdout: string | Buffer;\n}\n\nexport interface CredentialCommandOptions {\n\tsignal?: AbortSignal;\n\ttimeoutMs: number;\n\tmaxOutputBytes: number;\n\tenvironment: Record<string, string>;\n}\n\nexport type CredentialCommandRunner = (\n\tcommand: string,\n\toptions: CredentialCommandOptions,\n) => Promise<CredentialCommandResult>;\n\nexport interface CredentialOptions {\n\tprovider: string;\n\tconfiguredValue?: unknown;\n\tenvironmentValue?: unknown;\n\tenvironment?: Record<string, string | undefined>;\n\tsignal?: AbortSignal;\n\trunCommand?: CredentialCommandRunner;\n}\n\nexport function redactCredential(text: string, credential: string | null | undefined): string {\n\treturn credential ? text.split(credential).join(\"[redacted]\") : text;\n}\n\nfunction normalize(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst normalized = value.trim();\n\treturn normalized.length > 0 ? normalized : null;\n}\n\nfunction commandEnvironment(source: Record<string, string | undefined>): Record<string, string> {\n\tconst environment: Record<string, string> = {};\n\tfor (const name of COMMAND_ENVIRONMENT_NAMES) {\n\t\tconst value = source[name];\n\t\tif (value !== undefined) environment[name] = value;\n\t}\n\tfor (const [name, value] of Object.entries(source)) {\n\t\tif (value !== undefined && OP_SESSION_NAME.test(name)) environment[name] = value;\n\t}\n\treturn environment;\n}\n\nfunction configuredSource(options: CredentialOptions): string | null {\n\treturn normalize(options.configuredValue);\n}\n\nfunction explicitEnvironmentName(source: string): string | null {\n\tconst match = source.match(ENV_SOURCE);\n\treturn match ? match[1] ?? match[2] : null;\n}\n\nfunction escapedSource(source: string): string | null {\n\tif (source.startsWith(\"$$\") || source.startsWith(\"$!\")) return source.slice(1);\n\treturn null;\n}\n\nfunction isMalformedExplicitSource(source: string): boolean {\n\treturn source.startsWith(\"$\") && escapedSource(source) === null && explicitEnvironmentName(source) === null;\n}\n\nasync function defaultRunCommand(\n\tcommand: string,\n\toptions: CredentialCommandOptions,\n): Promise<CredentialCommandResult> {\n\tconst result = await execAsync(command, {\n\t\tencoding: \"utf8\",\n\t\tenv: options.environment,\n\t\tmaxBuffer: options.maxOutputBytes + 1,\n\t\tsignal: options.signal,\n\t\ttimeout: options.timeoutMs,\n\t\twindowsHide: true,\n\t});\n\treturn { stdout: result.stdout };\n}\n\nfunction commandFailureCategory(error: unknown, signal?: AbortSignal): CredentialFailureCategory {\n\tif (signal?.aborted) return \"command-aborted\";\n\tif (error && typeof error === \"object\") {\n\t\tconst code = (error as { code?: string }).code;\n\t\tif (code === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\") return \"command-output-too-large\";\n\t\tif ((error as { killed?: boolean }).killed || code === \"ETIMEDOUT\") return \"command-timeout\";\n\t}\n\treturn \"command-failed\";\n}\n\nexport function hasCredentialSource(options: CredentialOptions): boolean {\n\tconst source = configuredSource(options);\n\tif (source?.startsWith(\"!\")) return true;\n\tif (source?.startsWith(\"$\")) return true;\n\treturn normalize(options.environmentValue) !== null || source !== null;\n}\n\nexport async function resolveCredential(options: CredentialOptions): Promise<string | null> {\n\tconst source = configuredSource(options);\n\tconst escaped = source ? escapedSource(source) : null;\n\tif (escaped !== null) return escaped;\n\tif (source?.startsWith(\"!\")) {\n\t\tconst command = source.slice(1).trim();\n\t\tif (!command) throw new CredentialResolutionError(options.provider, \"invalid-source\");\n\t\tlet result: CredentialCommandResult;\n\t\ttry {\n\t\t\tresult = await (options.runCommand ?? defaultRunCommand)(command, {\n\t\t\t\tsignal: options.signal,\n\t\t\t\ttimeoutMs: COMMAND_TIMEOUT_MS,\n\t\t\t\tmaxOutputBytes: MAX_CREDENTIAL_BYTES,\n\t\t\t\tenvironment: commandEnvironment(options.environment ?? process.env),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthrow new CredentialResolutionError(options.provider, commandFailureCategory(error, options.signal));\n\t\t}\n\t\tconst stdout = Buffer.isBuffer(result.stdout) ? result.stdout.toString(\"utf8\") : result.stdout;\n\t\tif (Buffer.byteLength(stdout, \"utf8\") > MAX_CREDENTIAL_BYTES) {\n\t\t\tthrow new CredentialResolutionError(options.provider, \"command-output-too-large\");\n\t\t}\n\t\tconst value = stdout.trim();\n\t\tif (!value) throw new CredentialResolutionError(options.provider, \"command-empty\");\n\t\tif (/[\\0-\\x1f\\x7f]/.test(value)) {\n\t\t\tthrow new CredentialResolutionError(options.provider, \"command-invalid-output\");\n\t\t}\n\t\treturn value;\n\t}\n\tif (source && isMalformedExplicitSource(source)) {\n\t\tthrow new CredentialResolutionError(options.provider, \"invalid-source\");\n\t}\n\tif (source?.startsWith(\"$\")) {\n\t\tconst name = explicitEnvironmentName(source);\n\t\tif (!name) throw new CredentialResolutionError(options.provider, \"invalid-source\");\n\t\tconst value = normalize((options.environment ?? process.env)[name]);\n\t\tif (!value) throw new CredentialResolutionError(options.provider, \"environment-empty\");\n\t\treturn value;\n\t}\n\treturn normalize(options.environmentValue) ?? source;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"curator-page.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/curator-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"curator-page.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/curator-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AA8D/D,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,MAAM,EAAE,EACjB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,kBAAkB,EAAE,oBAAoB,EACxC,eAAe,EAAE,MAAM,EACvB,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EACtD,mBAAmB,EAAE,MAAM,GAAG,IAAI,GAChC,MAAM,CA0IR"}
|
|
@@ -36,6 +36,7 @@ function buildProviderButtons(available, selected, hasInitialQueries) {
|
|
|
36
36
|
{ value: "mistral", label: "Mistral", available: available.mistral },
|
|
37
37
|
{ value: "brightdata", label: "Bright Data", available: available.brightdata },
|
|
38
38
|
{ value: "serpbase", label: "SerpBase", available: available.serpbase },
|
|
39
|
+
{ value: "serpapi", label: "SerpApi", available: available.serpapi },
|
|
39
40
|
{ value: "serper", label: "Serper", available: available.serper },
|
|
40
41
|
{ value: "valyu", label: "Valyu", available: available.valyu },
|
|
41
42
|
];
|
|
@@ -130,6 +131,7 @@ ${CSS}
|
|
|
130
131
|
<button class="btn btn-secondary" id="btn-summary-regenerate">Regenerate</button>
|
|
131
132
|
<button class="btn btn-secondary" id="btn-summary-preview" title="Preview rendered summary">Preview</button>
|
|
132
133
|
<button class="btn btn-submit" id="btn-summary-approve">Approve</button>
|
|
134
|
+
<button class="btn btn-submit" id="btn-summary-approve-remaining">Approve + auto-summary remaining searches for this prompt</button>
|
|
133
135
|
</div>
|
|
134
136
|
</section>
|
|
135
137
|
</main>
|
|
@@ -1177,6 +1179,7 @@ main {
|
|
|
1177
1179
|
}
|
|
1178
1180
|
.summary-actions {
|
|
1179
1181
|
display: flex;
|
|
1182
|
+
flex-wrap: wrap;
|
|
1180
1183
|
align-items: center;
|
|
1181
1184
|
justify-content: flex-end;
|
|
1182
1185
|
gap: 8px;
|
|
@@ -1448,7 +1451,7 @@ const SCRIPT = `(function() {
|
|
|
1448
1451
|
var token = DATA.sessionToken;
|
|
1449
1452
|
var timeoutSec = DATA.timeout;
|
|
1450
1453
|
var queries = Array.isArray(DATA.queries) ? DATA.queries : [];
|
|
1451
|
-
var providers = ["all", "openai", "exa", "brave", "parallel", "parallel-mcp", "tinyfish", "search1api", "searchinfinity", "querit", "tavily", "firecrawl", "jina", "serpdive", "kagi", "bocha", "ollama", "searxng", "duckduckgo", "perplexity", "gemini", "kimi", "anysearch", "xcrawl", "xai", "mistral", "brightdata", "serpbase", "serper", "valyu"];
|
|
1454
|
+
var providers = ["all", "openai", "exa", "brave", "parallel", "parallel-mcp", "tinyfish", "search1api", "searchinfinity", "querit", "tavily", "firecrawl", "jina", "serpdive", "kagi", "bocha", "ollama", "searxng", "duckduckgo", "perplexity", "gemini", "kimi", "anysearch", "xcrawl", "xai", "mistral", "brightdata", "serpbase", "serpapi", "serper", "valyu"];
|
|
1452
1455
|
var availProviders = DATA.availableProviders && typeof DATA.availableProviders === "object" ? DATA.availableProviders : {};
|
|
1453
1456
|
var workflow = "summary-review";
|
|
1454
1457
|
var initialDefaultProvider = typeof DATA.defaultProvider === "string" ? DATA.defaultProvider : "exa";
|
|
@@ -1513,6 +1516,7 @@ const SCRIPT = `(function() {
|
|
|
1513
1516
|
var btnSummaryRegenerate = document.getElementById("btn-summary-regenerate");
|
|
1514
1517
|
var btnSummaryPreview = document.getElementById("btn-summary-preview");
|
|
1515
1518
|
var btnSummaryApprove = document.getElementById("btn-summary-approve");
|
|
1519
|
+
var btnSummaryApproveRemaining = document.getElementById("btn-summary-approve-remaining");
|
|
1516
1520
|
var successOverlay = document.getElementById("success-overlay");
|
|
1517
1521
|
var successText = document.getElementById("success-text");
|
|
1518
1522
|
var expiredOverlay = document.getElementById("expired-overlay");
|
|
@@ -1678,6 +1682,9 @@ const SCRIPT = `(function() {
|
|
|
1678
1682
|
if (provider === "mistral") return "Mistral";
|
|
1679
1683
|
if (provider === "brightdata") return "Bright Data";
|
|
1680
1684
|
if (provider === "serpbase") return "SerpBase";
|
|
1685
|
+
if (provider === "serpapi") return "SerpApi";
|
|
1686
|
+
if (provider === "serper") return "Serper";
|
|
1687
|
+
if (provider === "valyu") return "Valyu";
|
|
1681
1688
|
return "Unknown";
|
|
1682
1689
|
}
|
|
1683
1690
|
|
|
@@ -2093,6 +2100,9 @@ const SCRIPT = `(function() {
|
|
|
2093
2100
|
if (btnSummaryApprove) {
|
|
2094
2101
|
btnSummaryApprove.disabled = submitted || timerExpired || submitInFlight || stage === "generating-summary" || isRegenerating || !hasSelection || !hasDraft;
|
|
2095
2102
|
}
|
|
2103
|
+
if (btnSummaryApproveRemaining) {
|
|
2104
|
+
btnSummaryApproveRemaining.disabled = submitted || timerExpired || submitInFlight || stage === "generating-summary" || isRegenerating || !hasSelection || !hasDraft;
|
|
2105
|
+
}
|
|
2096
2106
|
|
|
2097
2107
|
applyProviderInterlocks();
|
|
2098
2108
|
}
|
|
@@ -3184,7 +3194,7 @@ const SCRIPT = `(function() {
|
|
|
3184
3194
|
requestSummary(selected);
|
|
3185
3195
|
}
|
|
3186
3196
|
|
|
3187
|
-
function doApprove() {
|
|
3197
|
+
function doApprove(autoApproveRemainingSearches) {
|
|
3188
3198
|
if (submitted || timerExpired || submitInFlight || stage !== "summary-review") return;
|
|
3189
3199
|
|
|
3190
3200
|
var selected = getSelectedIndices();
|
|
@@ -3196,6 +3206,7 @@ const SCRIPT = `(function() {
|
|
|
3196
3206
|
|
|
3197
3207
|
var draft = getSummaryDraftText();
|
|
3198
3208
|
var payload = { selected: selected };
|
|
3209
|
+
if (autoApproveRemainingSearches === true) payload.autoApproveRemainingSearches = true;
|
|
3199
3210
|
if (draft.length > 0) {
|
|
3200
3211
|
payload.summary = draft;
|
|
3201
3212
|
payload.summaryMeta = normalizeSummaryMeta(summaryMeta, summaryMeta && summaryMeta.edited === true);
|
|
@@ -3434,6 +3445,13 @@ const SCRIPT = `(function() {
|
|
|
3434
3445
|
});
|
|
3435
3446
|
}
|
|
3436
3447
|
|
|
3448
|
+
if (btnSummaryApproveRemaining) {
|
|
3449
|
+
btnSummaryApproveRemaining.addEventListener("click", function() {
|
|
3450
|
+
doApprove(true);
|
|
3451
|
+
resetTimer();
|
|
3452
|
+
});
|
|
3453
|
+
}
|
|
3454
|
+
|
|
3437
3455
|
if (summaryInput) {
|
|
3438
3456
|
summaryInput.addEventListener("input", function() {
|
|
3439
3457
|
if (!summaryMeta || typeof summaryMeta !== "object") {
|