@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
@@ -9,6 +9,8 @@
9
9
  import { type DatalabMode } from "./datalab-pdf-extract.ts";
10
10
  export interface PDFExtractResult {
11
11
  title: string;
12
+ /** The same Markdown written to outputPath, retained for page answering. */
13
+ content: string;
12
14
  pages: number;
13
15
  chars: number;
14
16
  outputPath: string;
@@ -1 +1 @@
1
- {"version":3,"file":"pdf-extract.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/pdf-extract.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,EAMN,KAAK,WAAW,EAChB,MAAM,0BAA0B,CAAC;AAKlC,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAElE,eAAO,MAAM,mBAAmB,kBAK9B,CAAC;AAEH,MAAM,WAAW,SAAS;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,WAAW,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,eAAO,MAAM,sBAAsB,SAAU,CAAC;AAM9C,wBAAgB,aAAa,IAAI,SAAS,CAqEzC;AAsBD;;GAEG;AACH,wBAAsB,oBAAoB,CACzC,MAAM,EAAE,WAAW,EACnB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,iBAAsB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CA6H3B;AAyGD;;GAEG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAUhE"}
1
+ {"version":3,"file":"pdf-extract.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/pdf-extract.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,EAMN,KAAK,WAAW,EAChB,MAAM,0BAA0B,CAAC;AAKlC,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAElE,eAAO,MAAM,mBAAmB,kBAK9B,CAAC;AAEH,MAAM,WAAW,SAAS;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,WAAW,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,eAAO,MAAM,sBAAsB,SAAU,CAAC;AAM9C,wBAAgB,aAAa,IAAI,SAAS,CAqEzC;AAsBD;;GAEG;AACH,wBAAsB,oBAAoB,CACzC,MAAM,EAAE,WAAW,EACnB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,iBAAsB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CA6H3B;AA0GD;;GAEG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAUhE"}
@@ -241,6 +241,7 @@ async function writeMarkdownResult(options) {
241
241
  await writeFile(outputPath, content, "utf-8");
242
242
  return {
243
243
  title: options.title,
244
+ content,
244
245
  pages: options.pages,
245
246
  chars: content.length,
246
247
  outputPath,
@@ -1 +1 @@
1
- {"version":3,"file":"pdf-extract.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/pdf-extract.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PDF Content Extractor\n *\n * Converts PDFs to Markdown. The `auto` provider chain runs Datalab\n * (deterministic, layout-aware) first, then Gemini API, with unpdf as the\n * deterministic local fallback; the chain can also be pinned with\n * `pdf.provider`.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join, basename } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { CredentialResolutionError } from \"./credential-source.ts\";\nimport {\n\tDATALAB_MODE_VALUES,\n\tDEFAULT_DATALAB_TIMEOUT_MS,\n\tisDatalabApiAvailable,\n\tnormalizeDatalabMode,\n\textractPDFViaDatalab,\n\ttype DatalabMode,\n} from \"./datalab-pdf-extract.ts\";\nimport { isGeminiApiAvailable } from \"./gemini-api.ts\";\nimport { extractPDFViaGemini } from \"./gemini-pdf-extract.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nexport interface PDFExtractResult {\n\ttitle: string;\n\tpages: number;\n\tchars: number;\n\toutputPath: string;\n}\n\nexport interface PDFExtractOptions {\n\tmaxPages?: number;\n\toutputDir?: string;\n\tfilename?: string;\n\tsignal?: AbortSignal;\n\tgeminiTimeoutMs?: number;\n}\n\nexport type PDFProvider = \"auto\" | \"gemini\" | \"datalab\" | \"unpdf\";\n\nexport const PDF_PROVIDER_VALUES = new Set<PDFProvider>([\n\t\"auto\",\n\t\"gemini\",\n\t\"datalab\",\n\t\"unpdf\",\n]);\n\nexport interface PDFConfig {\n\tenabled: boolean;\n\tmaxSizeMB: number;\n\tmaxPages: number;\n\tprovider: PDFProvider;\n\tdatalabMode: DatalabMode;\n\tdatalabTimeoutMs: number;\n}\n\nexport const DEFAULT_PDF_MAX_SIZE_MB = 20;\nexport const MAX_PDF_MAX_SIZE_MB = 50;\nexport const MAX_DATALAB_TIMEOUT_MS = 300_000;\nconst DEFAULT_MAX_PAGES = 100;\nconst DEFAULT_OUTPUT_DIR = join(tmpdir(), \"pi-web-pdf\");\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst PAGE_MARKER_PATTERN = /^<!-- Page (\\d+) -->$/gm;\n\nexport function loadPDFConfig(): PDFConfig {\n\tif (!existsSync(CONFIG_PATH)) {\n\t\treturn {\n\t\t\tenabled: true,\n\t\t\tmaxSizeMB: DEFAULT_PDF_MAX_SIZE_MB,\n\t\t\tmaxPages: DEFAULT_MAX_PAGES,\n\t\t\tprovider: \"auto\",\n\t\t\tdatalabMode: normalizeDatalabMode(process.env.DATALAB_MODE),\n\t\t\tdatalabTimeoutMs: DEFAULT_DATALAB_TIMEOUT_MS,\n\t\t};\n\t}\n\n\tconst rawText = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(rawText) as unknown;\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\n\tconst root =\n\t\traw && typeof raw === \"object\" ? (raw as Record<string, unknown>) : {};\n\tconst pdf =\n\t\troot.pdf && typeof root.pdf === \"object\"\n\t\t\t? (root.pdf as Record<string, unknown>)\n\t\t\t: {};\n\tconst enabled = pdf.enabled !== false;\n\tconst configured = pdf.maxSizeMB;\n\tconst normalized =\n\t\ttypeof configured === \"number\" &&\n\t\tNumber.isFinite(configured) &&\n\t\tconfigured > 0\n\t\t\t? Math.min(configured, MAX_PDF_MAX_SIZE_MB)\n\t\t\t: DEFAULT_PDF_MAX_SIZE_MB;\n\tconst configuredMaxPages = pdf.maxPages;\n\tconst maxPages =\n\t\ttypeof configuredMaxPages === \"number\" &&\n\t\tNumber.isFinite(configuredMaxPages) &&\n\t\tconfiguredMaxPages > 0\n\t\t\t? Math.max(1, Math.floor(configuredMaxPages))\n\t\t\t: DEFAULT_MAX_PAGES;\n\n\tconst provider =\n\t\ttypeof pdf.provider === \"string\" &&\n\t\tPDF_PROVIDER_VALUES.has(pdf.provider as PDFProvider)\n\t\t\t? (pdf.provider as PDFProvider)\n\t\t\t: \"auto\";\n\tconst datalabMode =\n\t\ttypeof pdf.datalabMode === \"string\" &&\n\t\tDATALAB_MODE_VALUES.has(pdf.datalabMode as DatalabMode)\n\t\t\t? (pdf.datalabMode as DatalabMode)\n\t\t\t: normalizeDatalabMode(process.env.DATALAB_MODE);\n\tconst configuredTimeout = pdf.datalabTimeoutMs;\n\tconst datalabTimeoutMs =\n\t\ttypeof configuredTimeout === \"number\" &&\n\t\tNumber.isFinite(configuredTimeout) &&\n\t\tconfiguredTimeout > 0\n\t\t\t? Math.min(configuredTimeout, MAX_DATALAB_TIMEOUT_MS)\n\t\t\t: DEFAULT_DATALAB_TIMEOUT_MS;\n\n\treturn {\n\t\tenabled,\n\t\tmaxSizeMB: normalized,\n\t\tmaxPages,\n\t\tprovider,\n\t\tdatalabMode,\n\t\tdatalabTimeoutMs,\n\t};\n}\n\nasync function getUnpdf() {\n\tif (\n\t\ttypeof (Promise as PromiseConstructor & { try?: unknown }).try !==\n\t\t\"function\"\n\t) {\n\t\tconst { default: promiseTry } = await import(\"promise.try\");\n\t\tpromiseTry.shim();\n\t}\n\n\tconst [unpdf, pdfjs] = await Promise.all([\n\t\timport(\"unpdf\"),\n\t\timport(\"unpdf/pdfjs\"),\n\t]);\n\tconst { VerbosityLevel } = pdfjs as typeof pdfjs & {\n\t\tVerbosityLevel: { ERRORS: number };\n\t};\n\n\treturn { getDocumentProxy: unpdf.getDocumentProxy, VerbosityLevel };\n}\n\n/**\n * Extract text from a PDF buffer and save it to a Markdown file.\n */\nexport async function extractPDFToMarkdown(\n\tbuffer: ArrayBuffer,\n\turl: string,\n\toptions: PDFExtractOptions = {},\n): Promise<PDFExtractResult> {\n\tconst {\n\t\tmaxPages,\n\t\toutputDir = DEFAULT_OUTPUT_DIR,\n\t\tfilename,\n\t\tsignal,\n\t\tgeminiTimeoutMs,\n\t} = options;\n\n\tconst pdfConfig = loadPDFConfig();\n\tconst safeMaxPages =\n\t\tmaxPages === undefined\n\t\t\t? pdfConfig.maxPages\n\t\t\t: Number.isFinite(maxPages)\n\t\t\t\t? Math.max(1, Math.floor(maxPages))\n\t\t\t\t: DEFAULT_MAX_PAGES;\n\tconst urlTitle = extractTitleFromURL(url);\n\tconst provider = pdfConfig.provider;\n\n\tif (provider === \"auto\" || provider === \"datalab\") {\n\t\ttry {\n\t\t\tif (isDatalabApiAvailable()) {\n\t\t\t\tconst result = await extractPDFViaDatalab(buffer, {\n\t\t\t\t\tmaxPages: safeMaxPages,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tmode: pdfConfig.datalabMode,\n\t\t\t\t\ttimeoutMs: pdfConfig.datalabTimeoutMs,\n\t\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\t});\n\t\t\t\treturn writeMarkdownResult({\n\t\t\t\t\tmarkdownBody: result.markdown,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tpages: result.pages,\n\t\t\t\t\toutputDir,\n\t\t\t\t\tfilename,\n\t\t\t\t\turl,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (shouldRethrowExtractionError(err, signal)) throw err;\n\t\t}\n\t}\n\n\tif (provider === \"auto\" || provider === \"gemini\") {\n\t\ttry {\n\t\t\tif (isGeminiApiAvailable()) {\n\t\t\t\tconst markdownBody = await extractPDFViaGemini(buffer, {\n\t\t\t\t\tmaxPages: safeMaxPages,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\t\t...(geminiTimeoutMs !== undefined\n\t\t\t\t\t\t? { timeoutMs: geminiTimeoutMs }\n\t\t\t\t\t\t: {}),\n\t\t\t\t});\n\t\t\t\treturn writeMarkdownResult({\n\t\t\t\t\tmarkdownBody,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tpages: countPageMarkers(markdownBody),\n\t\t\t\t\toutputDir,\n\t\t\t\t\tfilename,\n\t\t\t\t\turl,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (shouldRethrowExtractionError(err, signal)) throw err;\n\t\t}\n\t}\n\n\tconst { getDocumentProxy, VerbosityLevel } = await getUnpdf();\n\tconst pdf = await getDocumentProxy(new Uint8Array(buffer), {\n\t\tverbosity: VerbosityLevel.ERRORS,\n\t});\n\tconst metadata = await pdf.getMetadata();\n\tconst metadataInfo =\n\t\tmetadata.info && typeof metadata.info === \"object\"\n\t\t\t? (metadata.info as Record<string, unknown>)\n\t\t\t: null;\n\n\tconst metaTitle =\n\t\ttypeof metadataInfo?.Title === \"string\" ? metadataInfo.Title : undefined;\n\tconst metaAuthor =\n\t\ttypeof metadataInfo?.Author === \"string\" ? metadataInfo.Author : undefined;\n\tconst title = metaTitle?.trim() || urlTitle;\n\tconst pagesToExtract = Math.min(pdf.numPages, safeMaxPages);\n\tconst truncated = pdf.numPages > safeMaxPages;\n\tconst pages: { pageNum: number; text: string }[] = [];\n\n\tfor (let i = 1; i <= pagesToExtract; i++) {\n\t\tconst page = await pdf.getPage(i);\n\t\tconst textContent = await page.getTextContent();\n\t\tconst pageText = textContent.items\n\t\t\t.map((item: unknown) => {\n\t\t\t\tconst textItem = item as { str?: string };\n\t\t\t\treturn textItem.str || \"\";\n\t\t\t})\n\t\t\t.join(\" \")\n\t\t\t.replace(/\\s+/g, \" \")\n\t\t\t.trim();\n\n\t\tif (pageText) {\n\t\t\tpages.push({ pageNum: i, text: pageText });\n\t\t}\n\t}\n\n\tconst bodyLines: string[] = [];\n\tfor (let i = 0; i < pages.length; i++) {\n\t\tif (i > 0) {\n\t\t\tbodyLines.push(\"\");\n\t\t\tbodyLines.push(`<!-- Page ${pages[i].pageNum} -->`);\n\t\t\tbodyLines.push(\"\");\n\t\t}\n\t\tbodyLines.push(pages[i].text);\n\t}\n\n\treturn writeMarkdownResult({\n\t\tmarkdownBody: bodyLines.join(\"\\n\"),\n\t\ttitle,\n\t\tpages: pdf.numPages,\n\t\toutputDir,\n\t\tfilename,\n\t\turl,\n\t\tmetaAuthor,\n\t\ttruncated,\n\t\tpagesToExtract,\n\t});\n}\n\nasync function writeMarkdownResult(options: {\n\tmarkdownBody: string;\n\ttitle: string;\n\tpages: number;\n\toutputDir: string;\n\tfilename?: string;\n\turl: string;\n\tmetaAuthor?: string;\n\ttruncated?: boolean;\n\tpagesToExtract?: number;\n}): Promise<PDFExtractResult> {\n\tconst lines: string[] = [];\n\tlines.push(`# ${options.title}`);\n\tlines.push(\"\");\n\tlines.push(`> Source: ${options.url}`);\n\tlines.push(\n\t\t`> Pages: ${options.pages}${options.truncated ? ` (extracted first ${options.pagesToExtract})` : \"\"}`,\n\t);\n\tif (options.metaAuthor) lines.push(`> Author: ${options.metaAuthor}`);\n\tlines.push(\"\");\n\tlines.push(\"---\");\n\tlines.push(\"\");\n\tif (options.markdownBody) lines.push(options.markdownBody);\n\n\tif (options.truncated) {\n\t\tlines.push(\"\");\n\t\tlines.push(\"---\");\n\t\tlines.push(\"\");\n\t\tlines.push(\n\t\t\t`*[Truncated: Only first ${options.pagesToExtract} of ${options.pages} pages extracted]*`,\n\t\t);\n\t}\n\n\tconst content = lines.join(\"\\n\");\n\tconst outputFilename =\n\t\toptions.filename || sanitizeFilename(options.title) + \".md\";\n\tconst outputPath = join(options.outputDir, outputFilename);\n\n\tawait mkdir(options.outputDir, { recursive: true });\n\tawait writeFile(outputPath, content, \"utf-8\");\n\n\treturn {\n\t\ttitle: options.title,\n\t\tpages: options.pages,\n\t\tchars: content.length,\n\t\toutputPath,\n\t};\n}\n\nfunction countPageMarkers(markdown: string): number {\n\treturn [...markdown.matchAll(PAGE_MARKER_PATTERN)].length;\n}\n\nfunction shouldRethrowExtractionError(\n\terr: unknown,\n\tsignal?: AbortSignal,\n): boolean {\n\tif (signal?.aborted) return true;\n\tif (err instanceof CredentialResolutionError) return true;\n\tconst message = err instanceof Error ? err.message : String(err);\n\treturn message.startsWith(\"Failed to parse \");\n}\n\n/**\n * Extract a reasonable title from URL\n */\nfunction extractTitleFromURL(url: string): string {\n\ttry {\n\t\tconst urlObj = new URL(url);\n\t\tconst pathname = urlObj.pathname;\n\n\t\tlet filename = basename(pathname, \".pdf\");\n\n\t\tif (urlObj.hostname.includes(\"arxiv.org\")) {\n\t\t\tconst match = pathname.match(/\\/(?:pdf|abs)\\/(\\d+\\.\\d+)/);\n\t\t\tif (match) {\n\t\t\t\tfilename = `arxiv-${match[1]}`;\n\t\t\t}\n\t\t}\n\n\t\tfilename = filename.replace(/[_-]+/g, \" \").replace(/\\s+/g, \" \").trim();\n\n\t\treturn filename || \"document\";\n\t} catch {\n\t\treturn \"document\";\n\t}\n}\n\n/**\n * Sanitize string for use as filename\n */\nfunction sanitizeFilename(name: string): string {\n\treturn (\n\t\tname\n\t\t\t.toLowerCase()\n\t\t\t.replace(/[^a-z0-9\\s-]/g, \"\")\n\t\t\t.replace(/\\s+/g, \"-\")\n\t\t\t.replace(/-+/g, \"-\")\n\t\t\t.slice(0, 100)\n\t\t\t.replace(/^-|-$/g, \"\") || \"document\"\n\t);\n}\n\n/**\n * Check if URL or content-type indicates a PDF\n */\nexport function isPDF(url: string, contentType?: string): boolean {\n\tif (contentType?.includes(\"application/pdf\")) {\n\t\treturn true;\n\t}\n\ttry {\n\t\tconst urlObj = new URL(url);\n\t\treturn urlObj.pathname.toLowerCase().endsWith(\".pdf\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n"]}
1
+ {"version":3,"file":"pdf-extract.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/pdf-extract.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PDF Content Extractor\n *\n * Converts PDFs to Markdown. The `auto` provider chain runs Datalab\n * (deterministic, layout-aware) first, then Gemini API, with unpdf as the\n * deterministic local fallback; the chain can also be pinned with\n * `pdf.provider`.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join, basename } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { CredentialResolutionError } from \"./credential-source.ts\";\nimport {\n\tDATALAB_MODE_VALUES,\n\tDEFAULT_DATALAB_TIMEOUT_MS,\n\tisDatalabApiAvailable,\n\tnormalizeDatalabMode,\n\textractPDFViaDatalab,\n\ttype DatalabMode,\n} from \"./datalab-pdf-extract.ts\";\nimport { isGeminiApiAvailable } from \"./gemini-api.ts\";\nimport { extractPDFViaGemini } from \"./gemini-pdf-extract.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nexport interface PDFExtractResult {\n\ttitle: string;\n\t/** The same Markdown written to outputPath, retained for page answering. */\n\tcontent: string;\n\tpages: number;\n\tchars: number;\n\toutputPath: string;\n}\n\nexport interface PDFExtractOptions {\n\tmaxPages?: number;\n\toutputDir?: string;\n\tfilename?: string;\n\tsignal?: AbortSignal;\n\tgeminiTimeoutMs?: number;\n}\n\nexport type PDFProvider = \"auto\" | \"gemini\" | \"datalab\" | \"unpdf\";\n\nexport const PDF_PROVIDER_VALUES = new Set<PDFProvider>([\n\t\"auto\",\n\t\"gemini\",\n\t\"datalab\",\n\t\"unpdf\",\n]);\n\nexport interface PDFConfig {\n\tenabled: boolean;\n\tmaxSizeMB: number;\n\tmaxPages: number;\n\tprovider: PDFProvider;\n\tdatalabMode: DatalabMode;\n\tdatalabTimeoutMs: number;\n}\n\nexport const DEFAULT_PDF_MAX_SIZE_MB = 20;\nexport const MAX_PDF_MAX_SIZE_MB = 50;\nexport const MAX_DATALAB_TIMEOUT_MS = 300_000;\nconst DEFAULT_MAX_PAGES = 100;\nconst DEFAULT_OUTPUT_DIR = join(tmpdir(), \"pi-web-pdf\");\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst PAGE_MARKER_PATTERN = /^<!-- Page (\\d+) -->$/gm;\n\nexport function loadPDFConfig(): PDFConfig {\n\tif (!existsSync(CONFIG_PATH)) {\n\t\treturn {\n\t\t\tenabled: true,\n\t\t\tmaxSizeMB: DEFAULT_PDF_MAX_SIZE_MB,\n\t\t\tmaxPages: DEFAULT_MAX_PAGES,\n\t\t\tprovider: \"auto\",\n\t\t\tdatalabMode: normalizeDatalabMode(process.env.DATALAB_MODE),\n\t\t\tdatalabTimeoutMs: DEFAULT_DATALAB_TIMEOUT_MS,\n\t\t};\n\t}\n\n\tconst rawText = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(rawText) as unknown;\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\n\tconst root =\n\t\traw && typeof raw === \"object\" ? (raw as Record<string, unknown>) : {};\n\tconst pdf =\n\t\troot.pdf && typeof root.pdf === \"object\"\n\t\t\t? (root.pdf as Record<string, unknown>)\n\t\t\t: {};\n\tconst enabled = pdf.enabled !== false;\n\tconst configured = pdf.maxSizeMB;\n\tconst normalized =\n\t\ttypeof configured === \"number\" &&\n\t\tNumber.isFinite(configured) &&\n\t\tconfigured > 0\n\t\t\t? Math.min(configured, MAX_PDF_MAX_SIZE_MB)\n\t\t\t: DEFAULT_PDF_MAX_SIZE_MB;\n\tconst configuredMaxPages = pdf.maxPages;\n\tconst maxPages =\n\t\ttypeof configuredMaxPages === \"number\" &&\n\t\tNumber.isFinite(configuredMaxPages) &&\n\t\tconfiguredMaxPages > 0\n\t\t\t? Math.max(1, Math.floor(configuredMaxPages))\n\t\t\t: DEFAULT_MAX_PAGES;\n\n\tconst provider =\n\t\ttypeof pdf.provider === \"string\" &&\n\t\tPDF_PROVIDER_VALUES.has(pdf.provider as PDFProvider)\n\t\t\t? (pdf.provider as PDFProvider)\n\t\t\t: \"auto\";\n\tconst datalabMode =\n\t\ttypeof pdf.datalabMode === \"string\" &&\n\t\tDATALAB_MODE_VALUES.has(pdf.datalabMode as DatalabMode)\n\t\t\t? (pdf.datalabMode as DatalabMode)\n\t\t\t: normalizeDatalabMode(process.env.DATALAB_MODE);\n\tconst configuredTimeout = pdf.datalabTimeoutMs;\n\tconst datalabTimeoutMs =\n\t\ttypeof configuredTimeout === \"number\" &&\n\t\tNumber.isFinite(configuredTimeout) &&\n\t\tconfiguredTimeout > 0\n\t\t\t? Math.min(configuredTimeout, MAX_DATALAB_TIMEOUT_MS)\n\t\t\t: DEFAULT_DATALAB_TIMEOUT_MS;\n\n\treturn {\n\t\tenabled,\n\t\tmaxSizeMB: normalized,\n\t\tmaxPages,\n\t\tprovider,\n\t\tdatalabMode,\n\t\tdatalabTimeoutMs,\n\t};\n}\n\nasync function getUnpdf() {\n\tif (\n\t\ttypeof (Promise as PromiseConstructor & { try?: unknown }).try !==\n\t\t\"function\"\n\t) {\n\t\tconst { default: promiseTry } = await import(\"promise.try\");\n\t\tpromiseTry.shim();\n\t}\n\n\tconst [unpdf, pdfjs] = await Promise.all([\n\t\timport(\"unpdf\"),\n\t\timport(\"unpdf/pdfjs\"),\n\t]);\n\tconst { VerbosityLevel } = pdfjs as typeof pdfjs & {\n\t\tVerbosityLevel: { ERRORS: number };\n\t};\n\n\treturn { getDocumentProxy: unpdf.getDocumentProxy, VerbosityLevel };\n}\n\n/**\n * Extract text from a PDF buffer and save it to a Markdown file.\n */\nexport async function extractPDFToMarkdown(\n\tbuffer: ArrayBuffer,\n\turl: string,\n\toptions: PDFExtractOptions = {},\n): Promise<PDFExtractResult> {\n\tconst {\n\t\tmaxPages,\n\t\toutputDir = DEFAULT_OUTPUT_DIR,\n\t\tfilename,\n\t\tsignal,\n\t\tgeminiTimeoutMs,\n\t} = options;\n\n\tconst pdfConfig = loadPDFConfig();\n\tconst safeMaxPages =\n\t\tmaxPages === undefined\n\t\t\t? pdfConfig.maxPages\n\t\t\t: Number.isFinite(maxPages)\n\t\t\t\t? Math.max(1, Math.floor(maxPages))\n\t\t\t\t: DEFAULT_MAX_PAGES;\n\tconst urlTitle = extractTitleFromURL(url);\n\tconst provider = pdfConfig.provider;\n\n\tif (provider === \"auto\" || provider === \"datalab\") {\n\t\ttry {\n\t\t\tif (isDatalabApiAvailable()) {\n\t\t\t\tconst result = await extractPDFViaDatalab(buffer, {\n\t\t\t\t\tmaxPages: safeMaxPages,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tmode: pdfConfig.datalabMode,\n\t\t\t\t\ttimeoutMs: pdfConfig.datalabTimeoutMs,\n\t\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\t});\n\t\t\t\treturn writeMarkdownResult({\n\t\t\t\t\tmarkdownBody: result.markdown,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tpages: result.pages,\n\t\t\t\t\toutputDir,\n\t\t\t\t\tfilename,\n\t\t\t\t\turl,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (shouldRethrowExtractionError(err, signal)) throw err;\n\t\t}\n\t}\n\n\tif (provider === \"auto\" || provider === \"gemini\") {\n\t\ttry {\n\t\t\tif (isGeminiApiAvailable()) {\n\t\t\t\tconst markdownBody = await extractPDFViaGemini(buffer, {\n\t\t\t\t\tmaxPages: safeMaxPages,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\t\t...(geminiTimeoutMs !== undefined\n\t\t\t\t\t\t? { timeoutMs: geminiTimeoutMs }\n\t\t\t\t\t\t: {}),\n\t\t\t\t});\n\t\t\t\treturn writeMarkdownResult({\n\t\t\t\t\tmarkdownBody,\n\t\t\t\t\ttitle: urlTitle,\n\t\t\t\t\tpages: countPageMarkers(markdownBody),\n\t\t\t\t\toutputDir,\n\t\t\t\t\tfilename,\n\t\t\t\t\turl,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (shouldRethrowExtractionError(err, signal)) throw err;\n\t\t}\n\t}\n\n\tconst { getDocumentProxy, VerbosityLevel } = await getUnpdf();\n\tconst pdf = await getDocumentProxy(new Uint8Array(buffer), {\n\t\tverbosity: VerbosityLevel.ERRORS,\n\t});\n\tconst metadata = await pdf.getMetadata();\n\tconst metadataInfo =\n\t\tmetadata.info && typeof metadata.info === \"object\"\n\t\t\t? (metadata.info as Record<string, unknown>)\n\t\t\t: null;\n\n\tconst metaTitle =\n\t\ttypeof metadataInfo?.Title === \"string\" ? metadataInfo.Title : undefined;\n\tconst metaAuthor =\n\t\ttypeof metadataInfo?.Author === \"string\" ? metadataInfo.Author : undefined;\n\tconst title = metaTitle?.trim() || urlTitle;\n\tconst pagesToExtract = Math.min(pdf.numPages, safeMaxPages);\n\tconst truncated = pdf.numPages > safeMaxPages;\n\tconst pages: { pageNum: number; text: string }[] = [];\n\n\tfor (let i = 1; i <= pagesToExtract; i++) {\n\t\tconst page = await pdf.getPage(i);\n\t\tconst textContent = await page.getTextContent();\n\t\tconst pageText = textContent.items\n\t\t\t.map((item: unknown) => {\n\t\t\t\tconst textItem = item as { str?: string };\n\t\t\t\treturn textItem.str || \"\";\n\t\t\t})\n\t\t\t.join(\" \")\n\t\t\t.replace(/\\s+/g, \" \")\n\t\t\t.trim();\n\n\t\tif (pageText) {\n\t\t\tpages.push({ pageNum: i, text: pageText });\n\t\t}\n\t}\n\n\tconst bodyLines: string[] = [];\n\tfor (let i = 0; i < pages.length; i++) {\n\t\tif (i > 0) {\n\t\t\tbodyLines.push(\"\");\n\t\t\tbodyLines.push(`<!-- Page ${pages[i].pageNum} -->`);\n\t\t\tbodyLines.push(\"\");\n\t\t}\n\t\tbodyLines.push(pages[i].text);\n\t}\n\n\treturn writeMarkdownResult({\n\t\tmarkdownBody: bodyLines.join(\"\\n\"),\n\t\ttitle,\n\t\tpages: pdf.numPages,\n\t\toutputDir,\n\t\tfilename,\n\t\turl,\n\t\tmetaAuthor,\n\t\ttruncated,\n\t\tpagesToExtract,\n\t});\n}\n\nasync function writeMarkdownResult(options: {\n\tmarkdownBody: string;\n\ttitle: string;\n\tpages: number;\n\toutputDir: string;\n\tfilename?: string;\n\turl: string;\n\tmetaAuthor?: string;\n\ttruncated?: boolean;\n\tpagesToExtract?: number;\n}): Promise<PDFExtractResult> {\n\tconst lines: string[] = [];\n\tlines.push(`# ${options.title}`);\n\tlines.push(\"\");\n\tlines.push(`> Source: ${options.url}`);\n\tlines.push(\n\t\t`> Pages: ${options.pages}${options.truncated ? ` (extracted first ${options.pagesToExtract})` : \"\"}`,\n\t);\n\tif (options.metaAuthor) lines.push(`> Author: ${options.metaAuthor}`);\n\tlines.push(\"\");\n\tlines.push(\"---\");\n\tlines.push(\"\");\n\tif (options.markdownBody) lines.push(options.markdownBody);\n\n\tif (options.truncated) {\n\t\tlines.push(\"\");\n\t\tlines.push(\"---\");\n\t\tlines.push(\"\");\n\t\tlines.push(\n\t\t\t`*[Truncated: Only first ${options.pagesToExtract} of ${options.pages} pages extracted]*`,\n\t\t);\n\t}\n\n\tconst content = lines.join(\"\\n\");\n\tconst outputFilename =\n\t\toptions.filename || sanitizeFilename(options.title) + \".md\";\n\tconst outputPath = join(options.outputDir, outputFilename);\n\n\tawait mkdir(options.outputDir, { recursive: true });\n\tawait writeFile(outputPath, content, \"utf-8\");\n\n\treturn {\n\t\ttitle: options.title,\n\t\tcontent,\n\t\tpages: options.pages,\n\t\tchars: content.length,\n\t\toutputPath,\n\t};\n}\n\nfunction countPageMarkers(markdown: string): number {\n\treturn [...markdown.matchAll(PAGE_MARKER_PATTERN)].length;\n}\n\nfunction shouldRethrowExtractionError(\n\terr: unknown,\n\tsignal?: AbortSignal,\n): boolean {\n\tif (signal?.aborted) return true;\n\tif (err instanceof CredentialResolutionError) return true;\n\tconst message = err instanceof Error ? err.message : String(err);\n\treturn message.startsWith(\"Failed to parse \");\n}\n\n/**\n * Extract a reasonable title from URL\n */\nfunction extractTitleFromURL(url: string): string {\n\ttry {\n\t\tconst urlObj = new URL(url);\n\t\tconst pathname = urlObj.pathname;\n\n\t\tlet filename = basename(pathname, \".pdf\");\n\n\t\tif (urlObj.hostname.includes(\"arxiv.org\")) {\n\t\t\tconst match = pathname.match(/\\/(?:pdf|abs)\\/(\\d+\\.\\d+)/);\n\t\t\tif (match) {\n\t\t\t\tfilename = `arxiv-${match[1]}`;\n\t\t\t}\n\t\t}\n\n\t\tfilename = filename.replace(/[_-]+/g, \" \").replace(/\\s+/g, \" \").trim();\n\n\t\treturn filename || \"document\";\n\t} catch {\n\t\treturn \"document\";\n\t}\n}\n\n/**\n * Sanitize string for use as filename\n */\nfunction sanitizeFilename(name: string): string {\n\treturn (\n\t\tname\n\t\t\t.toLowerCase()\n\t\t\t.replace(/[^a-z0-9\\s-]/g, \"\")\n\t\t\t.replace(/\\s+/g, \"-\")\n\t\t\t.replace(/-+/g, \"-\")\n\t\t\t.slice(0, 100)\n\t\t\t.replace(/^-|-$/g, \"\") || \"document\"\n\t);\n}\n\n/**\n * Check if URL or content-type indicates a PDF\n */\nexport function isPDF(url: string, contentType?: string): boolean {\n\tif (contentType?.includes(\"application/pdf\")) {\n\t\treturn true;\n\t}\n\ttry {\n\t\tconst urlObj = new URL(url);\n\t\treturn urlObj.pathname.toLowerCase().endsWith(\".pdf\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"querit.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/querit.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA0DrE,UAAU,mBAAoB,SAAQ,aAAa;IAClD,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AA4CD,wBAAgB,iBAAiB,IAAI,OAAO,CAM3C;AA4OD,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAAC,cAAc,CAAC,CA+BzB;AAED,wBAAsB,iBAAiB,CACtC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA0BlC"}
1
+ {"version":3,"file":"querit.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/querit.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA4DrE,UAAU,mBAAoB,SAAQ,aAAa;IAClD,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AA4CD,wBAAgB,iBAAiB,IAAI,OAAO,CAM3C;AAiND,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAAC,cAAc,CAAC,CA+BzB;AAED,wBAAsB,iBAAiB,CACtC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA0BlC"}
@@ -1,6 +1,9 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { activityMonitor } from "./activity.js";
3
+ import { normalizeDomain } from "./domain-filter-normalization.js";
3
4
  import { hasCredentialSource, redactCredential, resolveCredential } from "./credential-source.js";
5
+ import { formatSearchResultsAsAnswer } from "./search-answer-formatting.js";
6
+ import { normalizeSearchResultCount } from "./search-result-count-normalization.js";
4
7
  import { getWebSearchConfigPath } from "./utils.js";
5
8
  const QUERIT_SEARCH_URL = "https://api.querit.ai/v1/search";
6
9
  const QUERIT_CONTENTS_URL = "https://api.querit.ai/v1/contents";
@@ -60,29 +63,6 @@ function requestSignal(signal, timeoutMs) {
60
63
  const timeout = AbortSignal.timeout(timeoutMs);
61
64
  return signal ? AbortSignal.any([signal, timeout]) : timeout;
62
65
  }
63
- function normalizeNumResults(value) {
64
- if (typeof value !== "number" || !Number.isFinite(value))
65
- return 5;
66
- return Math.max(1, Math.min(Math.floor(value), 20));
67
- }
68
- function normalizeDomain(value) {
69
- let input = value.trim().toLowerCase();
70
- if (!input)
71
- return null;
72
- if (input.startsWith("-"))
73
- input = input.slice(1).trim();
74
- if (!input)
75
- return null;
76
- try {
77
- const parsed = input.includes("://") ? new URL(input) : new URL(`https://${input}`);
78
- input = parsed.hostname;
79
- }
80
- catch {
81
- input = input.split("/")[0]?.split(":")[0] ?? "";
82
- }
83
- input = input.replace(/^\.+|\.+$/g, "");
84
- return /^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/i.test(input) ? input : null;
85
- }
86
66
  function mapDomainFilter(domainFilter) {
87
67
  const include = [];
88
68
  const exclude = [];
@@ -121,7 +101,7 @@ function buildSearchBody(query, options) {
121
101
  filters.timeRange = { date };
122
102
  return {
123
103
  query,
124
- count: normalizeNumResults(options.numResults),
104
+ count: normalizeSearchResultCount(options.numResults),
125
105
  ...(Object.keys(filters).length > 0 ? { filters } : {}),
126
106
  };
127
107
  }
@@ -210,13 +190,6 @@ function mapSearchResults(data) {
210
190
  }];
211
191
  });
212
192
  }
213
- function buildAnswer(results) {
214
- return results.map((result) => {
215
- if (result.snippet)
216
- return `${result.snippet}\nSource: ${result.title} (${result.url})`;
217
- return `Source: ${result.title} (${result.url})`;
218
- }).join("\n\n");
219
- }
220
193
  function mapContentResult(result, requestedUrl) {
221
194
  if (!result || typeof result.content !== "string" || result.content.trim().length === 0)
222
195
  return null;
@@ -276,7 +249,7 @@ export async function searchWithQuerit(query, options = {}) {
276
249
  const data = await queritJsonRequest("Search", QUERIT_SEARCH_URL, apiKey, buildSearchBody(query, options), SEARCH_TIMEOUT_MS, options.signal);
277
250
  assertApiSuccess("Search", data);
278
251
  const results = mapSearchResults(data);
279
- const response = { answer: buildAnswer(results), results };
252
+ const response = { answer: formatSearchResultsAsAnswer(results), results };
280
253
  if (options.includeContent && results.length > 0) {
281
254
  const inlineContent = await fetchInlineContent(results.map((result) => result.url), apiKey, options.signal);
282
255
  if (inlineContent.length > 0)
@@ -1 +1 @@
1
- {"version":3,"file":"querit.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/querit.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport type { ExtractedContent, ExtractOptions } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst QUERIT_SEARCH_URL = \"https://api.querit.ai/v1/search\";\nconst QUERIT_CONTENTS_URL = \"https://api.querit.ai/v1/contents\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\nconst CONTENTS_TIMEOUT_MS = 60_000;\nconst MAX_CONTENT_URLS = 10;\n\ninterface WebSearchConfig {\n\tqueritApiKey?: unknown;\n}\n\ninterface QueritSearchResult {\n\turl?: string | null;\n\ttitle?: string | null;\n\tsnippet?: string | null;\n\tpage_age?: string | null;\n\tsite_name?: string | null;\n}\n\ninterface QueritSearchResponse {\n\terror_code?: number | string;\n\terror_msg?: string;\n\tsearch_id?: number | string;\n\tresults?: { result?: QueritSearchResult[] };\n}\n\ninterface QueritContentMetadata {\n\ttitle?: string | null;\n\turl?: string | null;\n\tpublishTime?: string | null;\n\tsiteName?: string | null;\n\tsiteIcon?: string | null;\n}\n\ninterface QueritContentResult {\n\tid?: string | null;\n\turl?: string | null;\n\tcontent?: string | null;\n\textrasMeta?: QueritContentMetadata | null;\n}\n\ninterface QueritContentStatus {\n\tid?: string | null;\n\tstatus?: string | null;\n}\n\ninterface QueritContentsResponse {\n\terror_code?: number | string;\n\terror_msg?: string;\n\tsearch_id?: number | string;\n\tresults?: QueritContentResult[];\n\tstatuses?: QueritContentStatus[];\n\tsearchTime?: number;\n}\n\ninterface QueritSearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveCredential({\n\t\tprovider: \"Querit\",\n\t\tconfiguredValue: loadConfig().queritApiKey,\n\t\tenvironmentValue: process.env.QUERIT_API_KEY,\n\t\tsignal,\n\t});\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Querit API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"queritApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set QUERIT_API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://www.querit.ai/en/dashboard/api-keys\",\n\t\t);\n\t}\n\treturn key;\n}\n\nexport function isQueritAvailable(): boolean {\n\treturn hasCredentialSource({\n\t\tprovider: \"Querit\",\n\t\tconfiguredValue: loadConfig().queritApiKey,\n\t\tenvironmentValue: process.env.QUERIT_API_KEY,\n\t});\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction requestSignal(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {\n\tconst timeout = AbortSignal.timeout(timeoutMs);\n\treturn signal ? AbortSignal.any([signal, timeout]) : timeout;\n}\n\nfunction normalizeNumResults(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 20));\n}\n\nfunction normalizeDomain(value: string): string | null {\n\tlet input = value.trim().toLowerCase();\n\tif (!input) return null;\n\tif (input.startsWith(\"-\")) input = input.slice(1).trim();\n\tif (!input) return null;\n\ttry {\n\t\tconst parsed = input.includes(\"://\") ? new URL(input) : new URL(`https://${input}`);\n\t\tinput = parsed.hostname;\n\t} catch {\n\t\tinput = input.split(\"/\")[0]?.split(\":\")[0] ?? \"\";\n\t}\n\tinput = input.replace(/^\\.+|\\.+$/g, \"\");\n\treturn /^[a-z0-9][a-z0-9.-]*\\.[a-z]{2,}$/i.test(input) ? input : null;\n}\n\nfunction mapDomainFilter(domainFilter: string[] | undefined): { include: string[]; exclude: string[] } {\n\tconst include: string[] = [];\n\tconst exclude: string[] = [];\n\tfor (const raw of domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? exclude : include;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn { include, exclude };\n}\n\nfunction mapRecencyFilter(value: SearchOptions[\"recencyFilter\"]): string | undefined {\n\tif (value === \"day\") return \"d1\";\n\tif (value === \"week\") return \"w1\";\n\tif (value === \"month\") return \"m1\";\n\tif (value === \"year\") return \"y1\";\n\treturn undefined;\n}\n\nfunction buildSearchBody(query: string, options: QueritSearchOptions): Record<string, unknown> {\n\tconst { include, exclude } = mapDomainFilter(options.domainFilter);\n\tconst date = mapRecencyFilter(options.recencyFilter);\n\tconst filters: Record<string, unknown> = {};\n\tif (include.length > 0 || exclude.length > 0) {\n\t\tfilters.sites = {\n\t\t\t...(include.length > 0 ? { include } : {}),\n\t\t\t...(exclude.length > 0 ? { exclude } : {}),\n\t\t};\n\t}\n\tif (date) filters.timeRange = { date };\n\treturn {\n\t\tquery,\n\t\tcount: normalizeNumResults(options.numResults),\n\t\t...(Object.keys(filters).length > 0 ? { filters } : {}),\n\t};\n}\n\nfunction normalizeTimeoutMs(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return CONTENTS_TIMEOUT_MS;\n\treturn Math.max(1, Math.floor(value));\n}\n\nfunction crawlTimeoutSeconds(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 10;\n\treturn Math.max(1, Math.min(Math.ceil(value / 1_000), 60));\n}\n\nfunction buildContentsBody(urls: string[], options: ExtractOptions = {}): Record<string, unknown> {\n\treturn {\n\t\turls,\n\t\tformat: \"markdown\",\n\t\tcrawlTimeout: crawlTimeoutSeconds(options.timeoutMs),\n\t\textrasMeta: true,\n\t};\n}\n\nasync function queritJsonRequest<T>(\n\tlabel: \"Search\" | \"Contents\",\n\turl: string,\n\tapiKey: string,\n\tbody: Record<string, unknown>,\n\ttimeoutMs: number,\n\tsignal?: AbortSignal,\n): Promise<T> {\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: requestSignal(signal, timeoutMs),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst isRequestAbort = err instanceof Error\n\t\t\t? err.name === \"AbortError\" || err.name === \"TimeoutError\" || /abort|timeout/i.test(message)\n\t\t\t: /abort|timeout/i.test(message);\n\t\tif (!signal?.aborted && isRequestAbort) {\n\t\t\tconst timeoutError = new Error(`Querit ${label} API request timed out after ${Math.ceil(timeoutMs / 1_000)} seconds`);\n\t\t\ttimeoutError.name = \"TimeoutError\";\n\t\t\tthrow timeoutError;\n\t\t}\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tconst raw = await response.text();\n\tif (!response.ok) {\n\t\tthrow new Error(`Querit ${label} API error ${response.status}: ${redactCredential(raw, apiKey).slice(0, 300)}`);\n\t}\n\ttry {\n\t\treturn JSON.parse(raw) as T;\n\t} catch (err) {\n\t\tthrow new Error(`Querit ${label} API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n}\n\nfunction assertApiSuccess(label: \"Search\" | \"Contents\", data: QueritSearchResponse | QueritContentsResponse): void {\n\tconst code = Number(data.error_code);\n\tif (!Number.isFinite(code) || code !== 200) {\n\t\tconst renderedCode = data.error_code === undefined ? \"unknown\" : String(data.error_code);\n\t\tconst message = typeof data.error_msg === \"string\" && data.error_msg.trim() ? `: ${data.error_msg.trim()}` : \"\";\n\t\tthrow new Error(`Querit ${label} API returned error ${renderedCode}${message}`);\n\t}\n}\n\nfunction mapSearchResults(data: QueritSearchResponse): SearchResponse[\"results\"] {\n\tconst items = data.results?.result;\n\tif (!Array.isArray(items)) {\n\t\tthrow new Error(\"Querit Search API returned an unexpected response shape\");\n\t}\n\treturn items.flatMap((item) => {\n\t\tif (!item || typeof item.url !== \"string\" || item.url.trim().length === 0) return [];\n\t\tconst url = item.url.trim();\n\t\treturn [{\n\t\t\ttitle: typeof item.title === \"string\" && item.title.trim() ? item.title.trim() : url,\n\t\t\turl,\n\t\t\tsnippet: typeof item.snippet === \"string\" ? item.snippet.replace(/\\s+/g, \" \").trim() : \"\",\n\t\t}];\n\t});\n}\n\nfunction buildAnswer(results: SearchResponse[\"results\"]): string {\n\treturn results.map((result) => {\n\t\tif (result.snippet) return `${result.snippet}\\nSource: ${result.title} (${result.url})`;\n\t\treturn `Source: ${result.title} (${result.url})`;\n\t}).join(\"\\n\\n\");\n}\n\nfunction mapContentResult(result: QueritContentResult | undefined, requestedUrl: string): ExtractedContent | null {\n\tif (!result || typeof result.content !== \"string\" || result.content.trim().length === 0) return null;\n\tconst metadata = result.extrasMeta;\n\treturn {\n\t\turl: requestedUrl,\n\t\ttitle: metadata && typeof metadata.title === \"string\" ? metadata.title.trim() : \"\",\n\t\tcontent: result.content.trim(),\n\t\terror: null,\n\t};\n}\n\nfunction findContentResult(\n\tdata: QueritContentsResponse,\n\trequestedUrl: string,\n\tindex: number,\n\trequestedCount: number,\n): QueritContentResult | undefined {\n\tif (!Array.isArray(data.results)) return undefined;\n\tconst exact = data.results.find((item) => item?.url === requestedUrl || item?.extrasMeta?.url === requestedUrl);\n\tif (exact) return exact;\n\tif (requestedCount === 1) return data.results[0];\n\treturn data.results.length === requestedCount ? data.results[index] : undefined;\n}\n\nfunction failedContentStatus(data: QueritContentsResponse, result: QueritContentResult | undefined, index: number): boolean {\n\tif (!Array.isArray(data.statuses)) return false;\n\tconst status = result?.id\n\t\t? data.statuses.find((item) => item?.id === result.id)\n\t\t: data.statuses[index];\n\treturn status?.status === \"failed\";\n}\n\nasync function fetchContentsBatch(\n\turls: string[],\n\tapiKey: string,\n\tsignal?: AbortSignal,\n\toptions: ExtractOptions = {},\n): Promise<QueritContentsResponse> {\n\tconst data = await queritJsonRequest<QueritContentsResponse>(\n\t\t\"Contents\",\n\t\tQUERIT_CONTENTS_URL,\n\t\tapiKey,\n\t\tbuildContentsBody(urls, options),\n\t\tnormalizeTimeoutMs(options.timeoutMs),\n\t\tsignal,\n\t);\n\tassertApiSuccess(\"Contents\", data);\n\tif (!Array.isArray(data.results) || !Array.isArray(data.statuses)) {\n\t\tthrow new Error(\"Querit Contents API returned an unexpected response shape\");\n\t}\n\treturn data;\n}\n\nasync function fetchInlineContent(urls: string[], apiKey: string, signal?: AbortSignal): Promise<ExtractedContent[]> {\n\tconst content: ExtractedContent[] = [];\n\tfor (let offset = 0; offset < urls.length; offset += MAX_CONTENT_URLS) {\n\t\tconst batch = urls.slice(offset, offset + MAX_CONTENT_URLS);\n\t\tconst data = await fetchContentsBatch(batch, apiKey, signal);\n\t\tfor (let index = 0; index < batch.length; index++) {\n\t\t\tconst requestedUrl = batch[index];\n\t\t\tconst result = findContentResult(data, requestedUrl, index, batch.length);\n\t\t\tconst mapped = mapContentResult(result, requestedUrl);\n\t\t\tif (mapped) content.push(mapped);\n\t\t}\n\t}\n\treturn content;\n}\n\nexport async function searchWithQuerit(\n\tquery: string,\n\toptions: QueritSearchOptions = {},\n): Promise<SearchResponse> {\n\tconst apiKey = await getApiKey(options.signal);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\ttry {\n\t\tconst data = await queritJsonRequest<QueritSearchResponse>(\n\t\t\t\"Search\",\n\t\t\tQUERIT_SEARCH_URL,\n\t\t\tapiKey,\n\t\t\tbuildSearchBody(query, options),\n\t\t\tSEARCH_TIMEOUT_MS,\n\t\t\toptions.signal,\n\t\t);\n\t\tassertApiSuccess(\"Search\", data);\n\t\tconst results = mapSearchResults(data);\n\t\tconst response: SearchResponse = { answer: buildAnswer(results), results };\n\t\tif (options.includeContent && results.length > 0) {\n\t\t\tconst inlineContent = await fetchInlineContent(results.map((result) => result.url), apiKey, options.signal);\n\t\t\tif (inlineContent.length > 0) response.inlineContent = inlineContent;\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn response;\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (options.signal?.aborted) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n\nexport async function extractWithQuerit(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions: ExtractOptions = {},\n): Promise<ExtractedContent | null> {\n\tconst apiKey = await getApiKey(signal);\n\tconst activityId = activityMonitor.logStart({ type: \"fetch\", url });\n\ttry {\n\t\tconst data = await fetchContentsBatch([url], apiKey, signal, options);\n\t\tconst result = findContentResult(data, url, 0, 1);\n\t\tconst mapped = mapContentResult(result, url);\n\t\tif (mapped) {\n\t\t\tactivityMonitor.logComplete(activityId, 200);\n\t\t\treturn mapped;\n\t\t}\n\t\tif (failedContentStatus(data, result, 0)) {\n\t\t\tthrow new Error(`Querit Contents API failed to crawl ${url}`);\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn null;\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (signal?.aborted) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n"]}
1
+ {"version":3,"file":"querit.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/querit.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 { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport type { ExtractedContent, ExtractOptions } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { formatSearchResultsAsAnswer } from \"./search-answer-formatting.ts\";\nimport { normalizeSearchResultCount } from \"./search-result-count-normalization.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst QUERIT_SEARCH_URL = \"https://api.querit.ai/v1/search\";\nconst QUERIT_CONTENTS_URL = \"https://api.querit.ai/v1/contents\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\nconst CONTENTS_TIMEOUT_MS = 60_000;\nconst MAX_CONTENT_URLS = 10;\n\ninterface WebSearchConfig {\n\tqueritApiKey?: unknown;\n}\n\ninterface QueritSearchResult {\n\turl?: string | null;\n\ttitle?: string | null;\n\tsnippet?: string | null;\n\tpage_age?: string | null;\n\tsite_name?: string | null;\n}\n\ninterface QueritSearchResponse {\n\terror_code?: number | string;\n\terror_msg?: string;\n\tsearch_id?: number | string;\n\tresults?: { result?: QueritSearchResult[] };\n}\n\ninterface QueritContentMetadata {\n\ttitle?: string | null;\n\turl?: string | null;\n\tpublishTime?: string | null;\n\tsiteName?: string | null;\n\tsiteIcon?: string | null;\n}\n\ninterface QueritContentResult {\n\tid?: string | null;\n\turl?: string | null;\n\tcontent?: string | null;\n\textrasMeta?: QueritContentMetadata | null;\n}\n\ninterface QueritContentStatus {\n\tid?: string | null;\n\tstatus?: string | null;\n}\n\ninterface QueritContentsResponse {\n\terror_code?: number | string;\n\terror_msg?: string;\n\tsearch_id?: number | string;\n\tresults?: QueritContentResult[];\n\tstatuses?: QueritContentStatus[];\n\tsearchTime?: number;\n}\n\ninterface QueritSearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveCredential({\n\t\tprovider: \"Querit\",\n\t\tconfiguredValue: loadConfig().queritApiKey,\n\t\tenvironmentValue: process.env.QUERIT_API_KEY,\n\t\tsignal,\n\t});\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Querit API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"queritApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set QUERIT_API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://www.querit.ai/en/dashboard/api-keys\",\n\t\t);\n\t}\n\treturn key;\n}\n\nexport function isQueritAvailable(): boolean {\n\treturn hasCredentialSource({\n\t\tprovider: \"Querit\",\n\t\tconfiguredValue: loadConfig().queritApiKey,\n\t\tenvironmentValue: process.env.QUERIT_API_KEY,\n\t});\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction requestSignal(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {\n\tconst timeout = AbortSignal.timeout(timeoutMs);\n\treturn signal ? AbortSignal.any([signal, timeout]) : timeout;\n}\n\nfunction mapDomainFilter(domainFilter: string[] | undefined): { include: string[]; exclude: string[] } {\n\tconst include: string[] = [];\n\tconst exclude: string[] = [];\n\tfor (const raw of domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? exclude : include;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn { include, exclude };\n}\n\nfunction mapRecencyFilter(value: SearchOptions[\"recencyFilter\"]): string | undefined {\n\tif (value === \"day\") return \"d1\";\n\tif (value === \"week\") return \"w1\";\n\tif (value === \"month\") return \"m1\";\n\tif (value === \"year\") return \"y1\";\n\treturn undefined;\n}\n\nfunction buildSearchBody(query: string, options: QueritSearchOptions): Record<string, unknown> {\n\tconst { include, exclude } = mapDomainFilter(options.domainFilter);\n\tconst date = mapRecencyFilter(options.recencyFilter);\n\tconst filters: Record<string, unknown> = {};\n\tif (include.length > 0 || exclude.length > 0) {\n\t\tfilters.sites = {\n\t\t\t...(include.length > 0 ? { include } : {}),\n\t\t\t...(exclude.length > 0 ? { exclude } : {}),\n\t\t};\n\t}\n\tif (date) filters.timeRange = { date };\n\treturn {\n\t\tquery,\n\t\tcount: normalizeSearchResultCount(options.numResults),\n\t\t...(Object.keys(filters).length > 0 ? { filters } : {}),\n\t};\n}\n\nfunction normalizeTimeoutMs(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return CONTENTS_TIMEOUT_MS;\n\treturn Math.max(1, Math.floor(value));\n}\n\nfunction crawlTimeoutSeconds(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 10;\n\treturn Math.max(1, Math.min(Math.ceil(value / 1_000), 60));\n}\n\nfunction buildContentsBody(urls: string[], options: ExtractOptions = {}): Record<string, unknown> {\n\treturn {\n\t\turls,\n\t\tformat: \"markdown\",\n\t\tcrawlTimeout: crawlTimeoutSeconds(options.timeoutMs),\n\t\textrasMeta: true,\n\t};\n}\n\nasync function queritJsonRequest<T>(\n\tlabel: \"Search\" | \"Contents\",\n\turl: string,\n\tapiKey: string,\n\tbody: Record<string, unknown>,\n\ttimeoutMs: number,\n\tsignal?: AbortSignal,\n): Promise<T> {\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: requestSignal(signal, timeoutMs),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst isRequestAbort = err instanceof Error\n\t\t\t? err.name === \"AbortError\" || err.name === \"TimeoutError\" || /abort|timeout/i.test(message)\n\t\t\t: /abort|timeout/i.test(message);\n\t\tif (!signal?.aborted && isRequestAbort) {\n\t\t\tconst timeoutError = new Error(`Querit ${label} API request timed out after ${Math.ceil(timeoutMs / 1_000)} seconds`);\n\t\t\ttimeoutError.name = \"TimeoutError\";\n\t\t\tthrow timeoutError;\n\t\t}\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tconst raw = await response.text();\n\tif (!response.ok) {\n\t\tthrow new Error(`Querit ${label} API error ${response.status}: ${redactCredential(raw, apiKey).slice(0, 300)}`);\n\t}\n\ttry {\n\t\treturn JSON.parse(raw) as T;\n\t} catch (err) {\n\t\tthrow new Error(`Querit ${label} API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n}\n\nfunction assertApiSuccess(label: \"Search\" | \"Contents\", data: QueritSearchResponse | QueritContentsResponse): void {\n\tconst code = Number(data.error_code);\n\tif (!Number.isFinite(code) || code !== 200) {\n\t\tconst renderedCode = data.error_code === undefined ? \"unknown\" : String(data.error_code);\n\t\tconst message = typeof data.error_msg === \"string\" && data.error_msg.trim() ? `: ${data.error_msg.trim()}` : \"\";\n\t\tthrow new Error(`Querit ${label} API returned error ${renderedCode}${message}`);\n\t}\n}\n\nfunction mapSearchResults(data: QueritSearchResponse): SearchResponse[\"results\"] {\n\tconst items = data.results?.result;\n\tif (!Array.isArray(items)) {\n\t\tthrow new Error(\"Querit Search API returned an unexpected response shape\");\n\t}\n\treturn items.flatMap((item) => {\n\t\tif (!item || typeof item.url !== \"string\" || item.url.trim().length === 0) return [];\n\t\tconst url = item.url.trim();\n\t\treturn [{\n\t\t\ttitle: typeof item.title === \"string\" && item.title.trim() ? item.title.trim() : url,\n\t\t\turl,\n\t\t\tsnippet: typeof item.snippet === \"string\" ? item.snippet.replace(/\\s+/g, \" \").trim() : \"\",\n\t\t}];\n\t});\n}\n\nfunction mapContentResult(result: QueritContentResult | undefined, requestedUrl: string): ExtractedContent | null {\n\tif (!result || typeof result.content !== \"string\" || result.content.trim().length === 0) return null;\n\tconst metadata = result.extrasMeta;\n\treturn {\n\t\turl: requestedUrl,\n\t\ttitle: metadata && typeof metadata.title === \"string\" ? metadata.title.trim() : \"\",\n\t\tcontent: result.content.trim(),\n\t\terror: null,\n\t};\n}\n\nfunction findContentResult(\n\tdata: QueritContentsResponse,\n\trequestedUrl: string,\n\tindex: number,\n\trequestedCount: number,\n): QueritContentResult | undefined {\n\tif (!Array.isArray(data.results)) return undefined;\n\tconst exact = data.results.find((item) => item?.url === requestedUrl || item?.extrasMeta?.url === requestedUrl);\n\tif (exact) return exact;\n\tif (requestedCount === 1) return data.results[0];\n\treturn data.results.length === requestedCount ? data.results[index] : undefined;\n}\n\nfunction failedContentStatus(data: QueritContentsResponse, result: QueritContentResult | undefined, index: number): boolean {\n\tif (!Array.isArray(data.statuses)) return false;\n\tconst status = result?.id\n\t\t? data.statuses.find((item) => item?.id === result.id)\n\t\t: data.statuses[index];\n\treturn status?.status === \"failed\";\n}\n\nasync function fetchContentsBatch(\n\turls: string[],\n\tapiKey: string,\n\tsignal?: AbortSignal,\n\toptions: ExtractOptions = {},\n): Promise<QueritContentsResponse> {\n\tconst data = await queritJsonRequest<QueritContentsResponse>(\n\t\t\"Contents\",\n\t\tQUERIT_CONTENTS_URL,\n\t\tapiKey,\n\t\tbuildContentsBody(urls, options),\n\t\tnormalizeTimeoutMs(options.timeoutMs),\n\t\tsignal,\n\t);\n\tassertApiSuccess(\"Contents\", data);\n\tif (!Array.isArray(data.results) || !Array.isArray(data.statuses)) {\n\t\tthrow new Error(\"Querit Contents API returned an unexpected response shape\");\n\t}\n\treturn data;\n}\n\nasync function fetchInlineContent(urls: string[], apiKey: string, signal?: AbortSignal): Promise<ExtractedContent[]> {\n\tconst content: ExtractedContent[] = [];\n\tfor (let offset = 0; offset < urls.length; offset += MAX_CONTENT_URLS) {\n\t\tconst batch = urls.slice(offset, offset + MAX_CONTENT_URLS);\n\t\tconst data = await fetchContentsBatch(batch, apiKey, signal);\n\t\tfor (let index = 0; index < batch.length; index++) {\n\t\t\tconst requestedUrl = batch[index];\n\t\t\tconst result = findContentResult(data, requestedUrl, index, batch.length);\n\t\t\tconst mapped = mapContentResult(result, requestedUrl);\n\t\t\tif (mapped) content.push(mapped);\n\t\t}\n\t}\n\treturn content;\n}\n\nexport async function searchWithQuerit(\n\tquery: string,\n\toptions: QueritSearchOptions = {},\n): Promise<SearchResponse> {\n\tconst apiKey = await getApiKey(options.signal);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\ttry {\n\t\tconst data = await queritJsonRequest<QueritSearchResponse>(\n\t\t\t\"Search\",\n\t\t\tQUERIT_SEARCH_URL,\n\t\t\tapiKey,\n\t\t\tbuildSearchBody(query, options),\n\t\t\tSEARCH_TIMEOUT_MS,\n\t\t\toptions.signal,\n\t\t);\n\t\tassertApiSuccess(\"Search\", data);\n\t\tconst results = mapSearchResults(data);\n\t\tconst response: SearchResponse = { answer: formatSearchResultsAsAnswer(results), results };\n\t\tif (options.includeContent && results.length > 0) {\n\t\t\tconst inlineContent = await fetchInlineContent(results.map((result) => result.url), apiKey, options.signal);\n\t\t\tif (inlineContent.length > 0) response.inlineContent = inlineContent;\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn response;\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (options.signal?.aborted) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n\nexport async function extractWithQuerit(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions: ExtractOptions = {},\n): Promise<ExtractedContent | null> {\n\tconst apiKey = await getApiKey(signal);\n\tconst activityId = activityMonitor.logStart({ type: \"fetch\", url });\n\ttry {\n\t\tconst data = await fetchContentsBatch([url], apiKey, signal, options);\n\t\tconst result = findContentResult(data, url, 0, 1);\n\t\tconst mapped = mapContentResult(result, url);\n\t\tif (mapped) {\n\t\t\tactivityMonitor.logComplete(activityId, 200);\n\t\t\treturn mapped;\n\t\t}\n\t\tif (failedContentStatus(data, result, 0)) {\n\t\t\tthrow new Error(`Querit Contents API failed to crawl ${url}`);\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn null;\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (signal?.aborted) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n"]}
@@ -0,0 +1,8 @@
1
+ interface AnswerResult {
2
+ title: string;
3
+ url: string;
4
+ snippet: string;
5
+ }
6
+ export declare function formatSearchResultsAsAnswer(results: readonly AnswerResult[]): string;
7
+ export {};
8
+ //# sourceMappingURL=search-answer-formatting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-answer-formatting.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/search-answer-formatting.ts"],"names":[],"mappings":"AAAA,UAAU,YAAY;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAIpF"}
@@ -0,0 +1,6 @@
1
+ export function formatSearchResultsAsAnswer(results) {
2
+ return results.map((result) => result.snippet
3
+ ? `${result.snippet}\nSource: ${result.title} (${result.url})`
4
+ : `Source: ${result.title} (${result.url})`).join("\n\n");
5
+ }
6
+ //# sourceMappingURL=search-answer-formatting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-answer-formatting.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/search-answer-formatting.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,2BAA2B,CAAC,OAAgC;IAC3E,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO;QAC5C,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,aAAa,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,GAAG,GAAG;QAC9D,CAAC,CAAC,WAAW,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5D,CAAC","sourcesContent":["interface AnswerResult {\n\ttitle: string;\n\turl: string;\n\tsnippet: string;\n}\n\nexport function formatSearchResultsAsAnswer(results: readonly AnswerResult[]): 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"]}
@@ -0,0 +1,2 @@
1
+ export declare function normalizeSearchResultCount(value: number | undefined): number;
2
+ //# sourceMappingURL=search-result-count-normalization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-result-count-normalization.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/search-result-count-normalization.ts"],"names":[],"mappings":"AAAA,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG5E"}
@@ -0,0 +1,6 @@
1
+ export function normalizeSearchResultCount(value) {
2
+ if (typeof value !== "number" || !Number.isFinite(value))
3
+ return 5;
4
+ return Math.max(1, Math.min(Math.floor(value), 20));
5
+ }
6
+ //# sourceMappingURL=search-result-count-normalization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-result-count-normalization.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/search-result-count-normalization.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,0BAA0B,CAAC,KAAyB;IACnE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACnE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AACrD,CAAC","sourcesContent":["export function normalizeSearchResultCount(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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"search1api.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/search1api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAqCrE,UAAU,uBAAwB,SAAQ,aAAa;IACtD,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AA4CD,wBAAgB,qBAAqB,IAAI,OAAO,CAM/C;AAmID,wBAAsB,oBAAoB,CACzC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,uBAA4B,GACnC,OAAO,CAAC,cAAc,CAAC,CA8BzB;AAED,wBAAsB,qBAAqB,CAC1C,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAwClC"}
1
+ {"version":3,"file":"search1api.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/search1api.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAuCrE,UAAU,uBAAwB,SAAQ,aAAa;IACtD,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AA4CD,wBAAgB,qBAAqB,IAAI,OAAO,CAM/C;AAwGD,wBAAsB,oBAAoB,CACzC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,uBAA4B,GACnC,OAAO,CAAC,cAAc,CAAC,CA8BzB;AAED,wBAAsB,qBAAqB,CAC1C,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,GAAE,cAAmB,GAC1B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAwClC"}
@@ -1,6 +1,9 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { activityMonitor } from "./activity.js";
3
+ import { normalizeDomain } from "./domain-filter-normalization.js";
3
4
  import { hasCredentialSource, redactCredential, resolveCredential } from "./credential-source.js";
5
+ import { formatSearchResultsAsAnswer } from "./search-answer-formatting.js";
6
+ import { normalizeSearchResultCount } from "./search-result-count-normalization.js";
4
7
  import { getWebSearchConfigPath } from "./utils.js";
5
8
  const SEARCH1API_SEARCH_URL = "https://api.search1api.com/search";
6
9
  const SEARCH1API_CRAWL_URL = "https://api.search1api.com/crawl";
@@ -59,29 +62,6 @@ function requestSignal(signal, timeoutMs) {
59
62
  const timeout = AbortSignal.timeout(timeoutMs);
60
63
  return signal ? AbortSignal.any([signal, timeout]) : timeout;
61
64
  }
62
- function normalizeNumResults(value) {
63
- if (typeof value !== "number" || !Number.isFinite(value))
64
- return 5;
65
- return Math.max(1, Math.min(Math.floor(value), 20));
66
- }
67
- function normalizeDomain(value) {
68
- let input = value.trim().toLowerCase();
69
- if (!input)
70
- return null;
71
- if (input.startsWith("-"))
72
- input = input.slice(1).trim();
73
- if (!input)
74
- return null;
75
- try {
76
- const parsed = input.includes("://") ? new URL(input) : new URL(`https://${input}`);
77
- input = parsed.hostname;
78
- }
79
- catch {
80
- input = input.split("/")[0]?.split(":")[0] ?? "";
81
- }
82
- input = input.replace(/^\.+|\.+$/g, "");
83
- return /^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/i.test(input) ? input : null;
84
- }
85
65
  function mapDomainFilter(domainFilter) {
86
66
  const includeSites = [];
87
67
  const excludeSites = [];
@@ -96,7 +76,7 @@ function mapDomainFilter(domainFilter) {
96
76
  return { includeSites, excludeSites };
97
77
  }
98
78
  function buildSearchBody(query, options) {
99
- const numResults = normalizeNumResults(options.numResults);
79
+ const numResults = normalizeSearchResultCount(options.numResults);
100
80
  const { includeSites, excludeSites } = mapDomainFilter(options.domainFilter);
101
81
  return {
102
82
  query,
@@ -172,20 +152,13 @@ function mapInlineContent(results) {
172
152
  }];
173
153
  });
174
154
  }
175
- function buildAnswer(results) {
176
- return results.map((result) => {
177
- if (result.snippet)
178
- return `${result.snippet}\nSource: ${result.title} (${result.url})`;
179
- return `Source: ${result.title} (${result.url})`;
180
- }).join("\n\n");
181
- }
182
155
  export async function searchWithSearch1API(query, options = {}) {
183
156
  const apiKey = await getApiKey(options.signal);
184
157
  const activityId = activityMonitor.logStart({ type: "api", query });
185
158
  try {
186
159
  const data = await search1APIJsonRequest("Search", SEARCH1API_SEARCH_URL, apiKey, buildSearchBody(query, options), SEARCH_TIMEOUT_MS, options.signal);
187
160
  const results = mapSearchResults(data.results);
188
- const response = { answer: buildAnswer(results), results };
161
+ const response = { answer: formatSearchResultsAsAnswer(results), results };
189
162
  if (options.includeContent) {
190
163
  const inlineContent = mapInlineContent(data.results);
191
164
  if (inlineContent.length > 0)
@@ -1 +1 @@
1
- {"version":3,"file":"search1api.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/search1api.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport type { ExtractedContent, ExtractOptions } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst SEARCH1API_SEARCH_URL = \"https://api.search1api.com/search\";\nconst SEARCH1API_CRAWL_URL = \"https://api.search1api.com/crawl\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\nconst CRAWL_TIMEOUT_MS = 60_000;\n\ninterface WebSearchConfig {\n\tsearch1apiApiKey?: unknown;\n}\n\ninterface Search1APISearchResult {\n\ttitle?: string | null;\n\tlink?: string | null;\n\tsnippet?: string | null;\n\tcontent?: string | null;\n}\n\ninterface Search1APISearchResponse {\n\tsearchParameters?: Record<string, unknown>;\n\tresults?: Search1APISearchResult[];\n}\n\ninterface Search1APICrawlResult {\n\ttitle?: string | null;\n\tlink?: string | null;\n\tcontent?: string | null;\n\tmetadata?: Record<string, unknown>;\n}\n\ninterface Search1APICrawlResponse {\n\tcrawlParameters?: { url?: string };\n\tresults?: Search1APICrawlResult;\n}\n\ninterface Search1APISearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveCredential({\n\t\tprovider: \"Search1API\",\n\t\tconfiguredValue: loadConfig().search1apiApiKey,\n\t\tenvironmentValue: process.env.SEARCH1API_KEY,\n\t\tsignal,\n\t});\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Search1API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"search1apiApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set SEARCH1API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://dashboard.search1api.com\",\n\t\t);\n\t}\n\treturn key;\n}\n\nexport function isSearch1APIAvailable(): boolean {\n\treturn hasCredentialSource({\n\t\tprovider: \"Search1API\",\n\t\tconfiguredValue: loadConfig().search1apiApiKey,\n\t\tenvironmentValue: process.env.SEARCH1API_KEY,\n\t});\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction requestSignal(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {\n\tconst timeout = AbortSignal.timeout(timeoutMs);\n\treturn signal ? AbortSignal.any([signal, timeout]) : timeout;\n}\n\nfunction normalizeNumResults(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 20));\n}\n\nfunction normalizeDomain(value: string): string | null {\n\tlet input = value.trim().toLowerCase();\n\tif (!input) return null;\n\tif (input.startsWith(\"-\")) input = input.slice(1).trim();\n\tif (!input) return null;\n\ttry {\n\t\tconst parsed = input.includes(\"://\") ? new URL(input) : new URL(`https://${input}`);\n\t\tinput = parsed.hostname;\n\t} catch {\n\t\tinput = input.split(\"/\")[0]?.split(\":\")[0] ?? \"\";\n\t}\n\tinput = input.replace(/^\\.+|\\.+$/g, \"\");\n\treturn /^[a-z0-9][a-z0-9.-]*\\.[a-z]{2,}$/i.test(input) ? input : null;\n}\n\nfunction mapDomainFilter(domainFilter: string[] | undefined): { includeSites: string[]; excludeSites: string[] } {\n\tconst includeSites: string[] = [];\n\tconst excludeSites: string[] = [];\n\tfor (const raw of domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? excludeSites : includeSites;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn { includeSites, excludeSites };\n}\n\nfunction buildSearchBody(query: string, options: Search1APISearchOptions): Record<string, unknown> {\n\tconst numResults = normalizeNumResults(options.numResults);\n\tconst { includeSites, excludeSites } = mapDomainFilter(options.domainFilter);\n\treturn {\n\t\tquery,\n\t\tmax_results: numResults,\n\t\tcrawl_results: options.includeContent ? numResults : 0,\n\t\t...(includeSites.length > 0 ? { include_sites: includeSites } : {}),\n\t\t...(excludeSites.length > 0 ? { exclude_sites: excludeSites } : {}),\n\t\t...(options.recencyFilter ? { time_range: options.recencyFilter } : {}),\n\t};\n}\n\nasync function search1APIJsonRequest<T>(\n\tlabel: \"Search\" | \"Crawl\",\n\turl: string,\n\tapiKey: string,\n\tbody: Record<string, unknown>,\n\ttimeoutMs: number,\n\tsignal?: AbortSignal,\n): Promise<T> {\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: requestSignal(signal, timeoutMs),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tconst raw = await response.text();\n\tif (!response.ok) {\n\t\tthrow new Error(`Search1API ${label} API error ${response.status}: ${redactCredential(raw, apiKey).slice(0, 300)}`);\n\t}\n\ttry {\n\t\treturn JSON.parse(raw) as T;\n\t} catch (err) {\n\t\tthrow new Error(`Search1API ${label} API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n}\n\nfunction mapSearchResults(results: Search1APISearchResult[] | undefined): SearchResponse[\"results\"] {\n\tif (!Array.isArray(results)) {\n\t\tthrow new Error(\"Search1API Search API returned an unexpected response shape\");\n\t}\n\treturn results.flatMap((item) => {\n\t\tif (!item || typeof item.link !== \"string\" || item.link.trim().length === 0) return [];\n\t\tconst url = item.link.trim();\n\t\treturn [{\n\t\t\ttitle: typeof item.title === \"string\" && item.title.trim() ? item.title.trim() : url,\n\t\t\turl,\n\t\t\tsnippet: typeof item.snippet === \"string\" ? item.snippet.replace(/\\s+/g, \" \").trim() : \"\",\n\t\t}];\n\t});\n}\n\nfunction mapInlineContent(results: Search1APISearchResult[] | undefined): ExtractedContent[] {\n\tif (!Array.isArray(results)) return [];\n\treturn results.flatMap((item) => {\n\t\tif (!item || typeof item.link !== \"string\" || item.link.trim().length === 0) return [];\n\t\tif (typeof item.content !== \"string\" || item.content.trim().length === 0) return [];\n\t\treturn [{\n\t\t\turl: item.link.trim(),\n\t\t\ttitle: typeof item.title === \"string\" ? item.title.trim() : \"\",\n\t\t\tcontent: item.content,\n\t\t\terror: null,\n\t\t}];\n\t});\n}\n\nfunction buildAnswer(results: SearchResponse[\"results\"]): string {\n\treturn results.map((result) => {\n\t\tif (result.snippet) return `${result.snippet}\\nSource: ${result.title} (${result.url})`;\n\t\treturn `Source: ${result.title} (${result.url})`;\n\t}).join(\"\\n\\n\");\n}\n\nexport async function searchWithSearch1API(\n\tquery: string,\n\toptions: Search1APISearchOptions = {},\n): Promise<SearchResponse> {\n\tconst apiKey = await getApiKey(options.signal);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\ttry {\n\t\tconst data = await search1APIJsonRequest<Search1APISearchResponse>(\n\t\t\t\"Search\",\n\t\t\tSEARCH1API_SEARCH_URL,\n\t\t\tapiKey,\n\t\t\tbuildSearchBody(query, options),\n\t\t\tSEARCH_TIMEOUT_MS,\n\t\t\toptions.signal,\n\t\t);\n\t\tconst results = mapSearchResults(data.results);\n\t\tconst response: SearchResponse = { answer: buildAnswer(results), results };\n\t\tif (options.includeContent) {\n\t\t\tconst inlineContent = mapInlineContent(data.results);\n\t\t\tif (inlineContent.length > 0) response.inlineContent = inlineContent;\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn response;\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n\nexport async function extractWithSearch1API(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions: ExtractOptions = {},\n): Promise<ExtractedContent | null> {\n\tconst apiKey = await getApiKey(signal);\n\tconst activityId = activityMonitor.logStart({ type: \"fetch\", url });\n\ttry {\n\t\tconst data = await search1APIJsonRequest<Search1APICrawlResponse>(\n\t\t\t\"Crawl\",\n\t\t\tSEARCH1API_CRAWL_URL,\n\t\t\tapiKey,\n\t\t\t{ url },\n\t\t\ttypeof options.timeoutMs === \"number\" && Number.isFinite(options.timeoutMs)\n\t\t\t\t? Math.max(1, Math.floor(options.timeoutMs))\n\t\t\t\t: CRAWL_TIMEOUT_MS,\n\t\t\tsignal,\n\t\t);\n\t\tconst result = data.results;\n\t\tif (!result || typeof result !== \"object\") {\n\t\t\tthrow new Error(\"Search1API Crawl API returned an unexpected response shape\");\n\t\t}\n\t\tconst content = typeof result.content === \"string\" ? result.content.trim() : \"\";\n\t\tif (!content) {\n\t\t\tactivityMonitor.logComplete(activityId, 200);\n\t\t\treturn null;\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn {\n\t\t\turl,\n\t\t\ttitle: typeof result.title === \"string\" ? result.title.trim() : \"\",\n\t\t\tcontent,\n\t\t\terror: null,\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"]}
1
+ {"version":3,"file":"search1api.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/search1api.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 { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport type { ExtractedContent, ExtractOptions } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { formatSearchResultsAsAnswer } from \"./search-answer-formatting.ts\";\nimport { normalizeSearchResultCount } from \"./search-result-count-normalization.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst SEARCH1API_SEARCH_URL = \"https://api.search1api.com/search\";\nconst SEARCH1API_CRAWL_URL = \"https://api.search1api.com/crawl\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\nconst CRAWL_TIMEOUT_MS = 60_000;\n\ninterface WebSearchConfig {\n\tsearch1apiApiKey?: unknown;\n}\n\ninterface Search1APISearchResult {\n\ttitle?: string | null;\n\tlink?: string | null;\n\tsnippet?: string | null;\n\tcontent?: string | null;\n}\n\ninterface Search1APISearchResponse {\n\tsearchParameters?: Record<string, unknown>;\n\tresults?: Search1APISearchResult[];\n}\n\ninterface Search1APICrawlResult {\n\ttitle?: string | null;\n\tlink?: string | null;\n\tcontent?: string | null;\n\tmetadata?: Record<string, unknown>;\n}\n\ninterface Search1APICrawlResponse {\n\tcrawlParameters?: { url?: string };\n\tresults?: Search1APICrawlResult;\n}\n\ninterface Search1APISearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string> {\n\tconst key = await resolveCredential({\n\t\tprovider: \"Search1API\",\n\t\tconfiguredValue: loadConfig().search1apiApiKey,\n\t\tenvironmentValue: process.env.SEARCH1API_KEY,\n\t\tsignal,\n\t});\n\tif (!key) {\n\t\tthrow new Error(\n\t\t\t\"Search1API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"search1apiApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set SEARCH1API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://dashboard.search1api.com\",\n\t\t);\n\t}\n\treturn key;\n}\n\nexport function isSearch1APIAvailable(): boolean {\n\treturn hasCredentialSource({\n\t\tprovider: \"Search1API\",\n\t\tconfiguredValue: loadConfig().search1apiApiKey,\n\t\tenvironmentValue: process.env.SEARCH1API_KEY,\n\t});\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction requestSignal(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {\n\tconst timeout = AbortSignal.timeout(timeoutMs);\n\treturn signal ? AbortSignal.any([signal, timeout]) : timeout;\n}\n\nfunction mapDomainFilter(domainFilter: string[] | undefined): { includeSites: string[]; excludeSites: string[] } {\n\tconst includeSites: string[] = [];\n\tconst excludeSites: string[] = [];\n\tfor (const raw of domainFilter ?? []) {\n\t\tconst domain = normalizeDomain(raw);\n\t\tif (!domain) continue;\n\t\tconst target = raw.trim().startsWith(\"-\") ? excludeSites : includeSites;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\treturn { includeSites, excludeSites };\n}\n\nfunction buildSearchBody(query: string, options: Search1APISearchOptions): Record<string, unknown> {\n\tconst numResults = normalizeSearchResultCount(options.numResults);\n\tconst { includeSites, excludeSites } = mapDomainFilter(options.domainFilter);\n\treturn {\n\t\tquery,\n\t\tmax_results: numResults,\n\t\tcrawl_results: options.includeContent ? numResults : 0,\n\t\t...(includeSites.length > 0 ? { include_sites: includeSites } : {}),\n\t\t...(excludeSites.length > 0 ? { exclude_sites: excludeSites } : {}),\n\t\t...(options.recencyFilter ? { time_range: options.recencyFilter } : {}),\n\t};\n}\n\nasync function search1APIJsonRequest<T>(\n\tlabel: \"Search\" | \"Crawl\",\n\turl: string,\n\tapiKey: string,\n\tbody: Record<string, unknown>,\n\ttimeoutMs: number,\n\tsignal?: AbortSignal,\n): Promise<T> {\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: requestSignal(signal, timeoutMs),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tconst raw = await response.text();\n\tif (!response.ok) {\n\t\tthrow new Error(`Search1API ${label} API error ${response.status}: ${redactCredential(raw, apiKey).slice(0, 300)}`);\n\t}\n\ttry {\n\t\treturn JSON.parse(raw) as T;\n\t} catch (err) {\n\t\tthrow new Error(`Search1API ${label} API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n}\n\nfunction mapSearchResults(results: Search1APISearchResult[] | undefined): SearchResponse[\"results\"] {\n\tif (!Array.isArray(results)) {\n\t\tthrow new Error(\"Search1API Search API returned an unexpected response shape\");\n\t}\n\treturn results.flatMap((item) => {\n\t\tif (!item || typeof item.link !== \"string\" || item.link.trim().length === 0) return [];\n\t\tconst url = item.link.trim();\n\t\treturn [{\n\t\t\ttitle: typeof item.title === \"string\" && item.title.trim() ? item.title.trim() : url,\n\t\t\turl,\n\t\t\tsnippet: typeof item.snippet === \"string\" ? item.snippet.replace(/\\s+/g, \" \").trim() : \"\",\n\t\t}];\n\t});\n}\n\nfunction mapInlineContent(results: Search1APISearchResult[] | undefined): ExtractedContent[] {\n\tif (!Array.isArray(results)) return [];\n\treturn results.flatMap((item) => {\n\t\tif (!item || typeof item.link !== \"string\" || item.link.trim().length === 0) return [];\n\t\tif (typeof item.content !== \"string\" || item.content.trim().length === 0) return [];\n\t\treturn [{\n\t\t\turl: item.link.trim(),\n\t\t\ttitle: typeof item.title === \"string\" ? item.title.trim() : \"\",\n\t\t\tcontent: item.content,\n\t\t\terror: null,\n\t\t}];\n\t});\n}\n\nexport async function searchWithSearch1API(\n\tquery: string,\n\toptions: Search1APISearchOptions = {},\n): Promise<SearchResponse> {\n\tconst apiKey = await getApiKey(options.signal);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\ttry {\n\t\tconst data = await search1APIJsonRequest<Search1APISearchResponse>(\n\t\t\t\"Search\",\n\t\t\tSEARCH1API_SEARCH_URL,\n\t\t\tapiKey,\n\t\t\tbuildSearchBody(query, options),\n\t\t\tSEARCH_TIMEOUT_MS,\n\t\t\toptions.signal,\n\t\t);\n\t\tconst results = mapSearchResults(data.results);\n\t\tconst response: SearchResponse = { answer: formatSearchResultsAsAnswer(results), results };\n\t\tif (options.includeContent) {\n\t\t\tconst inlineContent = mapInlineContent(data.results);\n\t\t\tif (inlineContent.length > 0) response.inlineContent = inlineContent;\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn response;\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n\nexport async function extractWithSearch1API(\n\turl: string,\n\tsignal?: AbortSignal,\n\toptions: ExtractOptions = {},\n): Promise<ExtractedContent | null> {\n\tconst apiKey = await getApiKey(signal);\n\tconst activityId = activityMonitor.logStart({ type: \"fetch\", url });\n\ttry {\n\t\tconst data = await search1APIJsonRequest<Search1APICrawlResponse>(\n\t\t\t\"Crawl\",\n\t\t\tSEARCH1API_CRAWL_URL,\n\t\t\tapiKey,\n\t\t\t{ url },\n\t\t\ttypeof options.timeoutMs === \"number\" && Number.isFinite(options.timeoutMs)\n\t\t\t\t? Math.max(1, Math.floor(options.timeoutMs))\n\t\t\t\t: CRAWL_TIMEOUT_MS,\n\t\t\tsignal,\n\t\t);\n\t\tconst result = data.results;\n\t\tif (!result || typeof result !== \"object\") {\n\t\t\tthrow new Error(\"Search1API Crawl API returned an unexpected response shape\");\n\t\t}\n\t\tconst content = typeof result.content === \"string\" ? result.content.trim() : \"\";\n\t\tif (!content) {\n\t\t\tactivityMonitor.logComplete(activityId, 200);\n\t\t\treturn null;\n\t\t}\n\t\tactivityMonitor.logComplete(activityId, 200);\n\t\treturn {\n\t\t\turl,\n\t\t\ttitle: typeof result.title === \"string\" ? result.title.trim() : \"\",\n\t\t\tcontent,\n\t\t\terror: null,\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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"searchinfinity.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/searchinfinity.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA6CrE,UAAU,2BAA4B,SAAQ,aAAa;IAC1D,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AA4CD,wBAAgB,yBAAyB,IAAI,OAAO,CAMnD;AAkJD,wBAAsB,wBAAwB,CAC7C,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,2BAAgC,GACvC,OAAO,CAAC,cAAc,CAAC,CAmBzB"}
1
+ {"version":3,"file":"searchinfinity.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/searchinfinity.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA+CrE,UAAU,2BAA4B,SAAQ,aAAa;IAC1D,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AA4CD,wBAAgB,yBAAyB,IAAI,OAAO,CAMnD;AAuHD,wBAAsB,wBAAwB,CAC7C,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,2BAAgC,GACvC,OAAO,CAAC,cAAc,CAAC,CAmBzB"}