@humain/terminal 0.2.2 → 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 (156) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/bundle/chunks/{chunk-NMPIM7MN.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-ADQYVZ6A.js → chunk-WKLAQTQ4.js} +104 -128
  5. package/dist/bundle/chunks/{compat-CN7WN6DA.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/core/tools/subagent.d.ts +2 -0
  11. package/dist/core/tools/subagent.d.ts.map +1 -1
  12. package/dist/core/tools/subagent.js +46 -16
  13. package/dist/core/tools/subagent.js.map +1 -1
  14. package/dist/humain/web-access/vendor/anysearch.d.ts.map +1 -1
  15. package/dist/humain/web-access/vendor/anysearch.js +4 -14
  16. package/dist/humain/web-access/vendor/anysearch.js.map +1 -1
  17. package/dist/humain/web-access/vendor/bocha.d.ts.map +1 -1
  18. package/dist/humain/web-access/vendor/bocha.js +3 -24
  19. package/dist/humain/web-access/vendor/bocha.js.map +1 -1
  20. package/dist/humain/web-access/vendor/brave.d.ts.map +1 -1
  21. package/dist/humain/web-access/vendor/brave.js +3 -24
  22. package/dist/humain/web-access/vendor/brave.js.map +1 -1
  23. package/dist/humain/web-access/vendor/brightdata.d.ts.map +1 -1
  24. package/dist/humain/web-access/vendor/brightdata.js +5 -34
  25. package/dist/humain/web-access/vendor/brightdata.js.map +1 -1
  26. package/dist/humain/web-access/vendor/content-find.d.ts.map +1 -1
  27. package/dist/humain/web-access/vendor/content-find.js +186 -51
  28. package/dist/humain/web-access/vendor/content-find.js.map +1 -1
  29. package/dist/humain/web-access/vendor/curator-page.d.ts.map +1 -1
  30. package/dist/humain/web-access/vendor/curator-page.js +4 -1
  31. package/dist/humain/web-access/vendor/curator-page.js.map +1 -1
  32. package/dist/humain/web-access/vendor/curator-run.d.ts.map +1 -1
  33. package/dist/humain/web-access/vendor/curator-run.js +3 -1
  34. package/dist/humain/web-access/vendor/curator-run.js.map +1 -1
  35. package/dist/humain/web-access/vendor/curator-server.d.ts.map +1 -1
  36. package/dist/humain/web-access/vendor/curator-server.js +2 -0
  37. package/dist/humain/web-access/vendor/curator-server.js.map +1 -1
  38. package/dist/humain/web-access/vendor/domain-filter-normalization.d.ts +2 -0
  39. package/dist/humain/web-access/vendor/domain-filter-normalization.d.ts.map +1 -0
  40. package/dist/humain/web-access/vendor/domain-filter-normalization.js +19 -0
  41. package/dist/humain/web-access/vendor/domain-filter-normalization.js.map +1 -0
  42. package/dist/humain/web-access/vendor/duckduckgo.d.ts.map +1 -1
  43. package/dist/humain/web-access/vendor/duckduckgo.js +3 -24
  44. package/dist/humain/web-access/vendor/duckduckgo.js.map +1 -1
  45. package/dist/humain/web-access/vendor/extract.d.ts.map +1 -1
  46. package/dist/humain/web-access/vendor/extract.js +3 -1
  47. package/dist/humain/web-access/vendor/extract.js.map +1 -1
  48. package/dist/humain/web-access/vendor/firecrawl.d.ts.map +1 -1
  49. package/dist/humain/web-access/vendor/firecrawl.js +5 -32
  50. package/dist/humain/web-access/vendor/firecrawl.js.map +1 -1
  51. package/dist/humain/web-access/vendor/gemini-search.d.ts +5 -2
  52. package/dist/humain/web-access/vendor/gemini-search.d.ts.map +1 -1
  53. package/dist/humain/web-access/vendor/gemini-search.js +85 -37
  54. package/dist/humain/web-access/vendor/gemini-search.js.map +1 -1
  55. package/dist/humain/web-access/vendor/index.d.ts +3 -3
  56. package/dist/humain/web-access/vendor/index.d.ts.map +1 -1
  57. package/dist/humain/web-access/vendor/index.js +135 -157
  58. package/dist/humain/web-access/vendor/index.js.map +1 -1
  59. package/dist/humain/web-access/vendor/jina-search.d.ts.map +1 -1
  60. package/dist/humain/web-access/vendor/jina-search.js +4 -14
  61. package/dist/humain/web-access/vendor/jina-search.js.map +1 -1
  62. package/dist/humain/web-access/vendor/kagi.d.ts.map +1 -1
  63. package/dist/humain/web-access/vendor/kagi.js +4 -12
  64. package/dist/humain/web-access/vendor/kagi.js.map +1 -1
  65. package/dist/humain/web-access/vendor/kimi-search.d.ts.map +1 -1
  66. package/dist/humain/web-access/vendor/kimi-search.js +5 -32
  67. package/dist/humain/web-access/vendor/kimi-search.js.map +1 -1
  68. package/dist/humain/web-access/vendor/mistral-search.d.ts.map +1 -1
  69. package/dist/humain/web-access/vendor/mistral-search.js +1 -18
  70. package/dist/humain/web-access/vendor/mistral-search.js.map +1 -1
  71. package/dist/humain/web-access/vendor/ollama.d.ts.map +1 -1
  72. package/dist/humain/web-access/vendor/ollama.js +2 -6
  73. package/dist/humain/web-access/vendor/ollama.js.map +1 -1
  74. package/dist/humain/web-access/vendor/openai-search.d.ts +3 -0
  75. package/dist/humain/web-access/vendor/openai-search.d.ts.map +1 -1
  76. package/dist/humain/web-access/vendor/openai-search.js +181 -38
  77. package/dist/humain/web-access/vendor/openai-search.js.map +1 -1
  78. package/dist/humain/web-access/vendor/opencode-session-headers.d.ts +10 -0
  79. package/dist/humain/web-access/vendor/opencode-session-headers.d.ts.map +1 -0
  80. package/dist/humain/web-access/vendor/opencode-session-headers.js +23 -0
  81. package/dist/humain/web-access/vendor/opencode-session-headers.js.map +1 -0
  82. package/dist/humain/web-access/vendor/page-query.d.ts.map +1 -1
  83. package/dist/humain/web-access/vendor/page-query.js +10 -2
  84. package/dist/humain/web-access/vendor/page-query.js.map +1 -1
  85. package/dist/humain/web-access/vendor/parallel.d.ts.map +1 -1
  86. package/dist/humain/web-access/vendor/parallel.js +1 -18
  87. package/dist/humain/web-access/vendor/parallel.js.map +1 -1
  88. package/dist/humain/web-access/vendor/pdf-extract.d.ts +2 -0
  89. package/dist/humain/web-access/vendor/pdf-extract.d.ts.map +1 -1
  90. package/dist/humain/web-access/vendor/pdf-extract.js +1 -0
  91. package/dist/humain/web-access/vendor/pdf-extract.js.map +1 -1
  92. package/dist/humain/web-access/vendor/querit.d.ts.map +1 -1
  93. package/dist/humain/web-access/vendor/querit.js +5 -32
  94. package/dist/humain/web-access/vendor/querit.js.map +1 -1
  95. package/dist/humain/web-access/vendor/search-answer-formatting.d.ts +8 -0
  96. package/dist/humain/web-access/vendor/search-answer-formatting.d.ts.map +1 -0
  97. package/dist/humain/web-access/vendor/search-answer-formatting.js +6 -0
  98. package/dist/humain/web-access/vendor/search-answer-formatting.js.map +1 -0
  99. package/dist/humain/web-access/vendor/search-result-count-normalization.d.ts +2 -0
  100. package/dist/humain/web-access/vendor/search-result-count-normalization.d.ts.map +1 -0
  101. package/dist/humain/web-access/vendor/search-result-count-normalization.js +6 -0
  102. package/dist/humain/web-access/vendor/search-result-count-normalization.js.map +1 -0
  103. package/dist/humain/web-access/vendor/search1api.d.ts.map +1 -1
  104. package/dist/humain/web-access/vendor/search1api.js +5 -32
  105. package/dist/humain/web-access/vendor/search1api.js.map +1 -1
  106. package/dist/humain/web-access/vendor/searchinfinity.d.ts.map +1 -1
  107. package/dist/humain/web-access/vendor/searchinfinity.js +5 -32
  108. package/dist/humain/web-access/vendor/searchinfinity.js.map +1 -1
  109. package/dist/humain/web-access/vendor/searxng.d.ts.map +1 -1
  110. package/dist/humain/web-access/vendor/searxng.js +3 -24
  111. package/dist/humain/web-access/vendor/searxng.js.map +1 -1
  112. package/dist/humain/web-access/vendor/serpapi.d.ts.map +1 -1
  113. package/dist/humain/web-access/vendor/serpapi.js +5 -30
  114. package/dist/humain/web-access/vendor/serpapi.js.map +1 -1
  115. package/dist/humain/web-access/vendor/serpbase.d.ts.map +1 -1
  116. package/dist/humain/web-access/vendor/serpbase.js +3 -24
  117. package/dist/humain/web-access/vendor/serpbase.js.map +1 -1
  118. package/dist/humain/web-access/vendor/serpdive.d.ts.map +1 -1
  119. package/dist/humain/web-access/vendor/serpdive.js +3 -24
  120. package/dist/humain/web-access/vendor/serpdive.js.map +1 -1
  121. package/dist/humain/web-access/vendor/serper.d.ts.map +1 -1
  122. package/dist/humain/web-access/vendor/serper.js +5 -30
  123. package/dist/humain/web-access/vendor/serper.js.map +1 -1
  124. package/dist/humain/web-access/vendor/serply.d.ts +4 -0
  125. package/dist/humain/web-access/vendor/serply.d.ts.map +1 -0
  126. package/dist/humain/web-access/vendor/serply.js +191 -0
  127. package/dist/humain/web-access/vendor/serply.js.map +1 -0
  128. package/dist/humain/web-access/vendor/source-check.d.ts.map +1 -1
  129. package/dist/humain/web-access/vendor/source-check.js +11 -47
  130. package/dist/humain/web-access/vendor/source-check.js.map +1 -1
  131. package/dist/humain/web-access/vendor/summary-review.d.ts +1 -1
  132. package/dist/humain/web-access/vendor/summary-review.d.ts.map +1 -1
  133. package/dist/humain/web-access/vendor/summary-review.js +6 -2
  134. package/dist/humain/web-access/vendor/summary-review.js.map +1 -1
  135. package/dist/humain/web-access/vendor/tavily.d.ts.map +1 -1
  136. package/dist/humain/web-access/vendor/tavily.js +3 -24
  137. package/dist/humain/web-access/vendor/tavily.js.map +1 -1
  138. package/dist/humain/web-access/vendor/tinyfish.d.ts.map +1 -1
  139. package/dist/humain/web-access/vendor/tinyfish.js +5 -32
  140. package/dist/humain/web-access/vendor/tinyfish.js.map +1 -1
  141. package/dist/humain/web-access/vendor/utils.d.ts.map +1 -1
  142. package/dist/humain/web-access/vendor/utils.js +2 -0
  143. package/dist/humain/web-access/vendor/utils.js.map +1 -1
  144. package/dist/humain/web-access/vendor/valyu.d.ts.map +1 -1
  145. package/dist/humain/web-access/vendor/valyu.js +5 -30
  146. package/dist/humain/web-access/vendor/valyu.js.map +1 -1
  147. package/dist/humain/web-access/vendor/xai-search.d.ts.map +1 -1
  148. package/dist/humain/web-access/vendor/xai-search.js +1 -18
  149. package/dist/humain/web-access/vendor/xai-search.js.map +1 -1
  150. package/dist/humain/web-access/vendor/xcrawl.d.ts.map +1 -1
  151. package/dist/humain/web-access/vendor/xcrawl.js +5 -34
  152. package/dist/humain/web-access/vendor/xcrawl.js.map +1 -1
  153. package/npm-shrinkwrap.json +6 -6
  154. package/package.json +2 -2
  155. package/src/humain/web-access/UPSTREAM.md +33 -1
  156. package/src/humain/web-access/upstream.json +6 -5
@@ -1 +1 @@
1
- {"version":3,"file":"xai-search.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/xai-search.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport type { ExtensionContext } from \"../host.ts\";\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\n// xAI's Agent Tools API: hosted `web_search` and opt-in `x_search` tools on an\n// OpenAI-compatible Responses endpoint. The search runs inside xAI's own inference, so — unlike\n// every keyed backend here — it is paid for by whatever credential answers for\n// the model, including a SuperGrok / X Premium subscription resolved through\n// pi's model registry.\n//\n// Note for anyone extending this: xAI's older Live Search (`search_parameters`\n// on /v1/chat/completions) is GONE. It now answers 410 with \"Live search is\n// deprecated. Please switch to the Agent Tools API\". Do not add it back.\n//\n// The request body is deliberately minimal — model, input, tools — because that\n// is the shape verified against a live subscription account. `stream`,\n// `include`, `tool_choice` and `parallel_tool_calls` are all sent by the OpenAI\n// backend but were NOT verified here, and a 400 from an unsupported field would\n// cost the user their search. Responses API inline citations are enabled by\n// default; sources may also come back in a search call's `action.sources`.\n\nconst XAI_RESPONSES_URL = \"https://api.x.ai/v1/responses\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\n\n// Ordered best-first. pi's builtin xai catalog is small and xAI retires models\n// briskly, so this is a preference list, not an assumption: the first one the\n// registry actually knows wins, and an unknown id is skipped rather than sent.\n// xAI's current X Search docs use grok-4.6. Keep the existing web-only default\n// unchanged, while preferring the documented model when X Search is opted in.\nconst WEB_SEARCH_AUTH_MODEL_CANDIDATES = [\"grok-4.5\", \"grok-4.3\", \"grok-build-0.1\"] as const;\nconst X_SEARCH_AUTH_MODEL_CANDIDATES = [\"grok-4.6\", ...WEB_SEARCH_AUTH_MODEL_CANDIDATES] as const;\n\ntype XaiSearchTool = \"web_search\" | \"x_search\";\nconst DEFAULT_XAI_SEARCH_TOOLS = [\"web_search\"] as const satisfies readonly XaiSearchTool[];\n\ninterface WebSearchConfig {\n\txaiApiKey?: unknown;\n\txaiSearchModel?: unknown;\n\txaiSearchTools?: unknown;\n}\n\ntype ProviderHeaders = Record<string, string | null>;\n\ninterface XaiAuth {\n\tapiKey: string;\n\tmodel: string;\n\theaders: ProviderHeaders;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\ttry {\n\t\tcachedConfig = JSON.parse(raw) as WebSearchConfig;\n\t\treturn cachedConfig;\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n}\n\nfunction resolveConfiguredSearchModel(value: unknown): string | undefined {\n\tif (value == null) return undefined;\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\tthrow new Error(`xaiSearchModel in ${CONFIG_PATH} must be a non-empty string`);\n\t}\n\treturn value.trim();\n}\n\nfunction resolveConfiguredSearchTools(value: unknown): XaiSearchTool[] {\n\tif (value === undefined) return [...DEFAULT_XAI_SEARCH_TOOLS];\n\tif (!Array.isArray(value) || value.length === 0) {\n\t\tthrow new Error(`xaiSearchTools in ${CONFIG_PATH} must be a non-empty array containing only web_search or x_search`);\n\t}\n\n\tconst tools: XaiSearchTool[] = [];\n\tfor (const tool of value) {\n\t\tif (tool !== \"web_search\" && tool !== \"x_search\") {\n\t\t\tthrow new Error(`xaiSearchTools in ${CONFIG_PATH} may only contain web_search or x_search`);\n\t\t}\n\t\tif (tools.includes(tool)) {\n\t\t\tthrow new Error(`xaiSearchTools in ${CONFIG_PATH} must not contain duplicates: ${tool}`);\n\t\t}\n\t\ttools.push(tool);\n\t}\n\treturn tools;\n}\n\nfunction modelCandidatesForTools(tools: readonly XaiSearchTool[]): readonly string[] {\n\treturn tools.includes(\"x_search\") ? X_SEARCH_AUTH_MODEL_CANDIDATES : WEB_SEARCH_AUTH_MODEL_CANDIDATES;\n}\n\nfunction toRequestHeaders(headers: ProviderHeaders): Record<string, string> {\n\tconst requestHeaders: Record<string, string> = {};\n\tfor (const [name, value] of Object.entries(headers)) {\n\t\tif (value !== null) requestHeaders[name] = value;\n\t}\n\treturn requestHeaders;\n}\n\n/**\n * Resolve auth from pi's model registry first, so a Grok subscription pays for\n * its own searches and no api key has to be configured at all. Mirrors how the\n * OpenAI backend picks up a Codex sign-in.\n */\nasync function resolvePiAuth(\n\tctx: ExtensionContext,\n\tmodelOverride: string | undefined,\n\ttools: readonly XaiSearchTool[],\n): Promise<XaiAuth | undefined> {\n\tfor (const modelId of modelCandidatesForTools(tools)) {\n\t\ttry {\n\t\t\tconst model = ctx.modelRegistry.find(\"xai\", modelId);\n\t\t\tif (!model) continue;\n\t\t\tconst resolved = await ctx.modelRegistry.getApiKeyAndHeaders(model);\n\t\t\tif (resolved.ok && resolved.apiKey) {\n\t\t\t\treturn { apiKey: resolved.apiKey, model: modelOverride ?? modelId, headers: resolved.headers ?? {} };\n\t\t\t}\n\t\t} catch {\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport async function resolveXaiAuth(ctx?: ExtensionContext, signal?: AbortSignal): Promise<XaiAuth | undefined> {\n\tconst config = loadConfig();\n\tconst modelOverride = resolveConfiguredSearchModel(config.xaiSearchModel);\n\tconst tools = resolveConfiguredSearchTools(config.xaiSearchTools);\n\tif (ctx) {\n\t\tconst auth = await resolvePiAuth(ctx, modelOverride, tools);\n\t\tif (auth) return auth;\n\t}\n\n\tconst hasSource = hasCredentialSource({\n\t\tprovider: \"xAI\",\n\t\tconfiguredValue: config.xaiApiKey,\n\t\tenvironmentValue: process.env.XAI_API_KEY,\n\t});\n\tif (!hasSource) return undefined;\n\tconst apiKey = await resolveCredential({\n\t\tprovider: \"xAI\",\n\t\tconfiguredValue: config.xaiApiKey,\n\t\tenvironmentValue: process.env.XAI_API_KEY,\n\t\tsignal,\n\t});\n\treturn apiKey ? { apiKey, model: modelOverride ?? modelCandidatesForTools(tools)[0], headers: {} } : undefined;\n}\n\nexport async function isXaiSearchAvailable(ctx?: ExtensionContext): Promise<boolean> {\n\tlet config: WebSearchConfig;\n\tlet tools: XaiSearchTool[];\n\ttry {\n\t\tconfig = loadConfig();\n\t\ttools = resolveConfiguredSearchTools(config.xaiSearchTools);\n\t} catch {\n\t\treturn false;\n\t}\n\tif (ctx && await resolvePiAuth(ctx, undefined, tools)) return true;\n\treturn hasCredentialSource({\n\t\tprovider: \"xAI\",\n\t\tconfiguredValue: config.xaiApiKey,\n\t\tenvironmentValue: process.env.XAI_API_KEY,\n\t});\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\n/**\n * Recency, result count and domain filters are folded into the prompt rather\n * than sent as tool parameters. xAI's filter field names are not verified, and\n * an unknown field risks a 400 that costs the whole search; steering through\n * the instruction text degrades to \"the model ignored it\" instead.\n */\nfunction buildInput(query: string, options: SearchOptions, tools: readonly XaiSearchTool[]): string {\n\tlet searchInstruction: string;\n\tif (tools.includes(\"x_search\") && tools.includes(\"web_search\")) {\n\t\tsearchInstruction = \"Search the web and X and answer using only what the search results say.\";\n\t} else if (tools.includes(\"x_search\")) {\n\t\tsearchInstruction = \"Search X and answer using only what the X results say.\";\n\t} else {\n\t\tsearchInstruction = \"Search the web and answer using only what the web results say.\";\n\t}\n\tconst lines = [\n\t\tsearchInstruction,\n\t\t\"Cite your sources inline.\",\n\t];\n\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]}.`);\n\t}\n\n\tif (typeof options.numResults === \"number\" && Number.isFinite(options.numResults) && options.numResults > 0) {\n\t\tlines.push(`Prefer around ${Math.min(Math.floor(options.numResults), 20)} distinct sources.`);\n\t}\n\n\tconst allowed: string[] = [];\n\tconst blocked: string[] = [];\n\tfor (const raw of options.domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? blocked : allowed;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\tif (allowed.length > 0) lines.push(`Only use sources from: ${allowed.slice(0, 100).join(\", \")}.`);\n\tif (blocked.length > 0) lines.push(`Do not use sources from: ${blocked.slice(0, 100).join(\", \")}.`);\n\n\treturn `${lines.join(\" \")}\\n\\n${query}`;\n}\n\nfunction addResult(results: SearchResult[], seen: Set<string>, url: unknown, title: unknown, snippet = \"\"): void {\n\tif (typeof url !== \"string\" || url.trim().length === 0) return;\n\tif (seen.has(url)) return;\n\tseen.add(url);\n\tresults.push({\n\t\ttitle: typeof title === \"string\" && title.trim().length > 0 ? title : url,\n\t\turl,\n\t\tsnippet,\n\t});\n}\n\nfunction addSource(results: SearchResult[], seen: Set<string>, source: unknown): void {\n\tif (typeof source === \"string\") {\n\t\taddResult(results, seen, source, undefined);\n\t\treturn;\n\t}\n\tif (!source || typeof source !== \"object\") return;\n\tconst record = source as Record<string, unknown>;\n\taddResult(results, seen, record.url ?? record.source_website_url, record.title ?? record.caption);\n}\n\nfunction addSources(results: SearchResult[], seen: Set<string>, sources: unknown): void {\n\tif (!Array.isArray(sources)) return;\n\tfor (const source of sources) addSource(results, seen, source);\n}\n\nfunction extractSnippetAround(text: string, start: unknown, end: unknown): string {\n\tif (typeof start !== \"number\" || typeof end !== \"number\" || !text) return \"\";\n\tconst before = Math.max(0, start - 100);\n\tconst after = Math.min(text.length, end + 100);\n\tconst snippet = text.slice(before, after).replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, \"$1\").trim();\n\treturn snippet.length > 300 ? `${snippet.slice(0, 297)}...` : snippet;\n}\n\nfunction extractAnswer(output: unknown[]): string {\n\tconst parts: string[] = [];\n\tfor (const item of output) {\n\t\tif (!item || typeof item !== \"object\" || (item as { type?: unknown }).type !== \"message\") continue;\n\t\tconst content = (item as { content?: unknown }).content;\n\t\tif (!Array.isArray(content)) continue;\n\t\tfor (const part of content) {\n\t\t\tif (!part || typeof part !== \"object\") continue;\n\t\t\tconst text = (part as { text?: unknown }).text;\n\t\t\tif (typeof text === \"string\" && text.trim().length > 0) parts.push(text);\n\t\t}\n\t}\n\treturn parts.join(\"\\n\").trim();\n}\n\n/**\n * Keep annotation sources first because they carry titles and offsets and must\n * win URL deduplication. Raw source lists from web/X search calls are next,\n * followed by xAI's response-level `citations` URL list. The latter is usually\n * strings, but object entries are tolerated when a compatible gateway adds\n * metadata.\n */\nfunction extractSearchResults(output: unknown[], citations: unknown, numResults: number | undefined): SearchResult[] {\n\tconst results: SearchResult[] = [];\n\tconst seenUrls = new Set<string>();\n\n\tfor (const item of output) {\n\t\tif (!item || typeof item !== \"object\" || (item as { type?: unknown }).type !== \"message\") continue;\n\t\tconst content = (item as { content?: unknown }).content;\n\t\tif (!Array.isArray(content)) continue;\n\t\tfor (const part of content) {\n\t\t\tif (!part || typeof part !== \"object\") continue;\n\t\t\tconst text = typeof (part as { text?: unknown }).text === \"string\" ? (part as { text: string }).text : \"\";\n\t\t\tconst annotations = (part as { annotations?: unknown }).annotations;\n\t\t\tif (!Array.isArray(annotations)) continue;\n\t\t\tfor (const annotation of annotations) {\n\t\t\t\tif (!annotation || typeof annotation !== \"object\") continue;\n\t\t\t\tif ((annotation as { type?: unknown }).type !== \"url_citation\") continue;\n\t\t\t\taddResult(\n\t\t\t\t\tresults,\n\t\t\t\t\tseenUrls,\n\t\t\t\t\t(annotation as { url?: unknown }).url,\n\t\t\t\t\t(annotation as { title?: unknown }).title,\n\t\t\t\t\textractSnippetAround(text, (annotation as { start_index?: unknown }).start_index, (annotation as { end_index?: unknown }).end_index),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const item of output) {\n\t\tif (!item || typeof item !== \"object\") continue;\n\t\tconst type = (item as { type?: unknown }).type;\n\t\tif (type !== \"web_search_call\" && type !== \"x_search_call\") continue;\n\t\tconst value = item as { action?: unknown; sources?: unknown; results?: unknown };\n\t\tconst actionSources = value.action && typeof value.action === \"object\"\n\t\t\t? (value.action as { sources?: unknown }).sources\n\t\t\t: undefined;\n\t\tfor (const group of [actionSources, value.sources, value.results]) addSources(results, seenUrls, group);\n\t}\n\n\taddSources(results, seenUrls, citations);\n\n\tif (typeof numResults === \"number\" && Number.isFinite(numResults) && numResults > 0) {\n\t\treturn results.slice(0, Math.min(Math.floor(numResults), 20));\n\t}\n\treturn results;\n}\n\nexport async function searchWithXai(\n\tquery: string,\n\toptions: SearchOptions = {},\n\tctx?: ExtensionContext,\n): Promise<SearchResponse> {\n\tconst tools = resolveConfiguredSearchTools(loadConfig().xaiSearchTools);\n\tconst auth = await resolveXaiAuth(ctx, options.signal);\n\tif (!auth) {\n\t\tthrow new Error(\n\t\t\t\"xAI search unavailable. Either:\\n\" +\n\t\t\t\" 1. Use /login to sign in with a SuperGrok or X Premium subscription\\n\" +\n\t\t\t` 2. Create ${CONFIG_PATH} with { \"xaiApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 3. Set XAI_API_KEY environment variable\",\n\t\t);\n\t}\n\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\ttry {\n\t\tconst response = await fetch(XAI_RESPONSES_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t...toRequestHeaders(auth.headers),\n\t\t\t\tAuthorization: `Bearer ${auth.apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tmodel: auth.model,\n\t\t\t\tinput: buildInput(query, options, tools),\n\t\t\t\ttools: tools.map((type) => ({ type })),\n\t\t\t}),\n\t\t\tsignal: options.signal\n\t\t\t\t? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal])\n\t\t\t\t: AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tactivityMonitor.logError(activityId, `HTTP ${response.status}`);\n\t\t\tconst errorText = redactCredential(await response.text(), auth.apiKey);\n\t\t\tthrow new Error(`xAI API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t\t}\n\n\t\tlet parsed: Record<string, unknown>;\n\t\ttry {\n\t\t\tparsed = await response.json() as Record<string, unknown>;\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\tthrow new Error(`xAI API returned invalid JSON: ${message}`);\n\t\t}\n\t\tconst output = Array.isArray(parsed.output) ? parsed.output : [];\n\t\tconst answer = extractAnswer(output);\n\t\tconst results = extractSearchResults(output, parsed.citations, options.numResults);\n\n\t\tif (!answer && results.length === 0) {\n\t\t\tthrow new Error(`xAI ${tools.join(\"+\")} returned no answer or sources`);\n\t\t}\n\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\treturn { answer, results };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tconst redactedMessage = redactCredential(message, auth.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":"xai-search.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/xai-search.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport type { ExtensionContext } from \"../host.ts\";\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\n// xAI's Agent Tools API: hosted `web_search` and opt-in `x_search` tools on an\n// OpenAI-compatible Responses endpoint. The search runs inside xAI's own inference, so — unlike\n// every keyed backend here — it is paid for by whatever credential answers for\n// the model, including a SuperGrok / X Premium subscription resolved through\n// pi's model registry.\n//\n// Note for anyone extending this: xAI's older Live Search (`search_parameters`\n// on /v1/chat/completions) is GONE. It now answers 410 with \"Live search is\n// deprecated. Please switch to the Agent Tools API\". Do not add it back.\n//\n// The request body is deliberately minimal — model, input, tools — because that\n// is the shape verified against a live subscription account. `stream`,\n// `include`, `tool_choice` and `parallel_tool_calls` are all sent by the OpenAI\n// backend but were NOT verified here, and a 400 from an unsupported field would\n// cost the user their search. Responses API inline citations are enabled by\n// default; sources may also come back in a search call's `action.sources`.\n\nconst XAI_RESPONSES_URL = \"https://api.x.ai/v1/responses\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\n\n// Ordered best-first. pi's builtin xai catalog is small and xAI retires models\n// briskly, so this is a preference list, not an assumption: the first one the\n// registry actually knows wins, and an unknown id is skipped rather than sent.\n// xAI's current X Search docs use grok-4.6. Keep the existing web-only default\n// unchanged, while preferring the documented model when X Search is opted in.\nconst WEB_SEARCH_AUTH_MODEL_CANDIDATES = [\"grok-4.5\", \"grok-4.3\", \"grok-build-0.1\"] as const;\nconst X_SEARCH_AUTH_MODEL_CANDIDATES = [\"grok-4.6\", ...WEB_SEARCH_AUTH_MODEL_CANDIDATES] as const;\n\ntype XaiSearchTool = \"web_search\" | \"x_search\";\nconst DEFAULT_XAI_SEARCH_TOOLS = [\"web_search\"] as const satisfies readonly XaiSearchTool[];\n\ninterface WebSearchConfig {\n\txaiApiKey?: unknown;\n\txaiSearchModel?: unknown;\n\txaiSearchTools?: unknown;\n}\n\ntype ProviderHeaders = Record<string, string | null>;\n\ninterface XaiAuth {\n\tapiKey: string;\n\tmodel: string;\n\theaders: ProviderHeaders;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\ttry {\n\t\tcachedConfig = JSON.parse(raw) as WebSearchConfig;\n\t\treturn cachedConfig;\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n}\n\nfunction resolveConfiguredSearchModel(value: unknown): string | undefined {\n\tif (value == null) return undefined;\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\tthrow new Error(`xaiSearchModel in ${CONFIG_PATH} must be a non-empty string`);\n\t}\n\treturn value.trim();\n}\n\nfunction resolveConfiguredSearchTools(value: unknown): XaiSearchTool[] {\n\tif (value === undefined) return [...DEFAULT_XAI_SEARCH_TOOLS];\n\tif (!Array.isArray(value) || value.length === 0) {\n\t\tthrow new Error(`xaiSearchTools in ${CONFIG_PATH} must be a non-empty array containing only web_search or x_search`);\n\t}\n\n\tconst tools: XaiSearchTool[] = [];\n\tfor (const tool of value) {\n\t\tif (tool !== \"web_search\" && tool !== \"x_search\") {\n\t\t\tthrow new Error(`xaiSearchTools in ${CONFIG_PATH} may only contain web_search or x_search`);\n\t\t}\n\t\tif (tools.includes(tool)) {\n\t\t\tthrow new Error(`xaiSearchTools in ${CONFIG_PATH} must not contain duplicates: ${tool}`);\n\t\t}\n\t\ttools.push(tool);\n\t}\n\treturn tools;\n}\n\nfunction modelCandidatesForTools(tools: readonly XaiSearchTool[]): readonly string[] {\n\treturn tools.includes(\"x_search\") ? X_SEARCH_AUTH_MODEL_CANDIDATES : WEB_SEARCH_AUTH_MODEL_CANDIDATES;\n}\n\nfunction toRequestHeaders(headers: ProviderHeaders): Record<string, string> {\n\tconst requestHeaders: Record<string, string> = {};\n\tfor (const [name, value] of Object.entries(headers)) {\n\t\tif (value !== null) requestHeaders[name] = value;\n\t}\n\treturn requestHeaders;\n}\n\n/**\n * Resolve auth from pi's model registry first, so a Grok subscription pays for\n * its own searches and no api key has to be configured at all. Mirrors how the\n * OpenAI backend picks up a Codex sign-in.\n */\nasync function resolvePiAuth(\n\tctx: ExtensionContext,\n\tmodelOverride: string | undefined,\n\ttools: readonly XaiSearchTool[],\n): Promise<XaiAuth | undefined> {\n\tfor (const modelId of modelCandidatesForTools(tools)) {\n\t\ttry {\n\t\t\tconst model = ctx.modelRegistry.find(\"xai\", modelId);\n\t\t\tif (!model) continue;\n\t\t\tconst resolved = await ctx.modelRegistry.getApiKeyAndHeaders(model);\n\t\t\tif (resolved.ok && resolved.apiKey) {\n\t\t\t\treturn { apiKey: resolved.apiKey, model: modelOverride ?? modelId, headers: resolved.headers ?? {} };\n\t\t\t}\n\t\t} catch {\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport async function resolveXaiAuth(ctx?: ExtensionContext, signal?: AbortSignal): Promise<XaiAuth | undefined> {\n\tconst config = loadConfig();\n\tconst modelOverride = resolveConfiguredSearchModel(config.xaiSearchModel);\n\tconst tools = resolveConfiguredSearchTools(config.xaiSearchTools);\n\tif (ctx) {\n\t\tconst auth = await resolvePiAuth(ctx, modelOverride, tools);\n\t\tif (auth) return auth;\n\t}\n\n\tconst hasSource = hasCredentialSource({\n\t\tprovider: \"xAI\",\n\t\tconfiguredValue: config.xaiApiKey,\n\t\tenvironmentValue: process.env.XAI_API_KEY,\n\t});\n\tif (!hasSource) return undefined;\n\tconst apiKey = await resolveCredential({\n\t\tprovider: \"xAI\",\n\t\tconfiguredValue: config.xaiApiKey,\n\t\tenvironmentValue: process.env.XAI_API_KEY,\n\t\tsignal,\n\t});\n\treturn apiKey ? { apiKey, model: modelOverride ?? modelCandidatesForTools(tools)[0], headers: {} } : undefined;\n}\n\nexport async function isXaiSearchAvailable(ctx?: ExtensionContext): Promise<boolean> {\n\tlet config: WebSearchConfig;\n\tlet tools: XaiSearchTool[];\n\ttry {\n\t\tconfig = loadConfig();\n\t\ttools = resolveConfiguredSearchTools(config.xaiSearchTools);\n\t} catch {\n\t\treturn false;\n\t}\n\tif (ctx && await resolvePiAuth(ctx, undefined, tools)) return true;\n\treturn hasCredentialSource({\n\t\tprovider: \"xAI\",\n\t\tconfiguredValue: config.xaiApiKey,\n\t\tenvironmentValue: process.env.XAI_API_KEY,\n\t});\n}\n\n/**\n * Recency, result count and domain filters are folded into the prompt rather\n * than sent as tool parameters. xAI's filter field names are not verified, and\n * an unknown field risks a 400 that costs the whole search; steering through\n * the instruction text degrades to \"the model ignored it\" instead.\n */\nfunction buildInput(query: string, options: SearchOptions, tools: readonly XaiSearchTool[]): string {\n\tlet searchInstruction: string;\n\tif (tools.includes(\"x_search\") && tools.includes(\"web_search\")) {\n\t\tsearchInstruction = \"Search the web and X and answer using only what the search results say.\";\n\t} else if (tools.includes(\"x_search\")) {\n\t\tsearchInstruction = \"Search X and answer using only what the X results say.\";\n\t} else {\n\t\tsearchInstruction = \"Search the web and answer using only what the web results say.\";\n\t}\n\tconst lines = [\n\t\tsearchInstruction,\n\t\t\"Cite your sources inline.\",\n\t];\n\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]}.`);\n\t}\n\n\tif (typeof options.numResults === \"number\" && Number.isFinite(options.numResults) && options.numResults > 0) {\n\t\tlines.push(`Prefer around ${Math.min(Math.floor(options.numResults), 20)} distinct sources.`);\n\t}\n\n\tconst allowed: string[] = [];\n\tconst blocked: string[] = [];\n\tfor (const raw of options.domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? blocked : allowed;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\tif (allowed.length > 0) lines.push(`Only use sources from: ${allowed.slice(0, 100).join(\", \")}.`);\n\tif (blocked.length > 0) lines.push(`Do not use sources from: ${blocked.slice(0, 100).join(\", \")}.`);\n\n\treturn `${lines.join(\" \")}\\n\\n${query}`;\n}\n\nfunction addResult(results: SearchResult[], seen: Set<string>, url: unknown, title: unknown, snippet = \"\"): void {\n\tif (typeof url !== \"string\" || url.trim().length === 0) return;\n\tif (seen.has(url)) return;\n\tseen.add(url);\n\tresults.push({\n\t\ttitle: typeof title === \"string\" && title.trim().length > 0 ? title : url,\n\t\turl,\n\t\tsnippet,\n\t});\n}\n\nfunction addSource(results: SearchResult[], seen: Set<string>, source: unknown): void {\n\tif (typeof source === \"string\") {\n\t\taddResult(results, seen, source, undefined);\n\t\treturn;\n\t}\n\tif (!source || typeof source !== \"object\") return;\n\tconst record = source as Record<string, unknown>;\n\taddResult(results, seen, record.url ?? record.source_website_url, record.title ?? record.caption);\n}\n\nfunction addSources(results: SearchResult[], seen: Set<string>, sources: unknown): void {\n\tif (!Array.isArray(sources)) return;\n\tfor (const source of sources) addSource(results, seen, source);\n}\n\nfunction extractSnippetAround(text: string, start: unknown, end: unknown): string {\n\tif (typeof start !== \"number\" || typeof end !== \"number\" || !text) return \"\";\n\tconst before = Math.max(0, start - 100);\n\tconst after = Math.min(text.length, end + 100);\n\tconst snippet = text.slice(before, after).replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, \"$1\").trim();\n\treturn snippet.length > 300 ? `${snippet.slice(0, 297)}...` : snippet;\n}\n\nfunction extractAnswer(output: unknown[]): string {\n\tconst parts: string[] = [];\n\tfor (const item of output) {\n\t\tif (!item || typeof item !== \"object\" || (item as { type?: unknown }).type !== \"message\") continue;\n\t\tconst content = (item as { content?: unknown }).content;\n\t\tif (!Array.isArray(content)) continue;\n\t\tfor (const part of content) {\n\t\t\tif (!part || typeof part !== \"object\") continue;\n\t\t\tconst text = (part as { text?: unknown }).text;\n\t\t\tif (typeof text === \"string\" && text.trim().length > 0) parts.push(text);\n\t\t}\n\t}\n\treturn parts.join(\"\\n\").trim();\n}\n\n/**\n * Keep annotation sources first because they carry titles and offsets and must\n * win URL deduplication. Raw source lists from web/X search calls are next,\n * followed by xAI's response-level `citations` URL list. The latter is usually\n * strings, but object entries are tolerated when a compatible gateway adds\n * metadata.\n */\nfunction extractSearchResults(output: unknown[], citations: unknown, numResults: number | undefined): SearchResult[] {\n\tconst results: SearchResult[] = [];\n\tconst seenUrls = new Set<string>();\n\n\tfor (const item of output) {\n\t\tif (!item || typeof item !== \"object\" || (item as { type?: unknown }).type !== \"message\") continue;\n\t\tconst content = (item as { content?: unknown }).content;\n\t\tif (!Array.isArray(content)) continue;\n\t\tfor (const part of content) {\n\t\t\tif (!part || typeof part !== \"object\") continue;\n\t\t\tconst text = typeof (part as { text?: unknown }).text === \"string\" ? (part as { text: string }).text : \"\";\n\t\t\tconst annotations = (part as { annotations?: unknown }).annotations;\n\t\t\tif (!Array.isArray(annotations)) continue;\n\t\t\tfor (const annotation of annotations) {\n\t\t\t\tif (!annotation || typeof annotation !== \"object\") continue;\n\t\t\t\tif ((annotation as { type?: unknown }).type !== \"url_citation\") continue;\n\t\t\t\taddResult(\n\t\t\t\t\tresults,\n\t\t\t\t\tseenUrls,\n\t\t\t\t\t(annotation as { url?: unknown }).url,\n\t\t\t\t\t(annotation as { title?: unknown }).title,\n\t\t\t\t\textractSnippetAround(text, (annotation as { start_index?: unknown }).start_index, (annotation as { end_index?: unknown }).end_index),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const item of output) {\n\t\tif (!item || typeof item !== \"object\") continue;\n\t\tconst type = (item as { type?: unknown }).type;\n\t\tif (type !== \"web_search_call\" && type !== \"x_search_call\") continue;\n\t\tconst value = item as { action?: unknown; sources?: unknown; results?: unknown };\n\t\tconst actionSources = value.action && typeof value.action === \"object\"\n\t\t\t? (value.action as { sources?: unknown }).sources\n\t\t\t: undefined;\n\t\tfor (const group of [actionSources, value.sources, value.results]) addSources(results, seenUrls, group);\n\t}\n\n\taddSources(results, seenUrls, citations);\n\n\tif (typeof numResults === \"number\" && Number.isFinite(numResults) && numResults > 0) {\n\t\treturn results.slice(0, Math.min(Math.floor(numResults), 20));\n\t}\n\treturn results;\n}\n\nexport async function searchWithXai(\n\tquery: string,\n\toptions: SearchOptions = {},\n\tctx?: ExtensionContext,\n): Promise<SearchResponse> {\n\tconst tools = resolveConfiguredSearchTools(loadConfig().xaiSearchTools);\n\tconst auth = await resolveXaiAuth(ctx, options.signal);\n\tif (!auth) {\n\t\tthrow new Error(\n\t\t\t\"xAI search unavailable. Either:\\n\" +\n\t\t\t\" 1. Use /login to sign in with a SuperGrok or X Premium subscription\\n\" +\n\t\t\t` 2. Create ${CONFIG_PATH} with { \"xaiApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 3. Set XAI_API_KEY environment variable\",\n\t\t);\n\t}\n\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\ttry {\n\t\tconst response = await fetch(XAI_RESPONSES_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t...toRequestHeaders(auth.headers),\n\t\t\t\tAuthorization: `Bearer ${auth.apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tmodel: auth.model,\n\t\t\t\tinput: buildInput(query, options, tools),\n\t\t\t\ttools: tools.map((type) => ({ type })),\n\t\t\t}),\n\t\t\tsignal: options.signal\n\t\t\t\t? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal])\n\t\t\t\t: AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tactivityMonitor.logError(activityId, `HTTP ${response.status}`);\n\t\t\tconst errorText = redactCredential(await response.text(), auth.apiKey);\n\t\t\tthrow new Error(`xAI API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t\t}\n\n\t\tlet parsed: Record<string, unknown>;\n\t\ttry {\n\t\t\tparsed = await response.json() as Record<string, unknown>;\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\tthrow new Error(`xAI API returned invalid JSON: ${message}`);\n\t\t}\n\t\tconst output = Array.isArray(parsed.output) ? parsed.output : [];\n\t\tconst answer = extractAnswer(output);\n\t\tconst results = extractSearchResults(output, parsed.citations, options.numResults);\n\n\t\tif (!answer && results.length === 0) {\n\t\t\tthrow new Error(`xAI ${tools.join(\"+\")} returned no answer or sources`);\n\t\t}\n\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\treturn { answer, results };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tconst redactedMessage = redactCredential(message, auth.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":"xcrawl.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/xcrawl.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA0DrE,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AA2HD,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CA8E1G"}
1
+ {"version":3,"file":"xcrawl.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/xcrawl.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA4DrE,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AA6FD,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CA8E1G"}
@@ -1,5 +1,8 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { activityMonitor } from "./activity.js";
3
+ import { normalizeDomain } from "./domain-filter-normalization.js";
4
+ import { formatSearchResultsAsAnswer } from "./search-answer-formatting.js";
5
+ import { normalizeSearchResultCount } from "./search-result-count-normalization.js";
3
6
  import { hasCredentialSource, redactCredential, resolveCredential } from "./credential-source.js";
4
7
  import { getWebSearchConfigPath } from "./utils.js";
5
8
  const XCRAWL_API_URL = "https://run.xcrawl.com/v1/serp";
@@ -47,11 +50,6 @@ function errorMessage(err) {
47
50
  function invalidResponse(message) {
48
51
  return new Error(`XCrawl API returned invalid response: ${message}`);
49
52
  }
50
- function normalizeCount(value) {
51
- if (typeof value !== "number" || !Number.isFinite(value))
52
- return 5;
53
- return Math.max(1, Math.min(Math.floor(value), 20));
54
- }
55
53
  function hostnameOf(url) {
56
54
  try {
57
55
  return new URL(url).hostname.toLowerCase();
@@ -74,26 +72,6 @@ function absolutizeLink(link) {
74
72
  return link;
75
73
  }
76
74
  }
77
- // Normalize a shared domainFilter entry the same way Valyu does before
78
- // matching: trim, lowercase, strip URL/paths/ports, validate the shape.
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
75
  // XCrawl's SERP API has no server-side domain filter, so apply the shared
98
76
  // include/exclude domainFilter locally instead of returning off-domain results.
99
77
  function applyDomainFilter(results, domainFilter) {
@@ -161,16 +139,9 @@ function parseResponse(value) {
161
139
  }
162
140
  return results;
163
141
  }
164
- function buildAnswer(results) {
165
- return results
166
- .map((result) => result.snippet
167
- ? `${result.snippet}\nSource: ${result.title} (${result.url})`
168
- : `Source: ${result.title} (${result.url})`)
169
- .join("\n\n");
170
- }
171
142
  export async function searchWithXCrawl(query, options = {}) {
172
143
  const apiKey = await getApiKey(options.signal);
173
- const numResults = normalizeCount(options.numResults);
144
+ const numResults = normalizeSearchResultCount(options.numResults);
174
145
  if (!apiKey) {
175
146
  throw new Error("XCrawl search requires an API key. Set xcrawlApiKey in " + CONFIG_PATH +
176
147
  " or export XCRAWL_API_KEY. Get one at https://dash.xcrawl.com/");
@@ -244,7 +215,7 @@ export async function searchWithXCrawl(query, options = {}) {
244
215
  const results = parseResponse(payload);
245
216
  const filtered = (options.domainFilter?.length ? applyDomainFilter(results, options.domainFilter) : results).slice(0, numResults);
246
217
  return {
247
- answer: buildAnswer(filtered),
218
+ answer: formatSearchResultsAsAnswer(filtered),
248
219
  results: filtered,
249
220
  };
250
221
  }
@@ -1 +1 @@
1
- {"version":3,"file":"xcrawl.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/xcrawl.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst XCRAWL_API_URL = \"https://run.xcrawl.com/v1/serp\";\nconst CONFIG_PATH = getWebSearchConfigPath();\n// The SERP API is usually fast (a few seconds, cached responses are quicker),\n// but leave generous headroom before treating a slow job as a provider failure.\nconst SEARCH_TIMEOUT_MS = 60_000;\n\ninterface WebSearchConfig {\n\txcrawlApiKey?: unknown;\n}\n\ninterface XCrawlSerpResult {\n\ttitle?: unknown;\n\tlink?: unknown;\n\tsnippet?: unknown;\n}\n\ninterface XCrawlSerpResponse {\n\tsearch_metadata?: unknown;\n\torganic_results?: unknown;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst 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: \"XCrawl\",\n\t\tconfiguredValue: loadConfig().xcrawlApiKey,\n\t\tenvironmentValue: process.env.XCRAWL_API_KEY,\n\t\tsignal,\n\t});\n}\n\nexport function isXcrawlAvailable(): boolean {\n\treturn hasCredentialSource({ provider: \"XCrawl\", configuredValue: loadConfig().xcrawlApiKey, environmentValue: process.env.XCRAWL_API_KEY });\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(`XCrawl API returned invalid response: ${message}`);\n}\n\nfunction normalizeCount(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 20));\n}\n\nfunction hostnameOf(url: string): string {\n\ttry {\n\t\treturn new URL(url).hostname.toLowerCase();\n\t} catch {\n\t\treturn \"\";\n\t}\n}\n\n// XCrawl's Google SERP results can carry links relative to the API origin\n// (e.g. \"/goto?url=...\" redirect stubs) instead of the documented absolute\n// URLs. Resolve those against the API origin so callers always receive a\n// well-formed absolute URL; absolute http(s) links pass through unchanged.\nfunction absolutizeLink(link: string): string {\n\tif (/^https?:\\/\\//i.test(link)) return link;\n\ttry {\n\t\treturn new URL(link, XCRAWL_API_URL).href;\n\t} catch {\n\t\treturn link;\n\t}\n}\n\n// Normalize a shared domainFilter entry the same way Valyu does before\n// matching: trim, lowercase, strip URL/paths/ports, validate the shape.\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\n// XCrawl's SERP API has no server-side domain filter, so apply the shared\n// include/exclude domainFilter locally instead of returning off-domain results.\nfunction applyDomainFilter(results: SearchResponse[\"results\"], domainFilter: NonNullable<SearchOptions[\"domainFilter\"]>): SearchResponse[\"results\"] {\n\tconst includes: string[] = [];\n\tconst excludes: string[] = [];\n\tfor (const raw of domainFilter) {\n\t\tconst normalized = normalizeDomain(raw);\n\t\tif (!normalized) continue;\n\t\tif (raw.trim().startsWith(\"-\")) excludes.push(normalized);\n\t\telse includes.push(normalized);\n\t}\n\tif (!includes.length && !excludes.length) return results;\n\treturn results.filter((result) => {\n\t\tconst host = hostnameOf(result.url);\n\t\tif (!host) return false;\n\t\tconst matches = (domain: string) => host === domain || host.endsWith(`.${domain}`);\n\t\tif (excludes.some(matches)) return false;\n\t\tif (includes.length && !includes.some(matches)) return false;\n\t\treturn true;\n\t});\n}\n\nfunction parseResponse(value: unknown): SearchResponse[\"results\"] {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow invalidResponse(\"expected an object envelope\");\n\t}\n\tconst envelope = value as XCrawlSerpResponse;\n\tconst metadata = envelope.search_metadata;\n\tif (!metadata || typeof metadata !== \"object\" || Array.isArray(metadata)) {\n\t\tthrow invalidResponse(\"expected search_metadata object\");\n\t}\n\tconst status = (metadata as Record<string, unknown>).status;\n\tif (status !== undefined && status !== \"completed\") {\n\t\tthrow invalidResponse(`expected search_metadata.status \\\"completed\\\", got ${JSON.stringify(status)}`);\n\t}\n\tif (!Array.isArray(envelope.organic_results)) throw invalidResponse(\"expected organic_results array\");\n\n\tconst results: SearchResponse[\"results\"] = [];\n\tfor (const [index, value] of (envelope.organic_results as unknown[]).entries()) {\n\t\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\t\tthrow invalidResponse(`expected organic_results[${index}] object`);\n\t\t}\n\t\tconst result = value as XCrawlSerpResult;\n\t\tconst { title, link, snippet } = result;\n\t\tif (typeof link !== \"string\" || !link.trim()) throw invalidResponse(`expected organic_results[${index}].link to be a non-empty string`);\n\t\tif (title !== null && title !== undefined && typeof title !== \"string\") {\n\t\t\tthrow invalidResponse(`expected organic_results[${index}].title to be a string or null`);\n\t\t}\n\t\tif (snippet !== undefined && snippet !== null && typeof snippet !== \"string\") {\n\t\t\tthrow invalidResponse(`expected organic_results[${index}].snippet to be a string or null`);\n\t\t}\n\t\tconst resolved = absolutizeLink(link.trim());\n\t\tresults.push({\n\t\t\ttitle: typeof title === \"string\" && title.trim().length > 0 ? title : resolved,\n\t\t\turl: resolved,\n\t\t\tsnippet: typeof snippet === \"string\" ? snippet : \"\",\n\t\t});\n\t}\n\n\treturn results;\n}\n\nfunction buildAnswer(results: SearchResponse[\"results\"]): string {\n\treturn results\n\t\t.map((result) => result.snippet\n\t\t\t? `${result.snippet}\\nSource: ${result.title} (${result.url})`\n\t\t\t: `Source: ${result.title} (${result.url})`)\n\t\t.join(\"\\n\\n\");\n}\n\nexport async function searchWithXCrawl(query: string, options: SearchOptions = {}): Promise<SearchResponse> {\n\tconst apiKey = await getApiKey(options.signal);\n\tconst numResults = normalizeCount(options.numResults);\n\tif (!apiKey) {\n\t\tthrow new Error(\n\t\t\t\"XCrawl search requires an API key. Set xcrawlApiKey in \" + CONFIG_PATH +\n\t\t\t\" or export XCRAWL_API_KEY. Get one at https://dash.xcrawl.com/\",\n\t\t);\n\t}\n\tconst body = { engine: \"google_search\", q: query };\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\t// Distinguishing caller cancellation from a provider-side timeout lets the\n\t// timeout surface as a retriable failure instead of looking like an abort.\n\tconst timeoutSignal = AbortSignal.timeout(SEARCH_TIMEOUT_MS);\n\tlet response: Response;\n\n\ttry {\n\t\tresponse = await fetch(XCRAWL_API_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: options.signal\n\t\t\t\t? AbortSignal.any([timeoutSignal, options.signal])\n\t\t\t\t: timeoutSignal,\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tif (options.signal?.aborted) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t\tthrow new Error(\"Aborted\");\n\t\t}\n\t\t// AbortSignal.timeout rejects with a TimeoutError; treat either that\n\t\t// shape or our own fired timer as a retriable provider-side timeout so\n\t\t// routing fallback still applies.\n\t\tconst providerTimeout = timeoutSignal.aborted || (err instanceof Error && err.name === \"TimeoutError\");\n\t\tlet outgoing: Error;\n\t\tif (providerTimeout) {\n\t\t\toutgoing = new Error(`XCrawl search request timed out after ${Math.round(SEARCH_TIMEOUT_MS / 1000)}s`);\n\t\t} else {\n\t\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\t\toutgoing = redactedMessage === message && err instanceof Error ? err : new Error(redactedMessage);\n\t\t\tif (err instanceof Error && outgoing.name === \"Error\") outgoing.name = err.name;\n\t\t}\n\t\tactivityMonitor.logError(activityId, redactCredential(errorMessage(outgoing), apiKey));\n\t\tthrow outgoing;\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\tlet detail = errorText.slice(0, 300);\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(errorText) as { message?: unknown; error?: unknown };\n\t\t\tif (typeof parsed.message === \"string\") detail = parsed.message.slice(0, 300);\n\t\t\telse if (typeof parsed.error === \"string\") detail = parsed.error.slice(0, 300);\n\t\t} catch {\n\t\t\t// keep raw text slice\n\t\t}\n\t\tthrow new Error(`XCrawl API error (${response.status}): ${detail}`);\n\t}\n\tactivityMonitor.logComplete(activityId, response.status);\n\n\tlet payload: unknown;\n\ttry {\n\t\tpayload = await response.json();\n\t} catch (err) {\n\t\tthrow invalidResponse(`response body is not valid JSON: ${errorMessage(err)}`);\n\t}\n\tconst results = parseResponse(payload);\n\tconst filtered = (options.domainFilter?.length ? applyDomainFilter(results, options.domainFilter) : results).slice(0, numResults);\n\n\treturn {\n\t\tanswer: buildAnswer(filtered),\n\t\tresults: filtered,\n\t};\n}\n"]}
1
+ {"version":3,"file":"xcrawl.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/xcrawl.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 } from \"./perplexity.ts\";\nimport { formatSearchResultsAsAnswer } from \"./search-answer-formatting.ts\";\nimport { normalizeSearchResultCount } from \"./search-result-count-normalization.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst XCRAWL_API_URL = \"https://run.xcrawl.com/v1/serp\";\nconst CONFIG_PATH = getWebSearchConfigPath();\n// The SERP API is usually fast (a few seconds, cached responses are quicker),\n// but leave generous headroom before treating a slow job as a provider failure.\nconst SEARCH_TIMEOUT_MS = 60_000;\n\ninterface WebSearchConfig {\n\txcrawlApiKey?: unknown;\n}\n\ninterface XCrawlSerpResult {\n\ttitle?: unknown;\n\tlink?: unknown;\n\tsnippet?: unknown;\n}\n\ninterface XCrawlSerpResponse {\n\tsearch_metadata?: unknown;\n\torganic_results?: unknown;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst 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: \"XCrawl\",\n\t\tconfiguredValue: loadConfig().xcrawlApiKey,\n\t\tenvironmentValue: process.env.XCRAWL_API_KEY,\n\t\tsignal,\n\t});\n}\n\nexport function isXcrawlAvailable(): boolean {\n\treturn hasCredentialSource({ provider: \"XCrawl\", configuredValue: loadConfig().xcrawlApiKey, environmentValue: process.env.XCRAWL_API_KEY });\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(`XCrawl API returned invalid response: ${message}`);\n}\n\nfunction hostnameOf(url: string): string {\n\ttry {\n\t\treturn new URL(url).hostname.toLowerCase();\n\t} catch {\n\t\treturn \"\";\n\t}\n}\n\n// XCrawl's Google SERP results can carry links relative to the API origin\n// (e.g. \"/goto?url=...\" redirect stubs) instead of the documented absolute\n// URLs. Resolve those against the API origin so callers always receive a\n// well-formed absolute URL; absolute http(s) links pass through unchanged.\nfunction absolutizeLink(link: string): string {\n\tif (/^https?:\\/\\//i.test(link)) return link;\n\ttry {\n\t\treturn new URL(link, XCRAWL_API_URL).href;\n\t} catch {\n\t\treturn link;\n\t}\n}\n\n// XCrawl's SERP API has no server-side domain filter, so apply the shared\n// include/exclude domainFilter locally instead of returning off-domain results.\nfunction applyDomainFilter(results: SearchResponse[\"results\"], domainFilter: NonNullable<SearchOptions[\"domainFilter\"]>): SearchResponse[\"results\"] {\n\tconst includes: string[] = [];\n\tconst excludes: string[] = [];\n\tfor (const raw of domainFilter) {\n\t\tconst normalized = normalizeDomain(raw);\n\t\tif (!normalized) continue;\n\t\tif (raw.trim().startsWith(\"-\")) excludes.push(normalized);\n\t\telse includes.push(normalized);\n\t}\n\tif (!includes.length && !excludes.length) return results;\n\treturn results.filter((result) => {\n\t\tconst host = hostnameOf(result.url);\n\t\tif (!host) return false;\n\t\tconst matches = (domain: string) => host === domain || host.endsWith(`.${domain}`);\n\t\tif (excludes.some(matches)) return false;\n\t\tif (includes.length && !includes.some(matches)) return false;\n\t\treturn true;\n\t});\n}\n\nfunction parseResponse(value: unknown): SearchResponse[\"results\"] {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow invalidResponse(\"expected an object envelope\");\n\t}\n\tconst envelope = value as XCrawlSerpResponse;\n\tconst metadata = envelope.search_metadata;\n\tif (!metadata || typeof metadata !== \"object\" || Array.isArray(metadata)) {\n\t\tthrow invalidResponse(\"expected search_metadata object\");\n\t}\n\tconst status = (metadata as Record<string, unknown>).status;\n\tif (status !== undefined && status !== \"completed\") {\n\t\tthrow invalidResponse(`expected search_metadata.status \\\"completed\\\", got ${JSON.stringify(status)}`);\n\t}\n\tif (!Array.isArray(envelope.organic_results)) throw invalidResponse(\"expected organic_results array\");\n\n\tconst results: SearchResponse[\"results\"] = [];\n\tfor (const [index, value] of (envelope.organic_results as unknown[]).entries()) {\n\t\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\t\tthrow invalidResponse(`expected organic_results[${index}] object`);\n\t\t}\n\t\tconst result = value as XCrawlSerpResult;\n\t\tconst { title, link, snippet } = result;\n\t\tif (typeof link !== \"string\" || !link.trim()) throw invalidResponse(`expected organic_results[${index}].link to be a non-empty string`);\n\t\tif (title !== null && title !== undefined && typeof title !== \"string\") {\n\t\t\tthrow invalidResponse(`expected organic_results[${index}].title to be a string or null`);\n\t\t}\n\t\tif (snippet !== undefined && snippet !== null && typeof snippet !== \"string\") {\n\t\t\tthrow invalidResponse(`expected organic_results[${index}].snippet to be a string or null`);\n\t\t}\n\t\tconst resolved = absolutizeLink(link.trim());\n\t\tresults.push({\n\t\t\ttitle: typeof title === \"string\" && title.trim().length > 0 ? title : resolved,\n\t\t\turl: resolved,\n\t\t\tsnippet: typeof snippet === \"string\" ? snippet : \"\",\n\t\t});\n\t}\n\n\treturn results;\n}\n\nexport async function searchWithXCrawl(query: string, options: SearchOptions = {}): Promise<SearchResponse> {\n\tconst apiKey = await getApiKey(options.signal);\n\tconst numResults = normalizeSearchResultCount(options.numResults);\n\tif (!apiKey) {\n\t\tthrow new Error(\n\t\t\t\"XCrawl search requires an API key. Set xcrawlApiKey in \" + CONFIG_PATH +\n\t\t\t\" or export XCRAWL_API_KEY. Get one at https://dash.xcrawl.com/\",\n\t\t);\n\t}\n\tconst body = { engine: \"google_search\", q: query };\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\t// Distinguishing caller cancellation from a provider-side timeout lets the\n\t// timeout surface as a retriable failure instead of looking like an abort.\n\tconst timeoutSignal = AbortSignal.timeout(SEARCH_TIMEOUT_MS);\n\tlet response: Response;\n\n\ttry {\n\t\tresponse = await fetch(XCRAWL_API_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: options.signal\n\t\t\t\t? AbortSignal.any([timeoutSignal, options.signal])\n\t\t\t\t: timeoutSignal,\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tif (options.signal?.aborted) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t\tthrow new Error(\"Aborted\");\n\t\t}\n\t\t// AbortSignal.timeout rejects with a TimeoutError; treat either that\n\t\t// shape or our own fired timer as a retriable provider-side timeout so\n\t\t// routing fallback still applies.\n\t\tconst providerTimeout = timeoutSignal.aborted || (err instanceof Error && err.name === \"TimeoutError\");\n\t\tlet outgoing: Error;\n\t\tif (providerTimeout) {\n\t\t\toutgoing = new Error(`XCrawl search request timed out after ${Math.round(SEARCH_TIMEOUT_MS / 1000)}s`);\n\t\t} else {\n\t\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\t\toutgoing = redactedMessage === message && err instanceof Error ? err : new Error(redactedMessage);\n\t\t\tif (err instanceof Error && outgoing.name === \"Error\") outgoing.name = err.name;\n\t\t}\n\t\tactivityMonitor.logError(activityId, redactCredential(errorMessage(outgoing), apiKey));\n\t\tthrow outgoing;\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\tlet detail = errorText.slice(0, 300);\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(errorText) as { message?: unknown; error?: unknown };\n\t\t\tif (typeof parsed.message === \"string\") detail = parsed.message.slice(0, 300);\n\t\t\telse if (typeof parsed.error === \"string\") detail = parsed.error.slice(0, 300);\n\t\t} catch {\n\t\t\t// keep raw text slice\n\t\t}\n\t\tthrow new Error(`XCrawl API error (${response.status}): ${detail}`);\n\t}\n\tactivityMonitor.logComplete(activityId, response.status);\n\n\tlet payload: unknown;\n\ttry {\n\t\tpayload = await response.json();\n\t} catch (err) {\n\t\tthrow invalidResponse(`response body is not valid JSON: ${errorMessage(err)}`);\n\t}\n\tconst results = parseResponse(payload);\n\tconst filtered = (options.domainFilter?.length ? applyDomainFilter(results, options.domainFilter) : results).slice(0, numResults);\n\n\treturn {\n\t\tanswer: formatSearchResultsAsAnswer(filtered),\n\t\tresults: filtered,\n\t};\n}\n"]}
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@humain/terminal",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@humain/terminal",
9
- "version": "0.2.2",
9
+ "version": "0.3.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@humain/terminal-contracts": "0.2.0",
12
+ "@humain/terminal-contracts": "0.3.0",
13
13
  "@aws-sdk/client-bedrock-runtime": "3.1127.0",
14
14
  "@earendil-works/pi-agent-core": "0.85.1",
15
15
  "@earendil-works/pi-ai": "0.85.1",
@@ -950,9 +950,9 @@
950
950
  "hasInstallScript": true
951
951
  },
952
952
  "node_modules/@humain/terminal-contracts": {
953
- "version": "0.2.0",
954
- "resolved": "https://registry.npmjs.org/@humain/terminal-contracts/-/terminal-contracts-0.2.0.tgz",
955
- "integrity": "sha512-ZMu1vL+ZNtH4rEHqwB5cHBN/BXyhj2DVGMUVwqArUrYXoJZqjNucYUpRYt0/dZ/x+gEZRTC0EvUlYTlPr2SpPg==",
953
+ "version": "0.3.0",
954
+ "resolved": "https://registry.npmjs.org/@humain/terminal-contracts/-/terminal-contracts-0.3.0.tgz",
955
+ "integrity": "sha512-+SIejOs095IxDr3huJCtTP/BrsnRkjfzArKG2GWRbxnDpC+DjQFyzJ/Apl0/CSME+gr5YAsSyx4MjDT7tZnjvA==",
956
956
  "license": "MIT",
957
957
  "dependencies": {
958
958
  "typebox": "1.3.27"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@humain/terminal",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "humainTerminalConfig": {
@@ -67,7 +67,7 @@
67
67
  "prepublishOnly": "npm run clean && npm run build && npm run shrinkwrap"
68
68
  },
69
69
  "dependencies": {
70
- "@humain/terminal-contracts": "0.2.0",
70
+ "@humain/terminal-contracts": "0.3.0",
71
71
  "@aws-sdk/client-bedrock-runtime": "3.1127.0",
72
72
  "@earendil-works/pi-agent-core": "0.85.1",
73
73
  "@earendil-works/pi-ai": "0.85.1",
@@ -1,7 +1,7 @@
1
1
  # pi-web-access upstream tracking
2
2
 
3
3
  The vendored implementation in `vendor/` is based on
4
- [`pi-web-access`](https://github.com/nicobailon/pi-web-access) version `0.29.0`
4
+ [`pi-web-access`](https://github.com/nicobailon/pi-web-access) version `0.30.0`
5
5
  and remains licensed under the upstream MIT license in `vendor/LICENSE`.
6
6
 
7
7
  `upstream.json` records the npm tarball URL, SHA-1 shasum, SHA-512 integrity,
@@ -36,3 +36,35 @@ import behind a lazy `import()`, the HUMAIN host-shim swap moved with it, so
36
36
  `curator-run.ts` now carries a patch and is recorded in `upstream.json`. Other
37
37
  recorded HUMAIN patches remain in place. Mistral and SerpApi are both excluded
38
38
  from automatic all-provider fan-out.
39
+
40
+ The 0.30.0 refresh was reviewed against both published npm tarballs with their
41
+ SHA-1 and SHA-512 metadata verified against the npm registry's own `dist`
42
+ record. Published packages now load a precompiled `dist/` bundle for faster
43
+ startup, while HUMAIN continues to vendor the TypeScript source files
44
+ directly, so this has no effect on the vendored tree. It adds an
45
+ explicit-only Serply Google Search provider, gated on a `serplyApiKey` config
46
+ value or `SERPLY_API_KEY` environment variable and, like SerpApi, absent from
47
+ `ALL_SEARCH_PROVIDERS` so it never runs under `provider: "all"`. It also adds
48
+ two further opt-in OpenAI search options (`openaiUseProviderBaseUrl`,
49
+ `openaiUseAlphaSearch`), a `webSearch.allowedProviders` allowlist, and
50
+ `fetch.defaultMode`/`fetch.allowedModes` controls; none of these change any
51
+ existing default. Fresh installs now default the search-tool `workflow` to
52
+ `none` (no auto-opened curator) instead of `summary-review`; this only
53
+ affects installs with no `workflow` configured; and it makes the tool quieter
54
+ by default, not more active. Upstream also removed the unconditional global
55
+ `fetch` replacement at extension init in favor of installing the proxy
56
+ transport lazily on first proxied call, and generates the search-tool's
57
+ provider-list description directly from `ALL_SEARCH_PROVIDERS` instead of a
58
+ hand-maintained string, closing a prior drift risk between the two. Runtime
59
+ dependencies are unchanged; the only dependency change is a new `esbuild`
60
+ devDependency used solely by the new `dist/` build/publish scripts, which do
61
+ not run against the vendored tree. The MIT license text is unchanged.
62
+
63
+ Upstream also converted the `ExtensionContext` import in the new
64
+ `opencode-session-headers.ts` helper (extracted from `summary-review.ts`'s
65
+ OpenCode attribution-header fix) to source directly from
66
+ `@earendil-works/pi-coding-agent`, so it now carries the HUMAIN host-shim
67
+ patch and is recorded in `upstream.json`, following the same pattern as
68
+ `curator-run.ts` in the 0.29.0 refresh. All other recorded HUMAIN patches
69
+ were reapplied via three-way merge and verified to still isolate to only
70
+ their documented intent.
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "pi-web-access",
3
3
  "repository": "https://github.com/nicobailon/pi-web-access",
4
- "version": "0.29.0",
5
- "tarball": "https://registry.npmjs.org/pi-web-access/-/pi-web-access-0.29.0.tgz",
6
- "shasum": "3b1bf8c63920221f9b34856f1eca65db4b97d3b1",
7
- "integrity": "sha512-1l4sAWYkFhiBynJf/mXuxmCHxjhiAyWJ4rfQVFu8UPa0JQhCS9oXAmNXcL0Q1SfrO00plmb6L4IkypJ3n1Q4Kg==",
4
+ "version": "0.30.0",
5
+ "tarball": "https://registry.npmjs.org/pi-web-access/-/pi-web-access-0.30.0.tgz",
6
+ "shasum": "24c38ce06a5ae4a7fd6d863c422e96d4994ec9a0",
7
+ "integrity": "sha512-BvqLP36JXfH9OBrmLiJ6IXeeCi9LVqJdLxpexeODM+LoVdCBV13vYiVEG8SQ3J+p+egbGmfPxdDQJ6V631LLUg==",
8
8
  "humainPatches": [
9
9
  "extract.ts",
10
10
  "gemini-adc.ts",
@@ -21,6 +21,7 @@
21
21
  "perplexity.ts",
22
22
  "summary-model-scope.ts",
23
23
  "utils.ts",
24
- "curator-run.ts"
24
+ "curator-run.ts",
25
+ "opencode-session-headers.ts"
25
26
  ]
26
27
  }