@humain/terminal 0.2.3 → 0.3.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.
Files changed (152) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/bundle/chunks/{chunk-U75GS4NL.js → chunk-CBTAWCW5.js} +1 -1
  3. package/dist/bundle/chunks/{chunk-D6HHRSB5.js → chunk-S43N4JYF.js} +14 -29
  4. package/dist/bundle/chunks/{chunk-LYOOYM65.js → chunk-WKLAQTQ4.js} +100 -124
  5. package/dist/bundle/chunks/{compat-22OQ5DBK.js → compat-L5WILLPV.js} +1 -1
  6. package/dist/bundle/chunks/{extract-CTIFQZDJ.js → extract-2YP6VMY4.js} +3 -3
  7. package/dist/bundle/cli.js +1 -1
  8. package/dist/bundle/index.js +1 -1
  9. package/dist/bundle/rpc-entry.js +1 -1
  10. package/dist/humain/web-access/vendor/anysearch.d.ts.map +1 -1
  11. package/dist/humain/web-access/vendor/anysearch.js +4 -14
  12. package/dist/humain/web-access/vendor/anysearch.js.map +1 -1
  13. package/dist/humain/web-access/vendor/bocha.d.ts.map +1 -1
  14. package/dist/humain/web-access/vendor/bocha.js +3 -24
  15. package/dist/humain/web-access/vendor/bocha.js.map +1 -1
  16. package/dist/humain/web-access/vendor/brave.d.ts.map +1 -1
  17. package/dist/humain/web-access/vendor/brave.js +3 -24
  18. package/dist/humain/web-access/vendor/brave.js.map +1 -1
  19. package/dist/humain/web-access/vendor/brightdata.d.ts.map +1 -1
  20. package/dist/humain/web-access/vendor/brightdata.js +5 -34
  21. package/dist/humain/web-access/vendor/brightdata.js.map +1 -1
  22. package/dist/humain/web-access/vendor/content-find.d.ts.map +1 -1
  23. package/dist/humain/web-access/vendor/content-find.js +186 -51
  24. package/dist/humain/web-access/vendor/content-find.js.map +1 -1
  25. package/dist/humain/web-access/vendor/curator-page.d.ts.map +1 -1
  26. package/dist/humain/web-access/vendor/curator-page.js +4 -1
  27. package/dist/humain/web-access/vendor/curator-page.js.map +1 -1
  28. package/dist/humain/web-access/vendor/curator-run.d.ts.map +1 -1
  29. package/dist/humain/web-access/vendor/curator-run.js +3 -1
  30. package/dist/humain/web-access/vendor/curator-run.js.map +1 -1
  31. package/dist/humain/web-access/vendor/curator-server.d.ts.map +1 -1
  32. package/dist/humain/web-access/vendor/curator-server.js +2 -0
  33. package/dist/humain/web-access/vendor/curator-server.js.map +1 -1
  34. package/dist/humain/web-access/vendor/domain-filter-normalization.d.ts +2 -0
  35. package/dist/humain/web-access/vendor/domain-filter-normalization.d.ts.map +1 -0
  36. package/dist/humain/web-access/vendor/domain-filter-normalization.js +19 -0
  37. package/dist/humain/web-access/vendor/domain-filter-normalization.js.map +1 -0
  38. package/dist/humain/web-access/vendor/duckduckgo.d.ts.map +1 -1
  39. package/dist/humain/web-access/vendor/duckduckgo.js +3 -24
  40. package/dist/humain/web-access/vendor/duckduckgo.js.map +1 -1
  41. package/dist/humain/web-access/vendor/extract.d.ts.map +1 -1
  42. package/dist/humain/web-access/vendor/extract.js +3 -1
  43. package/dist/humain/web-access/vendor/extract.js.map +1 -1
  44. package/dist/humain/web-access/vendor/firecrawl.d.ts.map +1 -1
  45. package/dist/humain/web-access/vendor/firecrawl.js +5 -32
  46. package/dist/humain/web-access/vendor/firecrawl.js.map +1 -1
  47. package/dist/humain/web-access/vendor/gemini-search.d.ts +5 -2
  48. package/dist/humain/web-access/vendor/gemini-search.d.ts.map +1 -1
  49. package/dist/humain/web-access/vendor/gemini-search.js +85 -37
  50. package/dist/humain/web-access/vendor/gemini-search.js.map +1 -1
  51. package/dist/humain/web-access/vendor/index.d.ts +3 -3
  52. package/dist/humain/web-access/vendor/index.d.ts.map +1 -1
  53. package/dist/humain/web-access/vendor/index.js +135 -157
  54. package/dist/humain/web-access/vendor/index.js.map +1 -1
  55. package/dist/humain/web-access/vendor/jina-search.d.ts.map +1 -1
  56. package/dist/humain/web-access/vendor/jina-search.js +4 -14
  57. package/dist/humain/web-access/vendor/jina-search.js.map +1 -1
  58. package/dist/humain/web-access/vendor/kagi.d.ts.map +1 -1
  59. package/dist/humain/web-access/vendor/kagi.js +4 -12
  60. package/dist/humain/web-access/vendor/kagi.js.map +1 -1
  61. package/dist/humain/web-access/vendor/kimi-search.d.ts.map +1 -1
  62. package/dist/humain/web-access/vendor/kimi-search.js +5 -32
  63. package/dist/humain/web-access/vendor/kimi-search.js.map +1 -1
  64. package/dist/humain/web-access/vendor/mistral-search.d.ts.map +1 -1
  65. package/dist/humain/web-access/vendor/mistral-search.js +1 -18
  66. package/dist/humain/web-access/vendor/mistral-search.js.map +1 -1
  67. package/dist/humain/web-access/vendor/ollama.d.ts.map +1 -1
  68. package/dist/humain/web-access/vendor/ollama.js +2 -6
  69. package/dist/humain/web-access/vendor/ollama.js.map +1 -1
  70. package/dist/humain/web-access/vendor/openai-search.d.ts +3 -0
  71. package/dist/humain/web-access/vendor/openai-search.d.ts.map +1 -1
  72. package/dist/humain/web-access/vendor/openai-search.js +181 -38
  73. package/dist/humain/web-access/vendor/openai-search.js.map +1 -1
  74. package/dist/humain/web-access/vendor/opencode-session-headers.d.ts +10 -0
  75. package/dist/humain/web-access/vendor/opencode-session-headers.d.ts.map +1 -0
  76. package/dist/humain/web-access/vendor/opencode-session-headers.js +23 -0
  77. package/dist/humain/web-access/vendor/opencode-session-headers.js.map +1 -0
  78. package/dist/humain/web-access/vendor/page-query.d.ts.map +1 -1
  79. package/dist/humain/web-access/vendor/page-query.js +10 -2
  80. package/dist/humain/web-access/vendor/page-query.js.map +1 -1
  81. package/dist/humain/web-access/vendor/parallel.d.ts.map +1 -1
  82. package/dist/humain/web-access/vendor/parallel.js +1 -18
  83. package/dist/humain/web-access/vendor/parallel.js.map +1 -1
  84. package/dist/humain/web-access/vendor/pdf-extract.d.ts +2 -0
  85. package/dist/humain/web-access/vendor/pdf-extract.d.ts.map +1 -1
  86. package/dist/humain/web-access/vendor/pdf-extract.js +1 -0
  87. package/dist/humain/web-access/vendor/pdf-extract.js.map +1 -1
  88. package/dist/humain/web-access/vendor/querit.d.ts.map +1 -1
  89. package/dist/humain/web-access/vendor/querit.js +5 -32
  90. package/dist/humain/web-access/vendor/querit.js.map +1 -1
  91. package/dist/humain/web-access/vendor/search-answer-formatting.d.ts +8 -0
  92. package/dist/humain/web-access/vendor/search-answer-formatting.d.ts.map +1 -0
  93. package/dist/humain/web-access/vendor/search-answer-formatting.js +6 -0
  94. package/dist/humain/web-access/vendor/search-answer-formatting.js.map +1 -0
  95. package/dist/humain/web-access/vendor/search-result-count-normalization.d.ts +2 -0
  96. package/dist/humain/web-access/vendor/search-result-count-normalization.d.ts.map +1 -0
  97. package/dist/humain/web-access/vendor/search-result-count-normalization.js +6 -0
  98. package/dist/humain/web-access/vendor/search-result-count-normalization.js.map +1 -0
  99. package/dist/humain/web-access/vendor/search1api.d.ts.map +1 -1
  100. package/dist/humain/web-access/vendor/search1api.js +5 -32
  101. package/dist/humain/web-access/vendor/search1api.js.map +1 -1
  102. package/dist/humain/web-access/vendor/searchinfinity.d.ts.map +1 -1
  103. package/dist/humain/web-access/vendor/searchinfinity.js +5 -32
  104. package/dist/humain/web-access/vendor/searchinfinity.js.map +1 -1
  105. package/dist/humain/web-access/vendor/searxng.d.ts.map +1 -1
  106. package/dist/humain/web-access/vendor/searxng.js +3 -24
  107. package/dist/humain/web-access/vendor/searxng.js.map +1 -1
  108. package/dist/humain/web-access/vendor/serpapi.d.ts.map +1 -1
  109. package/dist/humain/web-access/vendor/serpapi.js +5 -30
  110. package/dist/humain/web-access/vendor/serpapi.js.map +1 -1
  111. package/dist/humain/web-access/vendor/serpbase.d.ts.map +1 -1
  112. package/dist/humain/web-access/vendor/serpbase.js +3 -24
  113. package/dist/humain/web-access/vendor/serpbase.js.map +1 -1
  114. package/dist/humain/web-access/vendor/serpdive.d.ts.map +1 -1
  115. package/dist/humain/web-access/vendor/serpdive.js +3 -24
  116. package/dist/humain/web-access/vendor/serpdive.js.map +1 -1
  117. package/dist/humain/web-access/vendor/serper.d.ts.map +1 -1
  118. package/dist/humain/web-access/vendor/serper.js +5 -30
  119. package/dist/humain/web-access/vendor/serper.js.map +1 -1
  120. package/dist/humain/web-access/vendor/serply.d.ts +4 -0
  121. package/dist/humain/web-access/vendor/serply.d.ts.map +1 -0
  122. package/dist/humain/web-access/vendor/serply.js +191 -0
  123. package/dist/humain/web-access/vendor/serply.js.map +1 -0
  124. package/dist/humain/web-access/vendor/source-check.d.ts.map +1 -1
  125. package/dist/humain/web-access/vendor/source-check.js +11 -47
  126. package/dist/humain/web-access/vendor/source-check.js.map +1 -1
  127. package/dist/humain/web-access/vendor/summary-review.d.ts +1 -1
  128. package/dist/humain/web-access/vendor/summary-review.d.ts.map +1 -1
  129. package/dist/humain/web-access/vendor/summary-review.js +6 -2
  130. package/dist/humain/web-access/vendor/summary-review.js.map +1 -1
  131. package/dist/humain/web-access/vendor/tavily.d.ts.map +1 -1
  132. package/dist/humain/web-access/vendor/tavily.js +3 -24
  133. package/dist/humain/web-access/vendor/tavily.js.map +1 -1
  134. package/dist/humain/web-access/vendor/tinyfish.d.ts.map +1 -1
  135. package/dist/humain/web-access/vendor/tinyfish.js +5 -32
  136. package/dist/humain/web-access/vendor/tinyfish.js.map +1 -1
  137. package/dist/humain/web-access/vendor/utils.d.ts.map +1 -1
  138. package/dist/humain/web-access/vendor/utils.js +2 -0
  139. package/dist/humain/web-access/vendor/utils.js.map +1 -1
  140. package/dist/humain/web-access/vendor/valyu.d.ts.map +1 -1
  141. package/dist/humain/web-access/vendor/valyu.js +5 -30
  142. package/dist/humain/web-access/vendor/valyu.js.map +1 -1
  143. package/dist/humain/web-access/vendor/xai-search.d.ts.map +1 -1
  144. package/dist/humain/web-access/vendor/xai-search.js +1 -18
  145. package/dist/humain/web-access/vendor/xai-search.js.map +1 -1
  146. package/dist/humain/web-access/vendor/xcrawl.d.ts.map +1 -1
  147. package/dist/humain/web-access/vendor/xcrawl.js +5 -34
  148. package/dist/humain/web-access/vendor/xcrawl.js.map +1 -1
  149. package/npm-shrinkwrap.json +6 -6
  150. package/package.json +2 -2
  151. package/src/humain/web-access/UPSTREAM.md +33 -1
  152. package/src/humain/web-access/upstream.json +6 -5
@@ -1 +1 @@
1
- {"version":3,"file":"mistral-search.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/mistral-search.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { SearchOptions, SearchResponse, SearchResult } from \"./perplexity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst MISTRAL_CONVERSATIONS_URL = \"https://api.mistral.ai/v1/conversations\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\nconst DEFAULT_SEARCH_MODEL = \"mistral-small-latest\";\nconst DEFAULT_SEARCH_TOOL = \"web_search\";\nconst MAX_RESULTS = 20;\n\ntype MistralSearchTool = \"web_search\" | \"web_search_premium\";\n\ninterface WebSearchConfig {\n\tmistralApiKey?: unknown;\n\tmistralSearchModel?: unknown;\n\tmistralSearchTool?: unknown;\n}\n\ninterface DomainFilters {\n\tinclude: string[];\n\texclude: string[];\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nfunction resolveSearchModel(value: unknown): string {\n\tif (value === undefined) return DEFAULT_SEARCH_MODEL;\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\tthrow new Error(`mistralSearchModel in ${CONFIG_PATH} must be a non-empty string`);\n\t}\n\treturn value.trim();\n}\n\nfunction resolveSearchTool(value: unknown): MistralSearchTool {\n\tif (value === undefined) return DEFAULT_SEARCH_TOOL;\n\tif (value !== \"web_search\" && value !== \"web_search_premium\") {\n\t\tthrow new Error(`mistralSearchTool in ${CONFIG_PATH} must be either web_search or web_search_premium`);\n\t}\n\treturn value;\n}\n\nfunction normalizeCount(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), MAX_RESULTS));\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 parseDomainFilters(domainFilter: string[] | undefined): DomainFilters {\n\tconst filters: DomainFilters = { include: [], exclude: [] };\n\tfor (const raw of domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? filters.exclude : filters.include;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn filters;\n}\n\nfunction passesDomainFilters(url: string, filters: DomainFilters): boolean {\n\tif (filters.include.length === 0 && filters.exclude.length === 0) return true;\n\tconst hostname = new URL(url).hostname.toLowerCase();\n\tconst matches = (domain: string) => hostname === domain || hostname.endsWith(`.${domain}`);\n\tif (filters.exclude.some(matches)) return false;\n\treturn filters.include.length === 0 || filters.include.some(matches);\n}\n\nfunction normalizeResultUrl(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst url = value.trim();\n\tif (!url) return null;\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") return null;\n\t} catch {\n\t\treturn null;\n\t}\n\treturn url;\n}\n\nfunction buildSearchPrompt(query: string, options: SearchOptions, numResults: number): string {\n\tconst lines: string[] = [];\n\tif (options.recencyFilter) {\n\t\tconst labels: Record<string, string> = {\n\t\t\tday: \"past 24 hours\",\n\t\t\tweek: \"past week\",\n\t\t\tmonth: \"past month\",\n\t\t\tyear: \"past year\",\n\t\t};\n\t\tlines.push(`Prefer sources from the ${labels[options.recencyFilter] ?? options.recencyFilter}.`);\n\t}\n\tif (typeof options.numResults === \"number\" && Number.isFinite(options.numResults) && options.numResults > 0) {\n\t\tlines.push(`Prefer up to ${numResults} distinct sources.`);\n\t}\n\n\tconst filters = parseDomainFilters(options.domainFilter);\n\tif (filters.include.length > 0) lines.push(`Only use sources from: ${filters.include.slice(0, 100).join(\", \")}.`);\n\tif (filters.exclude.length > 0) lines.push(`Do not use sources from: ${filters.exclude.slice(0, 100).join(\", \")}.`);\n\treturn lines.length > 0 ? `${lines.join(\" \")}\\n\\n${query}` : query;\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction invalidResponse(message: string): Error {\n\treturn new Error(`Mistral API returned invalid response: ${message}`);\n}\n\nfunction parseConversationResponse(value: unknown, options: SearchOptions, numResults: number): SearchResponse {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow invalidResponse(\"expected an object envelope\");\n\t}\n\tconst outputs = (value as Record<string, unknown>).outputs;\n\tif (!Array.isArray(outputs)) throw invalidResponse(\"outputs must be an array\");\n\n\tconst answerParts: string[] = [];\n\tconst results: SearchResult[] = [];\n\tconst seenUrls = new Set<string>();\n\tconst domainFilters = parseDomainFilters(options.domainFilter);\n\n\tfor (const output of outputs) {\n\t\tif (!output || typeof output !== \"object\" || Array.isArray(output)) continue;\n\t\tconst entry = output as Record<string, unknown>;\n\t\tif (entry.type !== \"message.output\") continue;\n\t\tconst content = entry.content;\n\t\tif (typeof content === \"string\") {\n\t\t\tif (content.trim()) answerParts.push(content.trim());\n\t\t\tcontinue;\n\t\t}\n\t\tif (!Array.isArray(content)) continue;\n\n\t\tfor (const chunk of content) {\n\t\t\tif (!chunk || typeof chunk !== \"object\" || Array.isArray(chunk)) continue;\n\t\t\tconst part = chunk as Record<string, unknown>;\n\t\t\tif (part.type === \"text\") {\n\t\t\t\tif (typeof part.text === \"string\" && part.text.trim()) answerParts.push(part.text.trim());\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (part.type !== \"tool_reference\" || results.length >= numResults) continue;\n\n\t\t\tconst url = normalizeResultUrl(part.url);\n\t\t\tif (!url || !passesDomainFilters(url, domainFilters) || seenUrls.has(url)) continue;\n\t\t\tseenUrls.add(url);\n\t\t\tconst title = typeof part.title === \"string\" && part.title.trim() ? part.title.trim() : url;\n\t\t\tconst snippet = typeof part.description === \"string\" ? part.description : \"\";\n\t\t\tresults.push({ title, url, snippet });\n\t\t}\n\t}\n\n\tconst answer = answerParts.join(\"\\n\").trim();\n\tif (!answer && results.length === 0) throw invalidResponse(\"no answer or sources\");\n\treturn { answer, results };\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst apiKey = await resolveCredential({\n\t\tprovider: \"Mistral\",\n\t\tconfiguredValue: loadConfig().mistralApiKey,\n\t\tenvironmentValue: process.env.MISTRAL_API_KEY,\n\t\tsignal,\n\t});\n\tif (!apiKey) {\n\t\tthrow new Error(\n\t\t\t\"Mistral API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"mistralApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set MISTRAL_API_KEY environment variable\\n\" +\n\t\t\t\"Get a key at https://console.mistral.ai/api-keys\",\n\t\t);\n\t}\n\treturn apiKey;\n}\n\nexport function isMistralAvailable(): boolean {\n\ttry {\n\t\tconst config = loadConfig();\n\t\tresolveSearchModel(config.mistralSearchModel);\n\t\tresolveSearchTool(config.mistralSearchTool);\n\t\treturn hasCredentialSource({\n\t\t\tprovider: \"Mistral\",\n\t\t\tconfiguredValue: config.mistralApiKey,\n\t\t\tenvironmentValue: process.env.MISTRAL_API_KEY,\n\t\t});\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport async function searchWithMistral(query: string, options: SearchOptions = {}): Promise<SearchResponse> {\n\tconst config = loadConfig();\n\tconst model = resolveSearchModel(config.mistralSearchModel);\n\tconst tool = resolveSearchTool(config.mistralSearchTool);\n\tconst numResults = normalizeCount(options.numResults);\n\tconst apiKey = await getApiKey(options.signal);\n\tconst requestSignal = options.signal\n\t\t? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal])\n\t\t: AbortSignal.timeout(SEARCH_TIMEOUT_MS);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\n\ttry {\n\t\tconst response = await fetch(MISTRAL_CONVERSATIONS_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tinputs: [{ role: \"user\", content: buildSearchPrompt(query, options, numResults) }],\n\t\t\t\tstream: false,\n\t\t\t\tmodel,\n\t\t\t\ttools: [{ type: tool }],\n\t\t\t}),\n\t\t\tsignal: requestSignal,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\t\tthrow new Error(`Mistral API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t\t}\n\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = await response.json();\n\t\t} catch (err) {\n\t\t\tthrow new Error(`Mistral API returned invalid JSON: ${errorMessage(err)}`);\n\t\t}\n\t\tconst result = parseConversationResponse(parsed, options, numResults);\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\treturn result;\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, redactedMessage);\n\t\t}\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n"]}
1
+ {"version":3,"file":"mistral-search.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/mistral-search.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { normalizeDomain } from \"./domain-filter-normalization.ts\";\nimport type { SearchOptions, SearchResponse, SearchResult } from \"./perplexity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst MISTRAL_CONVERSATIONS_URL = \"https://api.mistral.ai/v1/conversations\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\nconst DEFAULT_SEARCH_MODEL = \"mistral-small-latest\";\nconst DEFAULT_SEARCH_TOOL = \"web_search\";\nconst MAX_RESULTS = 20;\n\ntype MistralSearchTool = \"web_search\" | \"web_search_premium\";\n\ninterface WebSearchConfig {\n\tmistralApiKey?: unknown;\n\tmistralSearchModel?: unknown;\n\tmistralSearchTool?: unknown;\n}\n\ninterface DomainFilters {\n\tinclude: string[];\n\texclude: string[];\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nfunction resolveSearchModel(value: unknown): string {\n\tif (value === undefined) return DEFAULT_SEARCH_MODEL;\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\tthrow new Error(`mistralSearchModel in ${CONFIG_PATH} must be a non-empty string`);\n\t}\n\treturn value.trim();\n}\n\nfunction resolveSearchTool(value: unknown): MistralSearchTool {\n\tif (value === undefined) return DEFAULT_SEARCH_TOOL;\n\tif (value !== \"web_search\" && value !== \"web_search_premium\") {\n\t\tthrow new Error(`mistralSearchTool in ${CONFIG_PATH} must be either web_search or web_search_premium`);\n\t}\n\treturn value;\n}\n\nfunction normalizeCount(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), MAX_RESULTS));\n}\n\nfunction parseDomainFilters(domainFilter: string[] | undefined): DomainFilters {\n\tconst filters: DomainFilters = { include: [], exclude: [] };\n\tfor (const raw of domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? filters.exclude : filters.include;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn filters;\n}\n\nfunction passesDomainFilters(url: string, filters: DomainFilters): boolean {\n\tif (filters.include.length === 0 && filters.exclude.length === 0) return true;\n\tconst hostname = new URL(url).hostname.toLowerCase();\n\tconst matches = (domain: string) => hostname === domain || hostname.endsWith(`.${domain}`);\n\tif (filters.exclude.some(matches)) return false;\n\treturn filters.include.length === 0 || filters.include.some(matches);\n}\n\nfunction normalizeResultUrl(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst url = value.trim();\n\tif (!url) return null;\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") return null;\n\t} catch {\n\t\treturn null;\n\t}\n\treturn url;\n}\n\nfunction buildSearchPrompt(query: string, options: SearchOptions, numResults: number): string {\n\tconst lines: string[] = [];\n\tif (options.recencyFilter) {\n\t\tconst labels: Record<string, string> = {\n\t\t\tday: \"past 24 hours\",\n\t\t\tweek: \"past week\",\n\t\t\tmonth: \"past month\",\n\t\t\tyear: \"past year\",\n\t\t};\n\t\tlines.push(`Prefer sources from the ${labels[options.recencyFilter] ?? options.recencyFilter}.`);\n\t}\n\tif (typeof options.numResults === \"number\" && Number.isFinite(options.numResults) && options.numResults > 0) {\n\t\tlines.push(`Prefer up to ${numResults} distinct sources.`);\n\t}\n\n\tconst filters = parseDomainFilters(options.domainFilter);\n\tif (filters.include.length > 0) lines.push(`Only use sources from: ${filters.include.slice(0, 100).join(\", \")}.`);\n\tif (filters.exclude.length > 0) lines.push(`Do not use sources from: ${filters.exclude.slice(0, 100).join(\", \")}.`);\n\treturn lines.length > 0 ? `${lines.join(\" \")}\\n\\n${query}` : query;\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction invalidResponse(message: string): Error {\n\treturn new Error(`Mistral API returned invalid response: ${message}`);\n}\n\nfunction parseConversationResponse(value: unknown, options: SearchOptions, numResults: number): SearchResponse {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow invalidResponse(\"expected an object envelope\");\n\t}\n\tconst outputs = (value as Record<string, unknown>).outputs;\n\tif (!Array.isArray(outputs)) throw invalidResponse(\"outputs must be an array\");\n\n\tconst answerParts: string[] = [];\n\tconst results: SearchResult[] = [];\n\tconst seenUrls = new Set<string>();\n\tconst domainFilters = parseDomainFilters(options.domainFilter);\n\n\tfor (const output of outputs) {\n\t\tif (!output || typeof output !== \"object\" || Array.isArray(output)) continue;\n\t\tconst entry = output as Record<string, unknown>;\n\t\tif (entry.type !== \"message.output\") continue;\n\t\tconst content = entry.content;\n\t\tif (typeof content === \"string\") {\n\t\t\tif (content.trim()) answerParts.push(content.trim());\n\t\t\tcontinue;\n\t\t}\n\t\tif (!Array.isArray(content)) continue;\n\n\t\tfor (const chunk of content) {\n\t\t\tif (!chunk || typeof chunk !== \"object\" || Array.isArray(chunk)) continue;\n\t\t\tconst part = chunk as Record<string, unknown>;\n\t\t\tif (part.type === \"text\") {\n\t\t\t\tif (typeof part.text === \"string\" && part.text.trim()) answerParts.push(part.text.trim());\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (part.type !== \"tool_reference\" || results.length >= numResults) continue;\n\n\t\t\tconst url = normalizeResultUrl(part.url);\n\t\t\tif (!url || !passesDomainFilters(url, domainFilters) || seenUrls.has(url)) continue;\n\t\t\tseenUrls.add(url);\n\t\t\tconst title = typeof part.title === \"string\" && part.title.trim() ? part.title.trim() : url;\n\t\t\tconst snippet = typeof part.description === \"string\" ? part.description : \"\";\n\t\t\tresults.push({ title, url, snippet });\n\t\t}\n\t}\n\n\tconst answer = answerParts.join(\"\\n\").trim();\n\tif (!answer && results.length === 0) throw invalidResponse(\"no answer or sources\");\n\treturn { answer, results };\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst apiKey = await resolveCredential({\n\t\tprovider: \"Mistral\",\n\t\tconfiguredValue: loadConfig().mistralApiKey,\n\t\tenvironmentValue: process.env.MISTRAL_API_KEY,\n\t\tsignal,\n\t});\n\tif (!apiKey) {\n\t\tthrow new Error(\n\t\t\t\"Mistral API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"mistralApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set MISTRAL_API_KEY environment variable\\n\" +\n\t\t\t\"Get a key at https://console.mistral.ai/api-keys\",\n\t\t);\n\t}\n\treturn apiKey;\n}\n\nexport function isMistralAvailable(): boolean {\n\ttry {\n\t\tconst config = loadConfig();\n\t\tresolveSearchModel(config.mistralSearchModel);\n\t\tresolveSearchTool(config.mistralSearchTool);\n\t\treturn hasCredentialSource({\n\t\t\tprovider: \"Mistral\",\n\t\t\tconfiguredValue: config.mistralApiKey,\n\t\t\tenvironmentValue: process.env.MISTRAL_API_KEY,\n\t\t});\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport async function searchWithMistral(query: string, options: SearchOptions = {}): Promise<SearchResponse> {\n\tconst config = loadConfig();\n\tconst model = resolveSearchModel(config.mistralSearchModel);\n\tconst tool = resolveSearchTool(config.mistralSearchTool);\n\tconst numResults = normalizeCount(options.numResults);\n\tconst apiKey = await getApiKey(options.signal);\n\tconst requestSignal = options.signal\n\t\t? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal])\n\t\t: AbortSignal.timeout(SEARCH_TIMEOUT_MS);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\n\ttry {\n\t\tconst response = await fetch(MISTRAL_CONVERSATIONS_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tinputs: [{ role: \"user\", content: buildSearchPrompt(query, options, numResults) }],\n\t\t\t\tstream: false,\n\t\t\t\tmodel,\n\t\t\t\ttools: [{ type: tool }],\n\t\t\t}),\n\t\t\tsignal: requestSignal,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\t\tthrow new Error(`Mistral API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t\t}\n\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = await response.json();\n\t\t} catch (err) {\n\t\t\tthrow new Error(`Mistral API returned invalid JSON: ${errorMessage(err)}`);\n\t\t}\n\t\tconst result = parseConversationResponse(parsed, options, numResults);\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\treturn result;\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, redactedMessage);\n\t\t}\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/ollama.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAErE,OAAO,EAAgG,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AA4BrJ,UAAU,mBAAoB,SAAQ,aAAa;IAClD,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,QAAQ,CAAC;IACzF,IAAI,CAAC,EAAE,UAAU,CAAC;CAClB;AA2FD,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,cAAc,CAAC,CAgDhH;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAoD/I"}
1
+ {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/ollama.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGrE,OAAO,EAAgG,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AA4BrJ,UAAU,mBAAoB,SAAQ,aAAa;IAClD,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,QAAQ,CAAC;IACzF,IAAI,CAAC,EAAE,UAAU,CAAC;CAClB;AAqFD,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,cAAc,CAAC,CAgDhH;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAoD/I"}
@@ -1,5 +1,6 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { activityMonitor } from "./activity.js";
3
+ import { formatSearchResultsAsAnswer } from "./search-answer-formatting.js";
3
4
  import { hasCredentialSource, redactCredential, resolveCredential } from "./credential-source.js";
4
5
  import { fetchRemoteUrl, loadFetchContentDomainPolicy, loadSsrfConfig, validateRemoteUrl } from "./ssrf-protection.js";
5
6
  import { getWebSearchConfigPath } from "./utils.js";
@@ -90,11 +91,6 @@ function parseFetchResponse(value) {
90
91
  throw invalidResponse("expected content string");
91
92
  return { title: envelope.title, content: envelope.content, links: envelope.links };
92
93
  }
93
- function buildAnswer(results) {
94
- return results.map((result) => result.snippet
95
- ? `${result.snippet}\nSource: ${result.title} (${result.url})`
96
- : `Source: ${result.title} (${result.url})`).join("\n\n");
97
- }
98
94
  export function isOllamaAvailable() {
99
95
  return hasCredentialSource({ provider: "Ollama", configuredValue: loadConfig().ollamaApiKey, environmentValue: process.env.OLLAMA_API_KEY });
100
96
  }
@@ -141,7 +137,7 @@ export async function searchWithOllama(query, options = {}) {
141
137
  const data = parseSearchResponse(rawData);
142
138
  activityMonitor.logComplete(activityId, response.status);
143
139
  const results = data.results.slice(0, numResults).map((result) => ({ title: result.title, url: result.url, snippet: result.content }));
144
- const mapped = { answer: buildAnswer(results), results };
140
+ const mapped = { answer: formatSearchResultsAsAnswer(results), results };
145
141
  if (options.includeContent) {
146
142
  const inlineContent = data.results.slice(0, numResults)
147
143
  .filter(result => result.content.trim().length > 0)
@@ -1 +1 @@
1
- {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/ollama.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 { fetchRemoteUrl, loadFetchContentDomainPolicy, loadSsrfConfig, validateRemoteUrl, type Lookup, type SsrfConfig } from \"./ssrf-protection.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst OLLAMA_SEARCH_URL = \"https://ollama.com/api/web_search\";\nconst OLLAMA_FETCH_URL = \"https://ollama.com/api/web_fetch\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\n\ninterface WebSearchConfig {\n\tollamaApiKey?: unknown;\n}\n\ninterface OllamaSearchResult {\n\ttitle: string;\n\turl: string;\n\tcontent: string;\n}\n\ninterface OllamaSearchResponse {\n\tresults: OllamaSearchResult[];\n}\n\ninterface OllamaFetchResponse {\n\ttitle: string;\n\tcontent: string;\n\tlinks?: unknown;\n}\n\ninterface OllamaSearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\nexport interface OllamaExtractOptions extends Pick<ExtractOptions, \"timeoutMs\" | \"lookup\"> {\n\tssrf?: SsrfConfig;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string | null> {\n\treturn resolveCredential({\n\t\tprovider: \"Ollama\",\n\t\tconfiguredValue: loadConfig().ollamaApiKey,\n\t\tenvironmentValue: process.env.OLLAMA_API_KEY,\n\t\tsignal,\n\t});\n}\n\nasync function requireApiKey(signal?: AbortSignal): Promise<string> {\n\tconst apiKey = await getApiKey(signal);\n\tif (!apiKey) {\n\t\tthrow new Error(\n\t\t\t\"Ollama API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"ollamaApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set OLLAMA_API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://ollama.com/settings/keys\",\n\t\t);\n\t}\n\treturn apiKey;\n}\n\nfunction normalizeCount(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 10));\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction invalidResponse(message: string): Error {\n\treturn new Error(`Ollama API returned invalid response: ${message}`);\n}\n\nfunction parseSearchResponse(value: unknown): OllamaSearchResponse {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(\"expected an object envelope\");\n\tconst envelope = value as Record<string, unknown>;\n\tif (!Array.isArray(envelope.results)) throw invalidResponse(\"expected results array\");\n\tconst results: OllamaSearchResult[] = [];\n\tfor (const [index, value] of envelope.results.entries()) {\n\t\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(`expected results[${index}] object`);\n\t\tconst item = value as Record<string, unknown>;\n\t\tif (typeof item.title !== \"string\") throw invalidResponse(`expected results[${index}].title string`);\n\t\tif (typeof item.url !== \"string\" || !item.url) throw invalidResponse(`expected results[${index}].url non-empty string`);\n\t\tif (typeof item.content !== \"string\") throw invalidResponse(`expected results[${index}].content string`);\n\t\tresults.push({ title: item.title, url: item.url, content: item.content });\n\t}\n\treturn { results };\n}\n\nfunction parseFetchResponse(value: unknown): OllamaFetchResponse {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(\"expected fetch object envelope\");\n\tconst envelope = value as Record<string, unknown>;\n\tif (typeof envelope.title !== \"string\") throw invalidResponse(\"expected title string\");\n\tif (typeof envelope.content !== \"string\") throw invalidResponse(\"expected content string\");\n\treturn { title: envelope.title, content: envelope.content, links: envelope.links };\n}\n\nfunction buildAnswer(results: SearchResponse[\"results\"]): string {\n\treturn results.map((result) => result.snippet\n\t\t? `${result.snippet}\\nSource: ${result.title} (${result.url})`\n\t\t: `Source: ${result.title} (${result.url})`).join(\"\\n\\n\");\n}\n\nexport function isOllamaAvailable(): boolean {\n\treturn hasCredentialSource({ provider: \"Ollama\", configuredValue: loadConfig().ollamaApiKey, environmentValue: process.env.OLLAMA_API_KEY });\n}\n\nexport async function searchWithOllama(query: string, options: OllamaSearchOptions = {}): Promise<SearchResponse> {\n\tconst apiKey = await requireApiKey(options.signal);\n\tconst numResults = normalizeCount(options.numResults);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(OLLAMA_SEARCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ query, max_results: numResults }),\n\t\t\tsignal: options.signal ? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal]) : AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Ollama API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Ollama API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\n\tconst data = parseSearchResponse(rawData);\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst results = data.results.slice(0, numResults).map((result) => ({ title: result.title, url: result.url, snippet: result.content }));\n\tconst mapped: SearchResponse = { answer: buildAnswer(results), results };\n\tif (options.includeContent) {\n\t\tconst inlineContent: ExtractedContent[] = data.results.slice(0, numResults)\n\t\t\t.filter(result => result.content.trim().length > 0)\n\t\t\t.map(result => ({ url: result.url, title: result.title, content: result.content, error: null }));\n\t\tif (inlineContent.length > 0) mapped.inlineContent = inlineContent;\n\t}\n\treturn mapped;\n}\n\nexport function isOllamaFetchAvailable(): boolean {\n\treturn isOllamaAvailable();\n}\n\nexport async function extractWithOllama(url: string, signal?: AbortSignal, options: OllamaExtractOptions = {}): Promise<ExtractedContent | null> {\n\tconst ssrf = options.ssrf ?? loadSsrfConfig();\n\tconst domainPolicy = loadFetchContentDomainPolicy();\n\tawait validateRemoteUrl(url, {\n\t\tallowRanges: ssrf.allowRanges,\n\t\ttrustEnvProxy: ssrf.trustEnvProxy,\n\t\tdomainPolicy,\n\t\t...(options.lookup ? { lookup: options.lookup } : {}),\n\t});\n\tconst apiKey = await requireApiKey(signal);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query: `ollama fetch: ${url}` });\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetchRemoteUrl(OLLAMA_FETCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ url }),\n\t\t\tsignal: signal ? AbortSignal.any([AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS), signal]) : AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS),\n\t\t}, {\n\t\t\tallowRanges: ssrf.allowRanges,\n\t\t\ttrustEnvProxy: ssrf.trustEnvProxy,\n\t\t\tonRedirect: ({ from, to, init }) => to.origin === from.origin ? init : { ...init, headers: { \"Content-Type\": \"application/json\" } },\n\t\t\t...(options.lookup ? { lookup: options.lookup } : {}),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Ollama Web Fetch error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Ollama Web Fetch returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\tconst data = parseFetchResponse(rawData);\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst content = data.content.trim();\n\tif (!content) return null;\n\treturn { url, title: data.title, content, error: null };\n}\n"]}
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/ollama.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 { formatSearchResultsAsAnswer } from \"./search-answer-formatting.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { fetchRemoteUrl, loadFetchContentDomainPolicy, loadSsrfConfig, validateRemoteUrl, type Lookup, type SsrfConfig } from \"./ssrf-protection.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst OLLAMA_SEARCH_URL = \"https://ollama.com/api/web_search\";\nconst OLLAMA_FETCH_URL = \"https://ollama.com/api/web_fetch\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\n\ninterface WebSearchConfig {\n\tollamaApiKey?: unknown;\n}\n\ninterface OllamaSearchResult {\n\ttitle: string;\n\turl: string;\n\tcontent: string;\n}\n\ninterface OllamaSearchResponse {\n\tresults: OllamaSearchResult[];\n}\n\ninterface OllamaFetchResponse {\n\ttitle: string;\n\tcontent: string;\n\tlinks?: unknown;\n}\n\ninterface OllamaSearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\nexport interface OllamaExtractOptions extends Pick<ExtractOptions, \"timeoutMs\" | \"lookup\"> {\n\tssrf?: SsrfConfig;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string | null> {\n\treturn resolveCredential({\n\t\tprovider: \"Ollama\",\n\t\tconfiguredValue: loadConfig().ollamaApiKey,\n\t\tenvironmentValue: process.env.OLLAMA_API_KEY,\n\t\tsignal,\n\t});\n}\n\nasync function requireApiKey(signal?: AbortSignal): Promise<string> {\n\tconst apiKey = await getApiKey(signal);\n\tif (!apiKey) {\n\t\tthrow new Error(\n\t\t\t\"Ollama API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"ollamaApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set OLLAMA_API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://ollama.com/settings/keys\",\n\t\t);\n\t}\n\treturn apiKey;\n}\n\nfunction normalizeCount(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 10));\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction invalidResponse(message: string): Error {\n\treturn new Error(`Ollama API returned invalid response: ${message}`);\n}\n\nfunction parseSearchResponse(value: unknown): OllamaSearchResponse {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(\"expected an object envelope\");\n\tconst envelope = value as Record<string, unknown>;\n\tif (!Array.isArray(envelope.results)) throw invalidResponse(\"expected results array\");\n\tconst results: OllamaSearchResult[] = [];\n\tfor (const [index, value] of envelope.results.entries()) {\n\t\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(`expected results[${index}] object`);\n\t\tconst item = value as Record<string, unknown>;\n\t\tif (typeof item.title !== \"string\") throw invalidResponse(`expected results[${index}].title string`);\n\t\tif (typeof item.url !== \"string\" || !item.url) throw invalidResponse(`expected results[${index}].url non-empty string`);\n\t\tif (typeof item.content !== \"string\") throw invalidResponse(`expected results[${index}].content string`);\n\t\tresults.push({ title: item.title, url: item.url, content: item.content });\n\t}\n\treturn { results };\n}\n\nfunction parseFetchResponse(value: unknown): OllamaFetchResponse {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(\"expected fetch object envelope\");\n\tconst envelope = value as Record<string, unknown>;\n\tif (typeof envelope.title !== \"string\") throw invalidResponse(\"expected title string\");\n\tif (typeof envelope.content !== \"string\") throw invalidResponse(\"expected content string\");\n\treturn { title: envelope.title, content: envelope.content, links: envelope.links };\n}\n\nexport function isOllamaAvailable(): boolean {\n\treturn hasCredentialSource({ provider: \"Ollama\", configuredValue: loadConfig().ollamaApiKey, environmentValue: process.env.OLLAMA_API_KEY });\n}\n\nexport async function searchWithOllama(query: string, options: OllamaSearchOptions = {}): Promise<SearchResponse> {\n\tconst apiKey = await requireApiKey(options.signal);\n\tconst numResults = normalizeCount(options.numResults);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(OLLAMA_SEARCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ query, max_results: numResults }),\n\t\t\tsignal: options.signal ? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal]) : AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Ollama API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Ollama API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\n\tconst data = parseSearchResponse(rawData);\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst results = data.results.slice(0, numResults).map((result) => ({ title: result.title, url: result.url, snippet: result.content }));\n\tconst mapped: SearchResponse = { answer: formatSearchResultsAsAnswer(results), results };\n\tif (options.includeContent) {\n\t\tconst inlineContent: ExtractedContent[] = data.results.slice(0, numResults)\n\t\t\t.filter(result => result.content.trim().length > 0)\n\t\t\t.map(result => ({ url: result.url, title: result.title, content: result.content, error: null }));\n\t\tif (inlineContent.length > 0) mapped.inlineContent = inlineContent;\n\t}\n\treturn mapped;\n}\n\nexport function isOllamaFetchAvailable(): boolean {\n\treturn isOllamaAvailable();\n}\n\nexport async function extractWithOllama(url: string, signal?: AbortSignal, options: OllamaExtractOptions = {}): Promise<ExtractedContent | null> {\n\tconst ssrf = options.ssrf ?? loadSsrfConfig();\n\tconst domainPolicy = loadFetchContentDomainPolicy();\n\tawait validateRemoteUrl(url, {\n\t\tallowRanges: ssrf.allowRanges,\n\t\ttrustEnvProxy: ssrf.trustEnvProxy,\n\t\tdomainPolicy,\n\t\t...(options.lookup ? { lookup: options.lookup } : {}),\n\t});\n\tconst apiKey = await requireApiKey(signal);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query: `ollama fetch: ${url}` });\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetchRemoteUrl(OLLAMA_FETCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ url }),\n\t\t\tsignal: signal ? AbortSignal.any([AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS), signal]) : AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS),\n\t\t}, {\n\t\t\tallowRanges: ssrf.allowRanges,\n\t\t\ttrustEnvProxy: ssrf.trustEnvProxy,\n\t\t\tonRedirect: ({ from, to, init }) => to.origin === from.origin ? init : { ...init, headers: { \"Content-Type\": \"application/json\" } },\n\t\t\t...(options.lookup ? { lookup: options.lookup } : {}),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Ollama Web Fetch error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Ollama Web Fetch returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\tconst data = parseFetchResponse(rawData);\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst content = data.content.trim();\n\tif (!content) return null;\n\treturn { url, title: data.title, content, error: null };\n}\n"]}
@@ -1,6 +1,8 @@
1
1
  import type { ExtensionContext } from "../host.ts";
2
2
  import type { SearchOptions, SearchResponse } from "./perplexity.ts";
3
3
  type ProviderHeaders = Record<string, string | null>;
4
+ export declare class OpenAIAlphaSearchUnsupportedError extends Error {
5
+ }
4
6
  interface OpenAIAuth {
5
7
  provider: string;
6
8
  apiKey: string;
@@ -8,6 +10,7 @@ interface OpenAIAuth {
8
10
  headers: ProviderHeaders;
9
11
  responsesUrl: string;
10
12
  useCodexEndpoint?: boolean;
13
+ useProviderBaseUrl?: boolean;
11
14
  }
12
15
  export declare function isCurrentModelHostedSearchEligible(ctx?: Pick<ExtensionContext, "model">): boolean;
13
16
  export declare function resolveOpenAIAuth(ctx?: ExtensionContext, signal?: AbortSignal): Promise<OpenAIAuth | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"openai-search.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/openai-search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAgB,MAAM,iBAAiB,CAAC;AAsCnF,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;AAIrD,UAAU,UAAU;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,eAAe,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC3B;AA+BD,wBAAgB,kCAAkC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GAAG,OAAO,CASjG;AAyKD,wBAAsB,iBAAiB,CAAC,GAAG,CAAC,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAyBrH;AAED,wBAAsB,uBAAuB,CAAC,GAAG,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAetF;AA6RD,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,EAC3B,GAAG,CAAC,EAAE,gBAAgB,GACpB,OAAO,CAAC,cAAc,CAAC,CAWzB;AAED,wBAAsB,4BAA4B,CACjD,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,EAC3B,GAAG,CAAC,EAAE,gBAAgB,GACpB,OAAO,CAAC,cAAc,CAAC,CAIzB"}
1
+ {"version":3,"file":"openai-search.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/openai-search.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGnD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAgB,MAAM,iBAAiB,CAAC;AAwCnF,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;AAIrD,qBAAa,iCAAkC,SAAQ,KAAK;CAAG;AAE/D,UAAU,UAAU;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,eAAe,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;AA+BD,wBAAgB,kCAAkC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GAAG,OAAO,CASjG;AAqMD,wBAAsB,iBAAiB,CAAC,GAAG,CAAC,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CA6BrH;AAED,wBAAsB,uBAAuB,CAAC,GAAG,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAiBtF;AA8XD,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,EAC3B,GAAG,CAAC,EAAE,gBAAgB,GACpB,OAAO,CAAC,cAAc,CAAC,CAWzB;AAED,wBAAsB,4BAA4B,CACjD,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,EAC3B,GAAG,CAAC,EAAE,gBAAgB,GACpB,OAAO,CAAC,cAAc,CAAC,CAIzB"}
@@ -1,5 +1,7 @@
1
+ import { randomUUID } from "node:crypto";
1
2
  import { existsSync, readFileSync } from "node:fs";
2
3
  import { activityMonitor } from "./activity.js";
4
+ import { normalizeDomain } from "./domain-filter-normalization.js";
3
5
  import { hasCredentialSource, redactCredential, resolveCredential } from "./credential-source.js";
4
6
  import { getWebSearchConfigPath } from "./utils.js";
5
7
  const OPENAI_RESPONSES_URL = "https://api.openai.com/v1/responses";
@@ -29,6 +31,8 @@ function pickSearchModel(models) {
29
31
  }
30
32
  class CustomOpenAIBaseUrlError extends Error {
31
33
  }
34
+ export class OpenAIAlphaSearchUnsupportedError extends Error {
35
+ }
32
36
  function resolveCurrentModelSearchTarget(model) {
33
37
  const url = new URL(model.baseUrl);
34
38
  if (url.protocol !== "https:")
@@ -76,24 +80,6 @@ function loadConfig() {
76
80
  throw new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);
77
81
  }
78
82
  }
79
- function normalizeDomain(value) {
80
- let input = value.trim().toLowerCase();
81
- if (!input)
82
- return null;
83
- if (input.startsWith("-"))
84
- input = input.slice(1).trim();
85
- if (!input)
86
- return null;
87
- try {
88
- const parsed = input.includes("://") ? new URL(input) : new URL(`https://${input}`);
89
- input = parsed.hostname;
90
- }
91
- catch {
92
- input = input.split("/")[0]?.split(":")[0] ?? "";
93
- }
94
- input = input.replace(/^\.+|\.+$/g, "");
95
- return /^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/i.test(input) ? input : null;
96
- }
97
83
  function normalizeDomainFilters(domainFilter) {
98
84
  if (!domainFilter?.length)
99
85
  return null;
@@ -157,6 +143,41 @@ function resolveConfiguredResponsesUrl(value) {
157
143
  }
158
144
  return url.toString();
159
145
  }
146
+ function resolveUseProviderBaseUrl(config) {
147
+ if (config.openaiResponsesUrl !== undefined)
148
+ return false;
149
+ const value = config.openaiUseProviderBaseUrl;
150
+ if (value === undefined)
151
+ return false;
152
+ if (typeof value !== "boolean") {
153
+ throw new Error(`openaiUseProviderBaseUrl in ${CONFIG_PATH} must be a boolean`);
154
+ }
155
+ return value;
156
+ }
157
+ function resolveProviderResponsesUrl(baseUrl, useCodexEndpoint) {
158
+ let url;
159
+ try {
160
+ if (typeof baseUrl !== "string" || !baseUrl.trim())
161
+ throw new Error();
162
+ url = new URL(baseUrl.trim());
163
+ if (url.protocol !== "https:" && url.protocol !== "http:")
164
+ throw new Error();
165
+ }
166
+ catch {
167
+ throw new CustomOpenAIBaseUrlError("OpenAI search configuration: openaiUseProviderBaseUrl requires an absolute http(s) provider baseUrl");
168
+ }
169
+ const path = url.pathname.replace(/\/+$/u, "");
170
+ if (path.endsWith("/responses")) {
171
+ url.pathname = path;
172
+ }
173
+ else if (useCodexEndpoint && url.hostname.toLowerCase() === "chatgpt.com" && path === "/backend-api") {
174
+ url.pathname = "/backend-api/codex/responses";
175
+ }
176
+ else {
177
+ url.pathname = `${path || "/v1"}/responses`;
178
+ }
179
+ return url.toString();
180
+ }
160
181
  function resolveConfiguredSearchProviders(value) {
161
182
  if (value === undefined)
162
183
  return DEFAULT_SEARCH_PROVIDERS;
@@ -181,8 +202,9 @@ function toRequestHeaders(headers) {
181
202
  }
182
203
  return requestHeaders;
183
204
  }
184
- async function resolvePiAuth(ctx, responsesUrl, providers, modelOverride, hasExplicitResponsesUrl = false) {
205
+ async function resolvePiAuth(ctx, responsesUrl, providers, modelOverride, hasExplicitResponsesUrl = false, useProviderBaseUrl = false) {
185
206
  let models;
207
+ let invalidProviderUrlError;
186
208
  try {
187
209
  models = ctx.modelRegistry.getAll();
188
210
  }
@@ -206,7 +228,7 @@ async function resolvePiAuth(ctx, responsesUrl, providers, modelOverride, hasExp
206
228
  // support from a gateway URL, or pair its credential with the official API.
207
229
  const baseUrl = resolved.baseUrl ?? preferred.baseUrl;
208
230
  const useCodexEndpoint = provider === "openai-codex" || isCodexJwt(resolved.apiKey);
209
- if (!hasExplicitResponsesUrl && !useCodexEndpoint && baseUrl !== undefined) {
231
+ if (!hasExplicitResponsesUrl && !useProviderBaseUrl && !useCodexEndpoint && baseUrl !== undefined) {
210
232
  let isOfficial = false;
211
233
  try {
212
234
  isOfficial = new URL(baseUrl).toString().replace(/\/+$/u, "") === "https://api.openai.com/v1";
@@ -217,26 +239,45 @@ async function resolvePiAuth(ctx, responsesUrl, providers, modelOverride, hasExp
217
239
  throw new CustomOpenAIBaseUrlError(`OpenAI web search cannot reuse Pi credentials with a custom baseUrl by default. Set openaiResponsesUrl in ${CONFIG_PATH} to the full Responses endpoint for this credential.`);
218
240
  }
219
241
  }
242
+ let providerResponsesUrl = responsesUrl;
243
+ if (useProviderBaseUrl) {
244
+ try {
245
+ providerResponsesUrl = resolveProviderResponsesUrl(baseUrl, useCodexEndpoint);
246
+ }
247
+ catch (err) {
248
+ if (!(err instanceof CustomOpenAIBaseUrlError))
249
+ throw err;
250
+ invalidProviderUrlError ??= err;
251
+ continue;
252
+ }
253
+ }
220
254
  return {
221
255
  provider,
222
256
  apiKey: resolved.apiKey,
223
257
  model: modelOverride ?? preferred.id,
224
258
  headers: resolved.headers ?? {},
225
- responsesUrl,
259
+ responsesUrl: providerResponsesUrl,
260
+ ...(useProviderBaseUrl ? { useProviderBaseUrl: true } : {}),
226
261
  };
227
262
  }
263
+ if (invalidProviderUrlError)
264
+ throw invalidProviderUrlError;
228
265
  return undefined;
229
266
  }
230
267
  export async function resolveOpenAIAuth(ctx, signal) {
231
268
  const config = loadConfig();
232
269
  const responsesUrl = resolveConfiguredResponsesUrl(config.openaiResponsesUrl);
270
+ const useProviderBaseUrl = resolveUseProviderBaseUrl(config);
233
271
  const modelOverride = resolveConfiguredSearchModel(config.openaiSearchModel);
234
272
  const providers = resolveConfiguredSearchProviders(config.openaiSearchProviders);
235
273
  if (ctx) {
236
- const auth = await resolvePiAuth(ctx, responsesUrl, providers, modelOverride, config.openaiResponsesUrl !== undefined);
274
+ const auth = await resolvePiAuth(ctx, responsesUrl, providers, modelOverride, config.openaiResponsesUrl !== undefined, useProviderBaseUrl);
237
275
  if (auth)
238
276
  return auth;
239
277
  }
278
+ if (useProviderBaseUrl) {
279
+ throw new CustomOpenAIBaseUrlError("OpenAI search configuration: openaiUseProviderBaseUrl requires selected Pi provider credentials and a baseUrl; set openaiResponsesUrl for standalone API keys");
280
+ }
240
281
  const hasSource = hasCredentialSource({
241
282
  provider: "OpenAI",
242
283
  configuredValue: config.openaiApiKey,
@@ -257,9 +298,10 @@ export async function resolveOpenAIAuth(ctx, signal) {
257
298
  export async function isOpenAISearchAvailable(ctx) {
258
299
  const config = loadConfig();
259
300
  const responsesUrl = resolveConfiguredResponsesUrl(config.openaiResponsesUrl);
301
+ const useProviderBaseUrl = resolveUseProviderBaseUrl(config);
260
302
  const providers = resolveConfiguredSearchProviders(config.openaiSearchProviders);
261
303
  try {
262
- if (ctx && await resolvePiAuth(ctx, responsesUrl, providers, undefined, config.openaiResponsesUrl !== undefined))
304
+ if (ctx && await resolvePiAuth(ctx, responsesUrl, providers, undefined, config.openaiResponsesUrl !== undefined, useProviderBaseUrl))
263
305
  return true;
264
306
  }
265
307
  catch (err) {
@@ -267,6 +309,8 @@ export async function isOpenAISearchAvailable(ctx) {
267
309
  return false;
268
310
  throw err;
269
311
  }
312
+ if (useProviderBaseUrl)
313
+ return false;
270
314
  return hasCredentialSource({
271
315
  provider: "OpenAI",
272
316
  configuredValue: config.openaiApiKey,
@@ -480,7 +524,110 @@ function extractAnswer(output) {
480
524
  }
481
525
  return parts.join("\n").trim();
482
526
  }
527
+ function isAlphaSearchEnabled() {
528
+ const value = loadConfig().openaiUseAlphaSearch;
529
+ if (value === undefined)
530
+ return false;
531
+ if (typeof value !== "boolean") {
532
+ throw new Error(`openaiUseAlphaSearch in ${CONFIG_PATH} must be a boolean`);
533
+ }
534
+ return value;
535
+ }
536
+ function resolveAlphaSearchUrl(responsesUrl) {
537
+ const url = new URL(responsesUrl);
538
+ const pathname = url.pathname.replace(/\/+$/u, "");
539
+ if (!pathname.endsWith("/responses")) {
540
+ throw new Error("OpenAI alpha/search configuration: endpoint path must end with /responses");
541
+ }
542
+ url.pathname = `${pathname.slice(0, -"/responses".length)}/alpha/search`;
543
+ return url.toString();
544
+ }
545
+ function buildAlphaSearchBody(query, options, model) {
546
+ const filters = normalizeDomainFilters(options.domainFilter);
547
+ if (filters?.blockedDomains?.length) {
548
+ throw new OpenAIAlphaSearchUnsupportedError("OpenAI alpha/search: unsupported excluded domains; use another search provider or disable openaiUseAlphaSearch");
549
+ }
550
+ const recencyDays = { day: 1, week: 7, month: 30, year: 365 };
551
+ return {
552
+ id: randomUUID(),
553
+ model,
554
+ commands: {
555
+ search_query: [{
556
+ q: query,
557
+ ...(options.recencyFilter ? { recency: recencyDays[options.recencyFilter] } : {}),
558
+ ...(filters?.allowedDomains ? { domains: filters.allowedDomains } : {}),
559
+ }],
560
+ },
561
+ };
562
+ }
563
+ function buildAlphaSearchHeaders(headers, apiKey) {
564
+ const result = new Headers(headers);
565
+ for (const name of ["OpenAI-Beta", "Session_ID", "Conversation_ID", "X-Codex-Beta-Features", "X-Codex-Turn-State", "x-openai-internal-codex-responses-lite"]) {
566
+ result.delete(name);
567
+ }
568
+ result.set("Authorization", `Bearer ${apiKey}`);
569
+ result.set("Content-Type", "application/json");
570
+ result.set("Accept", "application/json");
571
+ result.set("Originator", "codex_cli_rs");
572
+ return result;
573
+ }
574
+ async function parseAlphaSearchResponse(response, numResults = 5) {
575
+ const text = await response.text();
576
+ let payload;
577
+ try {
578
+ payload = JSON.parse(text);
579
+ }
580
+ catch {
581
+ throw new Error("OpenAI alpha/search returned invalid JSON");
582
+ }
583
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
584
+ throw new Error("OpenAI alpha/search returned an invalid response");
585
+ }
586
+ const record = payload;
587
+ const answer = typeof record.output === "string" ? record.output.trim() : "";
588
+ const results = [];
589
+ const seen = new Set();
590
+ for (const item of Array.isArray(record.results) ? record.results : []) {
591
+ if (!item || typeof item !== "object" || item.type !== "text_result" || typeof item.url !== "string")
592
+ continue;
593
+ try {
594
+ const url = new URL(item.url);
595
+ if (url.protocol !== "http:" && url.protocol !== "https:")
596
+ continue;
597
+ }
598
+ catch {
599
+ continue;
600
+ }
601
+ addResult(results, seen, item.url, item.title, typeof item.snippet === "string" ? item.snippet : "");
602
+ }
603
+ if (!answer && results.length === 0) {
604
+ throw new Error("OpenAI alpha/search returned no parseable results or plaintext output");
605
+ }
606
+ return {
607
+ answer,
608
+ results: typeof numResults === "number" && Number.isFinite(numResults) && numResults > 0
609
+ ? results.slice(0, Math.min(Math.floor(numResults), 20))
610
+ : results,
611
+ };
612
+ }
483
613
  async function runOpenAISearch(query, options, auth) {
614
+ const useAlphaSearch = isAlphaSearchEnabled();
615
+ if (useAlphaSearch)
616
+ options.signal?.throwIfAborted();
617
+ const useCodexEndpoint = auth.useCodexEndpoint ?? (auth.provider === "openai-codex" || isCodexJwt(auth.apiKey));
618
+ const responsesUrl = useCodexEndpoint && !auth.useProviderBaseUrl ? CODEX_RESPONSES_URL : auth.responsesUrl;
619
+ const requestUrl = useAlphaSearch ? resolveAlphaSearchUrl(responsesUrl) : responsesUrl;
620
+ const body = useAlphaSearch ? buildAlphaSearchBody(query, options, auth.model) : {
621
+ model: auth.model,
622
+ instructions: buildInstructions(options),
623
+ input: [{ role: "user", content: [{ type: "input_text", text: query }] }],
624
+ tools: [buildWebSearchTool(options)],
625
+ include: ["web_search_call.action.sources"],
626
+ store: false,
627
+ stream: true,
628
+ tool_choice: "required",
629
+ parallel_tool_calls: true,
630
+ };
484
631
  const activityId = activityMonitor.logStart({ type: "api", query });
485
632
  const headers = {
486
633
  ...toRequestHeaders(auth.headers),
@@ -488,28 +635,16 @@ async function runOpenAISearch(query, options, auth) {
488
635
  "Content-Type": "application/json",
489
636
  "OpenAI-Beta": "responses=experimental",
490
637
  };
491
- const useCodexEndpoint = auth.useCodexEndpoint ?? (auth.provider === "openai-codex" || isCodexJwt(auth.apiKey));
492
638
  if (useCodexEndpoint) {
493
639
  const accountId = extractAccountId(auth.apiKey);
494
640
  if (accountId)
495
641
  headers["chatgpt-account-id"] = accountId;
496
642
  headers.originator = "pi";
497
643
  }
498
- const body = {
499
- model: auth.model,
500
- instructions: buildInstructions(options),
501
- input: [{ role: "user", content: [{ type: "input_text", text: query }] }],
502
- tools: [buildWebSearchTool(options)],
503
- include: ["web_search_call.action.sources"],
504
- store: false,
505
- stream: true,
506
- tool_choice: "required",
507
- parallel_tool_calls: true,
508
- };
509
644
  try {
510
- const response = await fetch(useCodexEndpoint ? CODEX_RESPONSES_URL : auth.responsesUrl, {
645
+ const response = await fetch(requestUrl, {
511
646
  method: "POST",
512
- headers,
647
+ headers: useAlphaSearch ? buildAlphaSearchHeaders(headers, auth.apiKey) : headers,
513
648
  body: JSON.stringify(body),
514
649
  signal: options.signal
515
650
  ? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal])
@@ -518,7 +653,15 @@ async function runOpenAISearch(query, options, auth) {
518
653
  if (!response.ok) {
519
654
  activityMonitor.logError(activityId, `HTTP ${response.status}`);
520
655
  const errorText = redactCredential(await response.text(), auth.apiKey);
521
- throw new Error(`OpenAI API error ${response.status}: ${errorText.slice(0, 300)}`);
656
+ const ErrorType = useAlphaSearch && [404, 405, 501].includes(response.status)
657
+ ? OpenAIAlphaSearchUnsupportedError
658
+ : Error;
659
+ throw new ErrorType(`OpenAI ${useAlphaSearch ? "alpha/search " : ""}API error ${response.status}: ${errorText.slice(0, 300)}`);
660
+ }
661
+ if (useAlphaSearch) {
662
+ const result = await parseAlphaSearchResponse(response, options.numResults);
663
+ activityMonitor.logComplete(activityId, response.status);
664
+ return result;
522
665
  }
523
666
  const parsed = await parseOpenAIResponse(response);
524
667
  const output = Array.isArray(parsed.payload.output) ? parsed.payload.output : [];