@humain/terminal 0.0.2 → 0.0.3-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (680) hide show
  1. package/CHANGELOG.md +241 -24
  2. package/README.md +143 -119
  3. package/dist/cli/args.d.ts +4 -2
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +37 -39
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/auth-check.d.ts +19 -0
  8. package/dist/cli/auth-check.d.ts.map +1 -0
  9. package/dist/cli/auth-check.js +50 -0
  10. package/dist/cli/auth-check.js.map +1 -0
  11. package/dist/cli/auth-command.d.ts +24 -0
  12. package/dist/cli/auth-command.d.ts.map +1 -0
  13. package/dist/cli/auth-command.js +103 -0
  14. package/dist/cli/auth-command.js.map +1 -0
  15. package/dist/cli/config-selector.d.ts.map +1 -1
  16. package/dist/cli/config-selector.js +2 -2
  17. package/dist/cli/config-selector.js.map +1 -1
  18. package/dist/cli/credential-print.d.ts +5 -15
  19. package/dist/cli/credential-print.d.ts.map +1 -1
  20. package/dist/cli/credential-print.js +42 -83
  21. package/dist/cli/credential-print.js.map +1 -1
  22. package/dist/cli/experimental/auth.d.ts +16 -0
  23. package/dist/cli/experimental/auth.d.ts.map +1 -0
  24. package/dist/cli/experimental/auth.js +13 -0
  25. package/dist/cli/experimental/auth.js.map +1 -0
  26. package/dist/cli/experimental/cli.d.ts +6 -0
  27. package/dist/cli/experimental/cli.d.ts.map +1 -0
  28. package/dist/cli/experimental/cli.js +5 -0
  29. package/dist/cli/experimental/cli.js.map +1 -0
  30. package/dist/cli/experimental/command-options.d.ts +17 -0
  31. package/dist/cli/experimental/command-options.d.ts.map +1 -0
  32. package/dist/cli/experimental/command-options.js +35 -0
  33. package/dist/cli/experimental/command-options.js.map +1 -0
  34. package/dist/cli/experimental/command.d.ts +63 -0
  35. package/dist/cli/experimental/command.d.ts.map +1 -0
  36. package/dist/cli/experimental/command.js +130 -0
  37. package/dist/cli/experimental/command.js.map +1 -0
  38. package/dist/cli/experimental/commands/client.d.ts +13 -0
  39. package/dist/cli/experimental/commands/client.d.ts.map +1 -0
  40. package/dist/cli/experimental/commands/client.js +25 -0
  41. package/dist/cli/experimental/commands/client.js.map +1 -0
  42. package/dist/cli/experimental/commands/pi.d.ts +15 -0
  43. package/dist/cli/experimental/commands/pi.d.ts.map +1 -0
  44. package/dist/cli/experimental/commands/pi.js +28 -0
  45. package/dist/cli/experimental/commands/pi.js.map +1 -0
  46. package/dist/cli/experimental/commands/server.d.ts +13 -0
  47. package/dist/cli/experimental/commands/server.d.ts.map +1 -0
  48. package/dist/cli/experimental/commands/server.js +25 -0
  49. package/dist/cli/experimental/commands/server.js.map +1 -0
  50. package/dist/cli/experimental/transport-address.d.ts +10 -0
  51. package/dist/cli/experimental/transport-address.d.ts.map +1 -0
  52. package/dist/cli/experimental/transport-address.js +38 -0
  53. package/dist/cli/experimental/transport-address.js.map +1 -0
  54. package/dist/cli/list-models.d.ts +1 -1
  55. package/dist/cli/list-models.d.ts.map +1 -1
  56. package/dist/cli/list-models.js +2 -2
  57. package/dist/cli/list-models.js.map +1 -1
  58. package/dist/cli/startup-ui.d.ts +1 -1
  59. package/dist/cli/startup-ui.d.ts.map +1 -1
  60. package/dist/cli/startup-ui.js +2 -2
  61. package/dist/cli/startup-ui.js.map +1 -1
  62. package/dist/client/index.d.ts +3 -0
  63. package/dist/client/index.d.ts.map +1 -0
  64. package/dist/client/index.js +3 -0
  65. package/dist/client/index.js.map +1 -0
  66. package/dist/client/remote-session.d.ts +53 -0
  67. package/dist/client/remote-session.d.ts.map +1 -0
  68. package/dist/client/remote-session.js +340 -0
  69. package/dist/client/remote-session.js.map +1 -0
  70. package/dist/client/transcript.d.ts +12 -0
  71. package/dist/client/transcript.d.ts.map +1 -0
  72. package/dist/client/transcript.js +98 -0
  73. package/dist/client/transcript.js.map +1 -0
  74. package/dist/core/agent-session-services.d.ts +1 -0
  75. package/dist/core/agent-session-services.d.ts.map +1 -1
  76. package/dist/core/agent-session-services.js +1 -0
  77. package/dist/core/agent-session-services.js.map +1 -1
  78. package/dist/core/agent-session.d.ts +1 -10
  79. package/dist/core/agent-session.d.ts.map +1 -1
  80. package/dist/core/agent-session.js +72 -70
  81. package/dist/core/agent-session.js.map +1 -1
  82. package/dist/core/auth-storage.d.ts +25 -9
  83. package/dist/core/auth-storage.d.ts.map +1 -1
  84. package/dist/core/auth-storage.js +237 -39
  85. package/dist/core/auth-storage.js.map +1 -1
  86. package/dist/core/extensions/index.d.ts +1 -1
  87. package/dist/core/extensions/index.d.ts.map +1 -1
  88. package/dist/core/extensions/index.js.map +1 -1
  89. package/dist/core/extensions/loader.d.ts.map +1 -1
  90. package/dist/core/extensions/loader.js +60 -41
  91. package/dist/core/extensions/loader.js.map +1 -1
  92. package/dist/core/extensions/runner.d.ts +2 -1
  93. package/dist/core/extensions/runner.d.ts.map +1 -1
  94. package/dist/core/extensions/runner.js +3 -0
  95. package/dist/core/extensions/runner.js.map +1 -1
  96. package/dist/core/extensions/types.d.ts +27 -4
  97. package/dist/core/extensions/types.d.ts.map +1 -1
  98. package/dist/core/extensions/types.js.map +1 -1
  99. package/dist/core/http-dispatcher.d.ts.map +1 -1
  100. package/dist/core/http-dispatcher.js +5 -0
  101. package/dist/core/http-dispatcher.js.map +1 -1
  102. package/dist/core/keybindings.d.ts +45 -5
  103. package/dist/core/keybindings.d.ts.map +1 -1
  104. package/dist/core/keybindings.js.map +1 -1
  105. package/dist/core/model-config.d.ts +29 -5
  106. package/dist/core/model-config.d.ts.map +1 -1
  107. package/dist/core/model-config.js +4 -0
  108. package/dist/core/model-config.js.map +1 -1
  109. package/dist/core/model-registry.d.ts +5 -3
  110. package/dist/core/model-registry.d.ts.map +1 -1
  111. package/dist/core/model-registry.js +13 -10
  112. package/dist/core/model-registry.js.map +1 -1
  113. package/dist/core/model-resolver.d.ts +4 -3
  114. package/dist/core/model-resolver.d.ts.map +1 -1
  115. package/dist/core/model-resolver.js +42 -10
  116. package/dist/core/model-resolver.js.map +1 -1
  117. package/dist/core/model-runtime.d.ts +30 -13
  118. package/dist/core/model-runtime.d.ts.map +1 -1
  119. package/dist/core/model-runtime.js +233 -73
  120. package/dist/core/model-runtime.js.map +1 -1
  121. package/dist/core/models-store.d.ts +12 -7
  122. package/dist/core/models-store.d.ts.map +1 -1
  123. package/dist/core/models-store.js +83 -14
  124. package/dist/core/models-store.js.map +1 -1
  125. package/dist/core/package-manager.d.ts +6 -3
  126. package/dist/core/package-manager.d.ts.map +1 -1
  127. package/dist/core/package-manager.js +80 -61
  128. package/dist/core/package-manager.js.map +1 -1
  129. package/dist/core/pi-manifest.d.ts +8 -0
  130. package/dist/core/pi-manifest.d.ts.map +1 -0
  131. package/dist/core/pi-manifest.js +28 -0
  132. package/dist/core/pi-manifest.js.map +1 -0
  133. package/dist/core/provider-composer.d.ts +4 -1
  134. package/dist/core/provider-composer.d.ts.map +1 -1
  135. package/dist/core/provider-composer.js +36 -15
  136. package/dist/core/provider-composer.js.map +1 -1
  137. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  138. package/dist/core/remote-catalog-provider.js +73 -67
  139. package/dist/core/remote-catalog-provider.js.map +1 -1
  140. package/dist/core/resource-loader.d.ts.map +1 -1
  141. package/dist/core/resource-loader.js +2 -2
  142. package/dist/core/resource-loader.js.map +1 -1
  143. package/dist/core/runtime-credentials.d.ts +5 -5
  144. package/dist/core/runtime-credentials.d.ts.map +1 -1
  145. package/dist/core/runtime-credentials.js +11 -8
  146. package/dist/core/runtime-credentials.js.map +1 -1
  147. package/dist/core/sdk.d.ts +1 -1
  148. package/dist/core/sdk.d.ts.map +1 -1
  149. package/dist/core/sdk.js +2 -2
  150. package/dist/core/sdk.js.map +1 -1
  151. package/dist/core/session-manager.d.ts.map +1 -1
  152. package/dist/core/session-manager.js +3 -1
  153. package/dist/core/session-manager.js.map +1 -1
  154. package/dist/core/settings-manager.d.ts +12 -0
  155. package/dist/core/settings-manager.d.ts.map +1 -1
  156. package/dist/core/settings-manager.js +40 -16
  157. package/dist/core/settings-manager.js.map +1 -1
  158. package/dist/core/system-prompt.d.ts.map +1 -1
  159. package/dist/core/system-prompt.js +8 -0
  160. package/dist/core/system-prompt.js.map +1 -1
  161. package/dist/core/tools/bash.d.ts +5 -1
  162. package/dist/core/tools/bash.d.ts.map +1 -1
  163. package/dist/core/tools/bash.js +16 -15
  164. package/dist/core/tools/bash.js.map +1 -1
  165. package/dist/core/tools/edit.d.ts +4 -0
  166. package/dist/core/tools/edit.d.ts.map +1 -1
  167. package/dist/core/tools/edit.js +11 -7
  168. package/dist/core/tools/edit.js.map +1 -1
  169. package/dist/core/tools/find.d.ts +7 -0
  170. package/dist/core/tools/find.d.ts.map +1 -1
  171. package/dist/core/tools/find.js +16 -19
  172. package/dist/core/tools/find.js.map +1 -1
  173. package/dist/core/tools/grep.d.ts +4 -0
  174. package/dist/core/tools/grep.d.ts.map +1 -1
  175. package/dist/core/tools/grep.js +5 -1
  176. package/dist/core/tools/grep.js.map +1 -1
  177. package/dist/core/tools/ls.d.ts +4 -0
  178. package/dist/core/tools/ls.d.ts.map +1 -1
  179. package/dist/core/tools/ls.js +5 -1
  180. package/dist/core/tools/ls.js.map +1 -1
  181. package/dist/core/tools/read.d.ts +4 -0
  182. package/dist/core/tools/read.d.ts.map +1 -1
  183. package/dist/core/tools/read.js +7 -3
  184. package/dist/core/tools/read.js.map +1 -1
  185. package/dist/core/tools/write.d.ts +4 -0
  186. package/dist/core/tools/write.d.ts.map +1 -1
  187. package/dist/core/tools/write.js +6 -2
  188. package/dist/core/tools/write.js.map +1 -1
  189. package/dist/extensions/llama/index.d.ts.map +1 -1
  190. package/dist/extensions/llama/index.js +11 -2
  191. package/dist/extensions/llama/index.js.map +1 -1
  192. package/dist/extensions/llama/provider.d.ts.map +1 -1
  193. package/dist/extensions/llama/provider.js +21 -7
  194. package/dist/extensions/llama/provider.js.map +1 -1
  195. package/dist/humain/agent-execution-protocol.d.ts +218 -0
  196. package/dist/humain/agent-execution-protocol.d.ts.map +1 -0
  197. package/dist/humain/agent-execution-protocol.js +204 -0
  198. package/dist/humain/agent-execution-protocol.js.map +1 -0
  199. package/dist/humain/agent-execution-runtime.d.ts +35 -0
  200. package/dist/humain/agent-execution-runtime.d.ts.map +1 -0
  201. package/dist/humain/agent-execution-runtime.js +170 -0
  202. package/dist/humain/agent-execution-runtime.js.map +1 -0
  203. package/dist/humain/index.d.ts.map +1 -1
  204. package/dist/humain/index.js +8 -7
  205. package/dist/humain/index.js.map +1 -1
  206. package/dist/humain/mcp-adapter/vendor/CHANGELOG.md +660 -0
  207. package/dist/humain/mcp-adapter/vendor/LICENSE +21 -0
  208. package/dist/humain/mcp-adapter/vendor/README.md +733 -0
  209. package/dist/humain/mcp-adapter/vendor/abort.ts +34 -0
  210. package/dist/humain/mcp-adapter/vendor/agent-dir.ts +60 -0
  211. package/dist/humain/mcp-adapter/vendor/agent-plugin-loader.ts +377 -0
  212. package/dist/humain/mcp-adapter/vendor/app-bridge.bundle.js +67 -0
  213. package/dist/humain/mcp-adapter/vendor/banner.png +0 -0
  214. package/dist/humain/mcp-adapter/vendor/cli.js +209 -0
  215. package/dist/humain/mcp-adapter/vendor/commands.ts +627 -0
  216. package/dist/humain/mcp-adapter/vendor/config.ts +1226 -0
  217. package/dist/humain/mcp-adapter/vendor/consent-manager.ts +64 -0
  218. package/dist/humain/mcp-adapter/vendor/direct-tools.ts +604 -0
  219. package/dist/humain/mcp-adapter/vendor/elicitation-handler.ts +348 -0
  220. package/dist/humain/mcp-adapter/vendor/error-signal.ts +21 -0
  221. package/dist/humain/mcp-adapter/vendor/errors.ts +223 -0
  222. package/dist/humain/mcp-adapter/vendor/glimpse-ui.ts +80 -0
  223. package/dist/humain/mcp-adapter/vendor/host-html-template.ts +461 -0
  224. package/dist/humain/mcp-adapter/vendor/index.bundle.d.mts +4 -0
  225. package/dist/humain/mcp-adapter/vendor/index.bundle.mjs +15923 -0
  226. package/dist/humain/mcp-adapter/vendor/index.ts +898 -0
  227. package/dist/humain/mcp-adapter/vendor/init.ts +649 -0
  228. package/dist/humain/mcp-adapter/vendor/json-schema-validator.ts +69 -0
  229. package/dist/humain/mcp-adapter/vendor/lifecycle.ts +147 -0
  230. package/dist/humain/mcp-adapter/vendor/logger.ts +169 -0
  231. package/dist/humain/mcp-adapter/vendor/mcp-auth-flow.ts +993 -0
  232. package/dist/humain/mcp-adapter/vendor/mcp-auth.ts +1000 -0
  233. package/dist/humain/mcp-adapter/vendor/mcp-callback-server.ts +510 -0
  234. package/dist/humain/mcp-adapter/vendor/mcp-code.ts +354 -0
  235. package/dist/humain/mcp-adapter/vendor/mcp-keyring-helper.cjs +89 -0
  236. package/dist/humain/mcp-adapter/vendor/mcp-oauth-provider.ts +616 -0
  237. package/dist/humain/mcp-adapter/vendor/mcp-output-guard.ts +408 -0
  238. package/dist/humain/mcp-adapter/vendor/mcp-panel.ts +1015 -0
  239. package/dist/humain/mcp-adapter/vendor/mcp-probe.ts +187 -0
  240. package/dist/humain/mcp-adapter/vendor/mcp-script-worker.mjs +130 -0
  241. package/dist/humain/mcp-adapter/vendor/mcp-setup-panel.ts +666 -0
  242. package/dist/humain/mcp-adapter/vendor/mcp-status.ts +109 -0
  243. package/dist/humain/mcp-adapter/vendor/mcp-trace.ts +306 -0
  244. package/dist/humain/mcp-adapter/vendor/metadata-cache.ts +353 -0
  245. package/dist/humain/mcp-adapter/vendor/npx-resolver.ts +543 -0
  246. package/dist/humain/mcp-adapter/vendor/oauth-handler.ts +30 -0
  247. package/dist/humain/mcp-adapter/vendor/oauth.ts +48 -0
  248. package/dist/humain/mcp-adapter/vendor/onboarding-state.ts +76 -0
  249. package/dist/humain/mcp-adapter/vendor/package.json +178 -0
  250. package/dist/humain/mcp-adapter/vendor/panel-keys.ts +53 -0
  251. package/dist/humain/mcp-adapter/vendor/prompts.ts +353 -0
  252. package/dist/humain/mcp-adapter/vendor/proxy-modes.ts +1331 -0
  253. package/dist/humain/mcp-adapter/vendor/resource-tools.ts +17 -0
  254. package/dist/humain/mcp-adapter/vendor/runtime-owner.ts +91 -0
  255. package/dist/humain/mcp-adapter/vendor/sampling-handler.ts +284 -0
  256. package/dist/humain/mcp-adapter/vendor/search-ranking.ts +206 -0
  257. package/dist/humain/mcp-adapter/vendor/server-manager.ts +1124 -0
  258. package/dist/humain/mcp-adapter/vendor/session-recovery.ts +151 -0
  259. package/dist/humain/mcp-adapter/vendor/skills/mcp-scripting/SKILL.md +38 -0
  260. package/dist/humain/mcp-adapter/vendor/state.ts +62 -0
  261. package/dist/humain/mcp-adapter/vendor/tool-approval.ts +182 -0
  262. package/dist/humain/mcp-adapter/vendor/tool-metadata.ts +276 -0
  263. package/dist/humain/mcp-adapter/vendor/tool-registrar.ts +253 -0
  264. package/dist/humain/mcp-adapter/vendor/tool-result-renderer.ts +423 -0
  265. package/dist/humain/mcp-adapter/vendor/ts-shape.ts +149 -0
  266. package/dist/humain/mcp-adapter/vendor/types.ts +859 -0
  267. package/dist/humain/mcp-adapter/vendor/ui-app-bridge-helpers.ts +40 -0
  268. package/dist/humain/mcp-adapter/vendor/ui-resource-handler.ts +250 -0
  269. package/dist/humain/mcp-adapter/vendor/ui-server.ts +866 -0
  270. package/dist/humain/mcp-adapter/vendor/ui-session.ts +570 -0
  271. package/dist/humain/mcp-adapter/vendor/ui-stream-types.ts +89 -0
  272. package/dist/humain/mcp-adapter/vendor/ui-tool-visibility.ts +25 -0
  273. package/dist/humain/mcp-adapter/vendor/unix-socket-transport.ts +85 -0
  274. package/dist/humain/mcp-adapter/vendor/utils.ts +310 -0
  275. package/dist/humain/mcp-adapter.d.ts +3 -0
  276. package/dist/humain/mcp-adapter.d.ts.map +1 -0
  277. package/dist/humain/mcp-adapter.js +5 -0
  278. package/dist/humain/mcp-adapter.js.map +1 -0
  279. package/dist/humain/pi-agent-execution-host.d.ts +34 -0
  280. package/dist/humain/pi-agent-execution-host.d.ts.map +1 -0
  281. package/dist/humain/pi-agent-execution-host.js +77 -0
  282. package/dist/humain/pi-agent-execution-host.js.map +1 -0
  283. package/dist/humain/web-access/host.d.ts +4 -0
  284. package/dist/humain/web-access/host.d.ts.map +1 -0
  285. package/dist/humain/web-access/host.js +3 -0
  286. package/dist/humain/web-access/host.js.map +1 -0
  287. package/dist/humain/web-access/index.d.ts +3 -0
  288. package/dist/humain/web-access/index.d.ts.map +1 -0
  289. package/dist/humain/web-access/index.js +5 -0
  290. package/dist/humain/web-access/index.js.map +1 -0
  291. package/dist/humain/web-access/vendor/activity.d.ts +34 -0
  292. package/dist/humain/web-access/vendor/activity.d.ts.map +1 -0
  293. package/dist/humain/web-access/vendor/activity.js +68 -0
  294. package/dist/humain/web-access/vendor/activity.js.map +1 -0
  295. package/dist/humain/web-access/vendor/anysearch.d.ts +8 -0
  296. package/dist/humain/web-access/vendor/anysearch.d.ts.map +1 -0
  297. package/dist/humain/web-access/vendor/anysearch.js +167 -0
  298. package/dist/humain/web-access/vendor/anysearch.js.map +1 -0
  299. package/dist/humain/web-access/vendor/bocha.d.ts +4 -0
  300. package/dist/humain/web-access/vendor/bocha.d.ts.map +1 -0
  301. package/dist/humain/web-access/vendor/bocha.js +219 -0
  302. package/dist/humain/web-access/vendor/bocha.js.map +1 -0
  303. package/dist/humain/web-access/vendor/brave.d.ts +4 -0
  304. package/dist/humain/web-access/vendor/brave.d.ts.map +1 -0
  305. package/dist/humain/web-access/vendor/brave.js +194 -0
  306. package/dist/humain/web-access/vendor/brave.js.map +1 -0
  307. package/dist/humain/web-access/vendor/brightdata-unlocker.d.ts +12 -0
  308. package/dist/humain/web-access/vendor/brightdata-unlocker.d.ts.map +1 -0
  309. package/dist/humain/web-access/vendor/brightdata-unlocker.js +230 -0
  310. package/dist/humain/web-access/vendor/brightdata-unlocker.js.map +1 -0
  311. package/dist/humain/web-access/vendor/brightdata.d.ts +8 -0
  312. package/dist/humain/web-access/vendor/brightdata.d.ts.map +1 -0
  313. package/dist/humain/web-access/vendor/brightdata.js +519 -0
  314. package/dist/humain/web-access/vendor/brightdata.js.map +1 -0
  315. package/dist/humain/web-access/vendor/chrome-cookies.d.ts +10 -0
  316. package/dist/humain/web-access/vendor/chrome-cookies.d.ts.map +1 -0
  317. package/dist/humain/web-access/vendor/chrome-cookies.js +438 -0
  318. package/dist/humain/web-access/vendor/chrome-cookies.js.map +1 -0
  319. package/dist/humain/web-access/vendor/content-find.d.ts +11 -0
  320. package/dist/humain/web-access/vendor/content-find.d.ts.map +1 -0
  321. package/dist/humain/web-access/vendor/content-find.js +117 -0
  322. package/dist/humain/web-access/vendor/content-find.js.map +1 -0
  323. package/dist/humain/web-access/vendor/credential-source.d.ts +28 -0
  324. package/dist/humain/web-access/vendor/credential-source.d.ts.map +1 -0
  325. package/dist/humain/web-access/vendor/credential-source.js +151 -0
  326. package/dist/humain/web-access/vendor/credential-source.js.map +1 -0
  327. package/dist/humain/web-access/vendor/curator-page.d.ts +29 -0
  328. package/dist/humain/web-access/vendor/curator-page.d.ts.map +1 -0
  329. package/dist/humain/web-access/vendor/curator-page.js +3554 -0
  330. package/dist/humain/web-access/vendor/curator-page.js.map +1 -0
  331. package/dist/humain/web-access/vendor/curator-server.d.ts +93 -0
  332. package/dist/humain/web-access/vendor/curator-server.d.ts.map +1 -0
  333. package/dist/humain/web-access/vendor/curator-server.js +688 -0
  334. package/dist/humain/web-access/vendor/curator-server.js.map +1 -0
  335. package/dist/humain/web-access/vendor/datalab-pdf-extract.d.ts +60 -0
  336. package/dist/humain/web-access/vendor/datalab-pdf-extract.d.ts.map +1 -0
  337. package/dist/humain/web-access/vendor/datalab-pdf-extract.js +416 -0
  338. package/dist/humain/web-access/vendor/datalab-pdf-extract.js.map +1 -0
  339. package/dist/humain/web-access/vendor/declared-web-links.d.ts +16 -0
  340. package/dist/humain/web-access/vendor/declared-web-links.d.ts.map +1 -0
  341. package/dist/humain/web-access/vendor/declared-web-links.js +168 -0
  342. package/dist/humain/web-access/vendor/declared-web-links.js.map +1 -0
  343. package/dist/humain/web-access/vendor/duckduckgo.d.ts +4 -0
  344. package/dist/humain/web-access/vendor/duckduckgo.d.ts.map +1 -0
  345. package/dist/humain/web-access/vendor/duckduckgo.js +123 -0
  346. package/dist/humain/web-access/vendor/duckduckgo.js.map +1 -0
  347. package/dist/humain/web-access/vendor/exa.d.ts +10 -0
  348. package/dist/humain/web-access/vendor/exa.d.ts.map +1 -0
  349. package/dist/humain/web-access/vendor/exa.js +426 -0
  350. package/dist/humain/web-access/vendor/exa.js.map +1 -0
  351. package/dist/humain/web-access/vendor/extract.d.ts +46 -0
  352. package/dist/humain/web-access/vendor/extract.d.ts.map +1 -0
  353. package/dist/humain/web-access/vendor/extract.js +1064 -0
  354. package/dist/humain/web-access/vendor/extract.js.map +1 -0
  355. package/dist/humain/web-access/vendor/feature-config.d.ts +3 -0
  356. package/dist/humain/web-access/vendor/feature-config.d.ts.map +1 -0
  357. package/dist/humain/web-access/vendor/feature-config.js +27 -0
  358. package/dist/humain/web-access/vendor/feature-config.js.map +1 -0
  359. package/dist/humain/web-access/vendor/fetch-params.d.ts +25 -0
  360. package/dist/humain/web-access/vendor/fetch-params.d.ts.map +1 -0
  361. package/dist/humain/web-access/vendor/fetch-params.js +57 -0
  362. package/dist/humain/web-access/vendor/fetch-params.js.map +1 -0
  363. package/dist/humain/web-access/vendor/firecrawl.d.ts +12 -0
  364. package/dist/humain/web-access/vendor/firecrawl.d.ts.map +1 -0
  365. package/dist/humain/web-access/vendor/firecrawl.js +239 -0
  366. package/dist/humain/web-access/vendor/firecrawl.js.map +1 -0
  367. package/dist/humain/web-access/vendor/gemini-api.d.ts +27 -0
  368. package/dist/humain/web-access/vendor/gemini-api.d.ts.map +1 -0
  369. package/dist/humain/web-access/vendor/gemini-api.js +230 -0
  370. package/dist/humain/web-access/vendor/gemini-api.js.map +1 -0
  371. package/dist/humain/web-access/vendor/gemini-pdf-extract.d.ts +9 -0
  372. package/dist/humain/web-access/vendor/gemini-pdf-extract.d.ts.map +1 -0
  373. package/dist/humain/web-access/vendor/gemini-pdf-extract.js +85 -0
  374. package/dist/humain/web-access/vendor/gemini-pdf-extract.js.map +1 -0
  375. package/dist/humain/web-access/vendor/gemini-search.d.ts +40 -0
  376. package/dist/humain/web-access/vendor/gemini-search.d.ts.map +1 -0
  377. package/dist/humain/web-access/vendor/gemini-search.js +814 -0
  378. package/dist/humain/web-access/vendor/gemini-search.js.map +1 -0
  379. package/dist/humain/web-access/vendor/gemini-url-context.d.ts +4 -0
  380. package/dist/humain/web-access/vendor/gemini-url-context.d.ts.map +1 -0
  381. package/dist/humain/web-access/vendor/gemini-url-context.js +101 -0
  382. package/dist/humain/web-access/vendor/gemini-url-context.js.map +1 -0
  383. package/dist/humain/web-access/vendor/gemini-web-config.d.ts +4 -0
  384. package/dist/humain/web-access/vendor/gemini-web-config.d.ts.map +1 -0
  385. package/dist/humain/web-access/vendor/gemini-web-config.js +42 -0
  386. package/dist/humain/web-access/vendor/gemini-web-config.js.map +1 -0
  387. package/dist/humain/web-access/vendor/gemini-web.d.ts +18 -0
  388. package/dist/humain/web-access/vendor/gemini-web.d.ts.map +1 -0
  389. package/dist/humain/web-access/vendor/gemini-web.js +385 -0
  390. package/dist/humain/web-access/vendor/gemini-web.js.map +1 -0
  391. package/dist/humain/web-access/vendor/github-api.d.ts +7 -0
  392. package/dist/humain/web-access/vendor/github-api.d.ts.map +1 -0
  393. package/dist/humain/web-access/vendor/github-api.js +160 -0
  394. package/dist/humain/web-access/vendor/github-api.js.map +1 -0
  395. package/dist/humain/web-access/vendor/github-extract.d.ts +13 -0
  396. package/dist/humain/web-access/vendor/github-extract.d.ts.map +1 -0
  397. package/dist/humain/web-access/vendor/github-extract.js +635 -0
  398. package/dist/humain/web-access/vendor/github-extract.js.map +1 -0
  399. package/dist/humain/web-access/vendor/index.d.ts +4 -0
  400. package/dist/humain/web-access/vendor/index.d.ts.map +1 -0
  401. package/dist/humain/web-access/vendor/index.js +3002 -0
  402. package/dist/humain/web-access/vendor/index.js.map +1 -0
  403. package/dist/humain/web-access/vendor/jina-search.d.ts +8 -0
  404. package/dist/humain/web-access/vendor/jina-search.d.ts.map +1 -0
  405. package/dist/humain/web-access/vendor/jina-search.js +255 -0
  406. package/dist/humain/web-access/vendor/jina-search.js.map +1 -0
  407. package/dist/humain/web-access/vendor/kagi.d.ts +15 -0
  408. package/dist/humain/web-access/vendor/kagi.d.ts.map +1 -0
  409. package/dist/humain/web-access/vendor/kagi.js +262 -0
  410. package/dist/humain/web-access/vendor/kagi.js.map +1 -0
  411. package/dist/humain/web-access/vendor/ollama.d.ts +15 -0
  412. package/dist/humain/web-access/vendor/ollama.d.ts.map +1 -0
  413. package/dist/humain/web-access/vendor/ollama.js +216 -0
  414. package/dist/humain/web-access/vendor/ollama.js.map +1 -0
  415. package/dist/humain/web-access/vendor/openai-search.d.ts +15 -0
  416. package/dist/humain/web-access/vendor/openai-search.d.ts.map +1 -0
  417. package/dist/humain/web-access/vendor/openai-search.js +459 -0
  418. package/dist/humain/web-access/vendor/openai-search.js.map +1 -0
  419. package/dist/humain/web-access/vendor/page-query.d.ts +16 -0
  420. package/dist/humain/web-access/vendor/page-query.d.ts.map +1 -0
  421. package/dist/humain/web-access/vendor/page-query.js +79 -0
  422. package/dist/humain/web-access/vendor/page-query.js.map +1 -0
  423. package/dist/humain/web-access/vendor/parallel.d.ts +12 -0
  424. package/dist/humain/web-access/vendor/parallel.d.ts.map +1 -0
  425. package/dist/humain/web-access/vendor/parallel.js +343 -0
  426. package/dist/humain/web-access/vendor/parallel.js.map +1 -0
  427. package/dist/humain/web-access/vendor/pdf-extract.d.ts +44 -0
  428. package/dist/humain/web-access/vendor/pdf-extract.d.ts.map +1 -0
  429. package/dist/humain/web-access/vendor/pdf-extract.js +298 -0
  430. package/dist/humain/web-access/vendor/pdf-extract.js.map +1 -0
  431. package/dist/humain/web-access/vendor/perplexity.d.ts +20 -0
  432. package/dist/humain/web-access/vendor/perplexity.d.ts.map +1 -0
  433. package/dist/humain/web-access/vendor/perplexity.js +159 -0
  434. package/dist/humain/web-access/vendor/perplexity.js.map +1 -0
  435. package/dist/humain/web-access/vendor/querit.d.ts +10 -0
  436. package/dist/humain/web-access/vendor/querit.d.ts.map +1 -0
  437. package/dist/humain/web-access/vendor/querit.js +335 -0
  438. package/dist/humain/web-access/vendor/querit.js.map +1 -0
  439. package/dist/humain/web-access/vendor/render-search-error.d.ts +57 -0
  440. package/dist/humain/web-access/vendor/render-search-error.d.ts.map +1 -0
  441. package/dist/humain/web-access/vendor/render-search-error.js +130 -0
  442. package/dist/humain/web-access/vendor/render-search-error.js.map +1 -0
  443. package/dist/humain/web-access/vendor/rsc-extract.d.ts +12 -0
  444. package/dist/humain/web-access/vendor/rsc-extract.d.ts.map +1 -0
  445. package/dist/humain/web-access/vendor/rsc-extract.js +329 -0
  446. package/dist/humain/web-access/vendor/rsc-extract.js.map +1 -0
  447. package/dist/humain/web-access/vendor/search1api.d.ts +10 -0
  448. package/dist/humain/web-access/vendor/search1api.d.ts.map +1 -0
  449. package/dist/humain/web-access/vendor/search1api.js +251 -0
  450. package/dist/humain/web-access/vendor/search1api.js.map +1 -0
  451. package/dist/humain/web-access/vendor/searchinfinity.d.ts +8 -0
  452. package/dist/humain/web-access/vendor/searchinfinity.d.ts.map +1 -0
  453. package/dist/humain/web-access/vendor/searchinfinity.js +229 -0
  454. package/dist/humain/web-access/vendor/searchinfinity.js.map +1 -0
  455. package/dist/humain/web-access/vendor/searxng.d.ts +4 -0
  456. package/dist/humain/web-access/vendor/searxng.d.ts.map +1 -0
  457. package/dist/humain/web-access/vendor/searxng.js +238 -0
  458. package/dist/humain/web-access/vendor/searxng.js.map +1 -0
  459. package/dist/humain/web-access/vendor/serpbase.d.ts +4 -0
  460. package/dist/humain/web-access/vendor/serpbase.d.ts.map +1 -0
  461. package/dist/humain/web-access/vendor/serpbase.js +211 -0
  462. package/dist/humain/web-access/vendor/serpbase.js.map +1 -0
  463. package/dist/humain/web-access/vendor/serpdive.d.ts +8 -0
  464. package/dist/humain/web-access/vendor/serpdive.d.ts.map +1 -0
  465. package/dist/humain/web-access/vendor/serpdive.js +267 -0
  466. package/dist/humain/web-access/vendor/serpdive.js.map +1 -0
  467. package/dist/humain/web-access/vendor/source-check.d.ts +99 -0
  468. package/dist/humain/web-access/vendor/source-check.d.ts.map +1 -0
  469. package/dist/humain/web-access/vendor/source-check.js +205 -0
  470. package/dist/humain/web-access/vendor/source-check.js.map +1 -0
  471. package/dist/humain/web-access/vendor/ssrf-protection.d.ts +50 -0
  472. package/dist/humain/web-access/vendor/ssrf-protection.d.ts.map +1 -0
  473. package/dist/humain/web-access/vendor/ssrf-protection.js +466 -0
  474. package/dist/humain/web-access/vendor/ssrf-protection.js.map +1 -0
  475. package/dist/humain/web-access/vendor/storage.d.ts +55 -0
  476. package/dist/humain/web-access/vendor/storage.d.ts.map +1 -0
  477. package/dist/humain/web-access/vendor/storage.js +485 -0
  478. package/dist/humain/web-access/vendor/storage.js.map +1 -0
  479. package/dist/humain/web-access/vendor/summary-model-scope.d.ts +25 -0
  480. package/dist/humain/web-access/vendor/summary-model-scope.d.ts.map +1 -0
  481. package/dist/humain/web-access/vendor/summary-model-scope.js +98 -0
  482. package/dist/humain/web-access/vendor/summary-model-scope.js.map +1 -0
  483. package/dist/humain/web-access/vendor/summary-review.d.ts +24 -0
  484. package/dist/humain/web-access/vendor/summary-review.d.ts.map +1 -0
  485. package/dist/humain/web-access/vendor/summary-review.js +341 -0
  486. package/dist/humain/web-access/vendor/summary-review.js.map +1 -0
  487. package/dist/humain/web-access/vendor/tavily.d.ts +8 -0
  488. package/dist/humain/web-access/vendor/tavily.d.ts.map +1 -0
  489. package/dist/humain/web-access/vendor/tavily.js +194 -0
  490. package/dist/humain/web-access/vendor/tavily.js.map +1 -0
  491. package/dist/humain/web-access/vendor/tinyfish.d.ts +11 -0
  492. package/dist/humain/web-access/vendor/tinyfish.d.ts.map +1 -0
  493. package/dist/humain/web-access/vendor/tinyfish.js +331 -0
  494. package/dist/humain/web-access/vendor/tinyfish.js.map +1 -0
  495. package/dist/humain/web-access/vendor/utils.d.ts +20 -0
  496. package/dist/humain/web-access/vendor/utils.d.ts.map +1 -0
  497. package/dist/humain/web-access/vendor/utils.js +91 -0
  498. package/dist/humain/web-access/vendor/utils.js.map +1 -0
  499. package/dist/humain/web-access/vendor/video-extract.d.ts +16 -0
  500. package/dist/humain/web-access/vendor/video-extract.d.ts.map +1 -0
  501. package/dist/humain/web-access/vendor/video-extract.js +335 -0
  502. package/dist/humain/web-access/vendor/video-extract.js.map +1 -0
  503. package/dist/humain/web-access/vendor/xai-search.d.ts +13 -0
  504. package/dist/humain/web-access/vendor/xai-search.d.ts.map +1 -0
  505. package/dist/humain/web-access/vendor/xai-search.js +331 -0
  506. package/dist/humain/web-access/vendor/xai-search.js.map +1 -0
  507. package/dist/humain/web-access/vendor/youtube-extract.d.ts +27 -0
  508. package/dist/humain/web-access/vendor/youtube-extract.d.ts.map +1 -0
  509. package/dist/humain/web-access/vendor/youtube-extract.js +282 -0
  510. package/dist/humain/web-access/vendor/youtube-extract.js.map +1 -0
  511. package/dist/index.d.ts +7 -4
  512. package/dist/index.d.ts.map +1 -1
  513. package/dist/index.js +5 -2
  514. package/dist/index.js.map +1 -1
  515. package/dist/main.d.ts +2 -2
  516. package/dist/main.d.ts.map +1 -1
  517. package/dist/main.js +169 -102
  518. package/dist/main.js.map +1 -1
  519. package/dist/modes/agent-exec-mode.d.ts +14 -0
  520. package/dist/modes/agent-exec-mode.d.ts.map +1 -0
  521. package/dist/modes/agent-exec-mode.js +92 -0
  522. package/dist/modes/agent-exec-mode.js.map +1 -0
  523. package/dist/modes/index.d.ts +4 -2
  524. package/dist/modes/index.d.ts.map +1 -1
  525. package/dist/modes/index.js +2 -1
  526. package/dist/modes/index.js.map +1 -1
  527. package/dist/modes/interactive/components/assistant-message.d.ts +5 -2
  528. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  529. package/dist/modes/interactive/components/assistant-message.js +13 -4
  530. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  531. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  532. package/dist/modes/interactive/components/custom-editor.js +7 -0
  533. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  534. package/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
  535. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -0
  536. package/dist/modes/interactive/components/earendil-announcement.js +40 -0
  537. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -0
  538. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  539. package/dist/modes/interactive/components/footer.js +1 -1
  540. package/dist/modes/interactive/components/footer.js.map +1 -1
  541. package/dist/modes/interactive/components/markdown-transform.d.ts +3 -0
  542. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -0
  543. package/dist/modes/interactive/components/markdown-transform.js +19 -0
  544. package/dist/modes/interactive/components/markdown-transform.js.map +1 -0
  545. package/dist/modes/interactive/components/mermaid.d.ts +11 -0
  546. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
  547. package/dist/modes/interactive/components/mermaid.js +75 -0
  548. package/dist/modes/interactive/components/mermaid.js.map +1 -0
  549. package/dist/modes/interactive/components/model-selector.d.ts +1 -1
  550. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  551. package/dist/modes/interactive/components/model-selector.js +16 -4
  552. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  553. package/dist/modes/interactive/components/scoped-models-selector.d.ts +4 -0
  554. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  555. package/dist/modes/interactive/components/scoped-models-selector.js +26 -0
  556. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  557. package/dist/modes/interactive/components/settings-selector.d.ts +8 -2
  558. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  559. package/dist/modes/interactive/components/settings-selector.js +30 -0
  560. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  561. package/dist/modes/interactive/components/user-message.d.ts +3 -1
  562. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  563. package/dist/modes/interactive/components/user-message.js +9 -2
  564. package/dist/modes/interactive/components/user-message.js.map +1 -1
  565. package/dist/modes/interactive/interactive-mode.d.ts +45 -9
  566. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  567. package/dist/modes/interactive/interactive-mode.js +581 -211
  568. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  569. package/dist/modes/interactive/theme/dark.json +1 -0
  570. package/dist/modes/interactive/theme/light.json +1 -0
  571. package/dist/modes/interactive/theme/theme-controller.d.ts +3 -0
  572. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  573. package/dist/modes/interactive/theme/theme-controller.js +10 -1
  574. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  575. package/dist/modes/interactive/theme/theme-schema.json +5 -1
  576. package/dist/modes/interactive/theme/theme.d.ts +2 -2
  577. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  578. package/dist/modes/interactive/theme/theme.js +24 -6
  579. package/dist/modes/interactive/theme/theme.js.map +1 -1
  580. package/dist/modes/json-event.d.ts +28 -0
  581. package/dist/modes/json-event.d.ts.map +1 -0
  582. package/dist/modes/json-event.js +12 -0
  583. package/dist/modes/json-event.js.map +1 -0
  584. package/dist/modes/print-mode.d.ts.map +1 -1
  585. package/dist/modes/print-mode.js +12 -2
  586. package/dist/modes/print-mode.js.map +1 -1
  587. package/dist/modes/rpc/rpc-client.d.ts +12 -5
  588. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  589. package/dist/modes/rpc/rpc-client.js +55 -1
  590. package/dist/modes/rpc/rpc-client.js.map +1 -1
  591. package/dist/modes/rpc/rpc-mode.d.ts +1 -1
  592. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  593. package/dist/modes/rpc/rpc-mode.js +13 -3
  594. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  595. package/dist/modes/rpc/rpc-types.d.ts +15 -0
  596. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  597. package/dist/modes/rpc/rpc-types.js.map +1 -1
  598. package/dist/package-manager-cli.d.ts.map +1 -1
  599. package/dist/package-manager-cli.js +11 -9
  600. package/dist/package-manager-cli.js.map +1 -1
  601. package/dist/rpc-entry.d.ts.map +1 -1
  602. package/dist/rpc-entry.js +3 -2
  603. package/dist/rpc-entry.js.map +1 -1
  604. package/dist/server/create-harness.d.ts +26 -0
  605. package/dist/server/create-harness.d.ts.map +1 -0
  606. package/dist/server/create-harness.js +104 -0
  607. package/dist/server/create-harness.js.map +1 -0
  608. package/dist/utils/abort.d.ts +5 -0
  609. package/dist/utils/abort.d.ts.map +1 -0
  610. package/dist/utils/abort.js +48 -0
  611. package/dist/utils/abort.js.map +1 -0
  612. package/dist/utils/clipboard.d.ts +1 -1
  613. package/dist/utils/clipboard.d.ts.map +1 -1
  614. package/dist/utils/clipboard.js +22 -2
  615. package/dist/utils/clipboard.js.map +1 -1
  616. package/dist/utils/management-http.d.ts +23 -0
  617. package/dist/utils/management-http.d.ts.map +1 -0
  618. package/dist/utils/management-http.js +50 -0
  619. package/dist/utils/management-http.js.map +1 -0
  620. package/dist/utils/paths.d.ts +3 -0
  621. package/dist/utils/paths.d.ts.map +1 -1
  622. package/dist/utils/paths.js +23 -1
  623. package/dist/utils/paths.js.map +1 -1
  624. package/dist/utils/tool-result-images.d.ts +19 -0
  625. package/dist/utils/tool-result-images.d.ts.map +1 -0
  626. package/dist/utils/tool-result-images.js +45 -0
  627. package/dist/utils/tool-result-images.js.map +1 -0
  628. package/dist/utils/tools-manager.d.ts.map +1 -1
  629. package/dist/utils/tools-manager.js +13 -25
  630. package/dist/utils/tools-manager.js.map +1 -1
  631. package/dist/utils/version-check.d.ts +4 -0
  632. package/dist/utils/version-check.d.ts.map +1 -1
  633. package/dist/utils/version-check.js +23 -5
  634. package/dist/utils/version-check.js.map +1 -1
  635. package/docs/compaction.md +2 -2
  636. package/docs/custom-provider.md +7 -5
  637. package/docs/extensions.md +30 -5
  638. package/docs/humain-terminal.md +21 -1
  639. package/docs/json.md +24 -19
  640. package/docs/keybindings.md +46 -14
  641. package/docs/models.md +32 -11
  642. package/docs/providers.md +9 -1
  643. package/docs/quickstart.md +39 -37
  644. package/docs/rpc.md +31 -11
  645. package/docs/sdk.md +21 -2
  646. package/docs/security.md +21 -21
  647. package/docs/session-format.md +14 -14
  648. package/docs/settings.md +4 -1
  649. package/docs/themes.md +5 -3
  650. package/docs/usage.md +7 -0
  651. package/examples/extensions/custom-compaction.ts +3 -18
  652. package/examples/extensions/custom-provider-anthropic/index.ts +5 -1
  653. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  654. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  655. package/examples/extensions/custom-provider-gitlab-duo/index.ts +5 -1
  656. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  657. package/examples/extensions/doom-overlay/wad-finder.ts +7 -3
  658. package/examples/extensions/gondolin/package-lock.json +2 -2
  659. package/examples/extensions/gondolin/package.json +1 -1
  660. package/examples/extensions/handoff.ts +4 -13
  661. package/examples/extensions/qna.ts +5 -9
  662. package/examples/extensions/sandbox/package-lock.json +2 -2
  663. package/examples/extensions/sandbox/package.json +1 -1
  664. package/examples/extensions/summarize.ts +9 -20
  665. package/examples/extensions/with-deps/package-lock.json +2 -2
  666. package/examples/extensions/with-deps/package.json +1 -1
  667. package/examples/rpc-extension-ui.ts +11 -2
  668. package/examples/sdk/02-custom-model.ts +2 -3
  669. package/examples/sdk/09-api-keys-and-oauth.ts +1 -1
  670. package/examples/sdk/12-full-control.ts +1 -1
  671. package/examples/sdk/README.md +1 -1
  672. package/npm-shrinkwrap.json +2771 -535
  673. package/package.json +40 -11
  674. package/src/humain/mcp-adapter/UPSTREAM.md +15 -0
  675. package/src/humain/mcp-adapter/upstream.json +7 -0
  676. package/src/humain/mcp-adapter/vendor/CHANGELOG.md +660 -0
  677. package/src/humain/mcp-adapter/vendor/LICENSE +21 -0
  678. package/src/humain/web-access/UPSTREAM.md +17 -0
  679. package/src/humain/web-access/upstream.json +23 -0
  680. package/src/humain/web-access/vendor/LICENSE +21 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kagi.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/kagi.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { ExtractedContent, ExtractOptions } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { fetchRemoteUrl, loadFetchContentDomainPolicy, loadSsrfConfig, validateRemoteUrl, type SsrfConfig } from \"./ssrf-protection.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst KAGI_SEARCH_URL = \"https://kagi.com/api/v1/search\";\nconst KAGI_EXTRACT_URL = \"https://kagi.com/api/v1/extract\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\n\ninterface WebSearchConfig {\n\tkagiApiKey?: unknown;\n}\n\ninterface KagiSearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\nexport interface KagiExtractOptions extends Pick<ExtractOptions, \"timeoutMs\" | \"lookup\"> {\n\tssrf?: SsrfConfig;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string | null> {\n\treturn resolveCredential({\n\t\tprovider: \"Kagi\",\n\t\tconfiguredValue: loadConfig().kagiApiKey,\n\t\tenvironmentValue: process.env.KAGI_API_KEY,\n\t\tsignal,\n\t});\n}\n\nasync function requireApiKey(signal?: AbortSignal): Promise<string> {\n\tconst apiKey = await getApiKey(signal);\n\tif (!apiKey) {\n\t\tthrow new Error(\n\t\t\t\"Kagi API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"kagiApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set KAGI_API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://kagi.com/settings?p=api\",\n\t\t);\n\t}\n\treturn apiKey;\n}\n\nfunction normalizeCount(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 20));\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction invalidResponse(message: string): Error {\n\treturn new Error(`Kagi API returned invalid response: ${message}`);\n}\n\nfunction firstString(...values: unknown[]): string | null {\n\tfor (const value of values) {\n\t\tif (typeof value === \"string\" && value.trim()) return value.trim();\n\t}\n\treturn null;\n}\n\nfunction appendSearchItems(value: unknown, results: SearchResponse[\"results\"], inlineContent: ExtractedContent[]): void {\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) appendSearchItems(item, results, inlineContent);\n\t\treturn;\n\t}\n\tif (!value || typeof value !== \"object\") return;\n\tconst item = value as Record<string, unknown>;\n\tconst url = firstString(item.url, item.href, item.link);\n\tif (!url) return;\n\tconst title = firstString(item.title, item.name) ?? url;\n\tconst snippet = firstString(item.snippet, item.description, item.summary, item.content, item.markdown, item.text) ?? \"\";\n\tresults.push({ title, url, snippet });\n\tconst content = firstString(item.markdown, item.content, item.text);\n\tif (content) inlineContent.push({ url, title, content, error: null });\n}\n\nfunction parseErrors(value: unknown): string | null {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n\tconst envelope = value as Record<string, unknown>;\n\tconst rawErrors = envelope.errors ?? envelope.error;\n\tif (!Array.isArray(rawErrors)) return null;\n\tconst messages = rawErrors.map((entry) => {\n\t\tif (!entry || typeof entry !== \"object\") return String(entry);\n\t\tconst raw = entry as Record<string, unknown>;\n\t\treturn firstString(raw.message, raw.msg, raw.code) ?? JSON.stringify(raw);\n\t});\n\treturn messages.length > 0 ? messages.join(\"; \") : null;\n}\n\nfunction parseSearchResponse(value: unknown): { results: SearchResponse[\"results\"]; inlineContent: ExtractedContent[] } {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(\"expected an object envelope\");\n\tconst message = parseErrors(value);\n\tif (message) throw invalidResponse(message);\n\tconst envelope = value as Record<string, unknown>;\n\tconst results: SearchResponse[\"results\"] = [];\n\tconst inlineContent: ExtractedContent[] = [];\n\tconst data = envelope.data;\n\tconst items = (typeof data === \"object\" && data !== null && !Array.isArray(data))\n\t\t? (data as Record<string, unknown>).search\n\t\t: data;\n\tappendSearchItems(items, results, inlineContent);\n\treturn { results, inlineContent };\n}\n\nfunction parseExtractResponse(value: unknown, requestedUrl: string): ExtractedContent | null {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(\"expected extract object envelope\");\n\tconst message = parseErrors(value);\n\tif (message) throw invalidResponse(message);\n\tconst envelope = value as Record<string, unknown>;\n\tconst candidates = Array.isArray(envelope.data) ? envelope.data : [envelope.data ?? envelope];\n\tfor (const candidate of candidates) {\n\t\tif (!candidate || typeof candidate !== \"object\" || Array.isArray(candidate)) continue;\n\t\tconst item = candidate as Record<string, unknown>;\n\t\tconst content = firstString(item.markdown, item.content, item.text);\n\t\tif (!content) continue;\n\t\treturn {\n\t\t\turl: firstString(item.url, item.href, item.link) ?? requestedUrl,\n\t\t\ttitle: firstString(item.title, item.name) ?? requestedUrl,\n\t\t\tcontent,\n\t\t\terror: null,\n\t\t};\n\t}\n\treturn null;\n}\n\nfunction buildAnswer(results: SearchResponse[\"results\"]): string {\n\treturn results.map((result) => result.snippet\n\t\t? `${result.snippet}\\nSource: ${result.title} (${result.url})`\n\t\t: `Source: ${result.title} (${result.url})`).join(\"\\n\\n\");\n}\n\nexport function isKagiAvailable(): boolean {\n\treturn hasCredentialSource({ provider: \"Kagi\", configuredValue: loadConfig().kagiApiKey, environmentValue: process.env.KAGI_API_KEY });\n}\n\nexport async function searchWithKagi(query: string, options: KagiSearchOptions = {}): Promise<SearchResponse> {\n\tconst apiKey = await requireApiKey(options.signal);\n\tconst numResults = normalizeCount(options.numResults);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(KAGI_SEARCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\", Accept: \"application/json\" },\n\t\t\tbody: JSON.stringify({ query, limit: numResults }),\n\t\t\tsignal: options.signal ? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal]) : AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Kagi API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Kagi API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\tconst parsed = parseSearchResponse(rawData);\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst results = parsed.results.slice(0, numResults);\n\tconst mapped: SearchResponse = { answer: buildAnswer(results), results };\n\tif (options.includeContent) {\n\t\tconst urls = new Set(results.map(result => result.url));\n\t\tconst inlineContent = parsed.inlineContent.filter(content => urls.has(content.url));\n\t\tif (inlineContent.length > 0) mapped.inlineContent = inlineContent;\n\t}\n\treturn mapped;\n}\n\nexport function isKagiExtractAvailable(): boolean {\n\treturn isKagiAvailable();\n}\n\nexport async function extractWithKagi(url: string, signal?: AbortSignal, options: KagiExtractOptions = {}): Promise<ExtractedContent | null> {\n\tconst ssrf = options.ssrf ?? loadSsrfConfig();\n\tconst domainPolicy = loadFetchContentDomainPolicy();\n\tawait validateRemoteUrl(url, {\n\t\tallowRanges: ssrf.allowRanges,\n\t\ttrustEnvProxy: ssrf.trustEnvProxy,\n\t\tdomainPolicy,\n\t\t...(options.lookup ? { lookup: options.lookup } : {}),\n\t});\n\tconst apiKey = await requireApiKey(signal);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query: `kagi extract: ${url}` });\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetchRemoteUrl(KAGI_EXTRACT_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\", Accept: \"application/json\" },\n\t\t\tbody: JSON.stringify({ pages: [{ url }] }),\n\t\t\tsignal: signal ? AbortSignal.any([AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS), signal]) : AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS),\n\t\t}, {\n\t\t\tallowRanges: ssrf.allowRanges,\n\t\t\ttrustEnvProxy: ssrf.trustEnvProxy,\n\t\t\tonRedirect: ({ from, to, init }) => to.origin === from.origin ? init : { ...init, headers: { \"Content-Type\": \"application/json\", Accept: \"application/json\" } },\n\t\t\t...(options.lookup ? { lookup: options.lookup } : {}),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Kagi Extract API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Kagi Extract API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\tconst parsed = parseExtractResponse(rawData, url);\n\tactivityMonitor.logComplete(activityId, response.status);\n\treturn parsed;\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import type { ExtractedContent, ExtractOptions } from "./extract.ts";
2
+ import type { SearchOptions, SearchResponse } from "./perplexity.ts";
3
+ import { type SsrfConfig } from "./ssrf-protection.ts";
4
+ interface OllamaSearchOptions extends SearchOptions {
5
+ includeContent?: boolean;
6
+ }
7
+ export interface OllamaExtractOptions extends Pick<ExtractOptions, "timeoutMs" | "lookup"> {
8
+ ssrf?: SsrfConfig;
9
+ }
10
+ export declare function isOllamaAvailable(): boolean;
11
+ export declare function searchWithOllama(query: string, options?: OllamaSearchOptions): Promise<SearchResponse>;
12
+ export declare function isOllamaFetchAvailable(): boolean;
13
+ export declare function extractWithOllama(url: string, signal?: AbortSignal, options?: OllamaExtractOptions): Promise<ExtractedContent | null>;
14
+ export {};
15
+ //# sourceMappingURL=ollama.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/ollama.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAErE,OAAO,EAAgG,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AA4BrJ,UAAU,mBAAoB,SAAQ,aAAa;IAClD,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,QAAQ,CAAC;IACzF,IAAI,CAAC,EAAE,UAAU,CAAC;CAClB;AA2FD,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,cAAc,CAAC,CAgDhH;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAoD/I","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { ExtractedContent, ExtractOptions } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { fetchRemoteUrl, loadFetchContentDomainPolicy, loadSsrfConfig, validateRemoteUrl, type Lookup, type SsrfConfig } from \"./ssrf-protection.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst OLLAMA_SEARCH_URL = \"https://ollama.com/api/web_search\";\nconst OLLAMA_FETCH_URL = \"https://ollama.com/api/web_fetch\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\n\ninterface WebSearchConfig {\n\tollamaApiKey?: unknown;\n}\n\ninterface OllamaSearchResult {\n\ttitle: string;\n\turl: string;\n\tcontent: string;\n}\n\ninterface OllamaSearchResponse {\n\tresults: OllamaSearchResult[];\n}\n\ninterface OllamaFetchResponse {\n\ttitle: string;\n\tcontent: string;\n\tlinks?: unknown;\n}\n\ninterface OllamaSearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\nexport interface OllamaExtractOptions extends Pick<ExtractOptions, \"timeoutMs\" | \"lookup\"> {\n\tssrf?: SsrfConfig;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string | null> {\n\treturn resolveCredential({\n\t\tprovider: \"Ollama\",\n\t\tconfiguredValue: loadConfig().ollamaApiKey,\n\t\tenvironmentValue: process.env.OLLAMA_API_KEY,\n\t\tsignal,\n\t});\n}\n\nasync function requireApiKey(signal?: AbortSignal): Promise<string> {\n\tconst apiKey = await getApiKey(signal);\n\tif (!apiKey) {\n\t\tthrow new Error(\n\t\t\t\"Ollama API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"ollamaApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set OLLAMA_API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://ollama.com/settings/keys\",\n\t\t);\n\t}\n\treturn apiKey;\n}\n\nfunction normalizeCount(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 10));\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction invalidResponse(message: string): Error {\n\treturn new Error(`Ollama API returned invalid response: ${message}`);\n}\n\nfunction parseSearchResponse(value: unknown): OllamaSearchResponse {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(\"expected an object envelope\");\n\tconst envelope = value as Record<string, unknown>;\n\tif (!Array.isArray(envelope.results)) throw invalidResponse(\"expected results array\");\n\tconst results: OllamaSearchResult[] = [];\n\tfor (const [index, value] of envelope.results.entries()) {\n\t\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(`expected results[${index}] object`);\n\t\tconst item = value as Record<string, unknown>;\n\t\tif (typeof item.title !== \"string\") throw invalidResponse(`expected results[${index}].title string`);\n\t\tif (typeof item.url !== \"string\" || !item.url) throw invalidResponse(`expected results[${index}].url non-empty string`);\n\t\tif (typeof item.content !== \"string\") throw invalidResponse(`expected results[${index}].content string`);\n\t\tresults.push({ title: item.title, url: item.url, content: item.content });\n\t}\n\treturn { results };\n}\n\nfunction parseFetchResponse(value: unknown): OllamaFetchResponse {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(\"expected fetch object envelope\");\n\tconst envelope = value as Record<string, unknown>;\n\tif (typeof envelope.title !== \"string\") throw invalidResponse(\"expected title string\");\n\tif (typeof envelope.content !== \"string\") throw invalidResponse(\"expected content string\");\n\treturn { title: envelope.title, content: envelope.content, links: envelope.links };\n}\n\nfunction buildAnswer(results: SearchResponse[\"results\"]): string {\n\treturn results.map((result) => result.snippet\n\t\t? `${result.snippet}\\nSource: ${result.title} (${result.url})`\n\t\t: `Source: ${result.title} (${result.url})`).join(\"\\n\\n\");\n}\n\nexport function isOllamaAvailable(): boolean {\n\treturn hasCredentialSource({ provider: \"Ollama\", configuredValue: loadConfig().ollamaApiKey, environmentValue: process.env.OLLAMA_API_KEY });\n}\n\nexport async function searchWithOllama(query: string, options: OllamaSearchOptions = {}): Promise<SearchResponse> {\n\tconst apiKey = await requireApiKey(options.signal);\n\tconst numResults = normalizeCount(options.numResults);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(OLLAMA_SEARCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ query, max_results: numResults }),\n\t\t\tsignal: options.signal ? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal]) : AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Ollama API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Ollama API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\n\tconst data = parseSearchResponse(rawData);\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst results = data.results.slice(0, numResults).map((result) => ({ title: result.title, url: result.url, snippet: result.content }));\n\tconst mapped: SearchResponse = { answer: buildAnswer(results), results };\n\tif (options.includeContent) {\n\t\tconst inlineContent: ExtractedContent[] = data.results.slice(0, numResults)\n\t\t\t.filter(result => result.content.trim().length > 0)\n\t\t\t.map(result => ({ url: result.url, title: result.title, content: result.content, error: null }));\n\t\tif (inlineContent.length > 0) mapped.inlineContent = inlineContent;\n\t}\n\treturn mapped;\n}\n\nexport function isOllamaFetchAvailable(): boolean {\n\treturn isOllamaAvailable();\n}\n\nexport async function extractWithOllama(url: string, signal?: AbortSignal, options: OllamaExtractOptions = {}): Promise<ExtractedContent | null> {\n\tconst ssrf = options.ssrf ?? loadSsrfConfig();\n\tconst domainPolicy = loadFetchContentDomainPolicy();\n\tawait validateRemoteUrl(url, {\n\t\tallowRanges: ssrf.allowRanges,\n\t\ttrustEnvProxy: ssrf.trustEnvProxy,\n\t\tdomainPolicy,\n\t\t...(options.lookup ? { lookup: options.lookup } : {}),\n\t});\n\tconst apiKey = await requireApiKey(signal);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query: `ollama fetch: ${url}` });\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetchRemoteUrl(OLLAMA_FETCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ url }),\n\t\t\tsignal: signal ? AbortSignal.any([AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS), signal]) : AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS),\n\t\t}, {\n\t\t\tallowRanges: ssrf.allowRanges,\n\t\t\ttrustEnvProxy: ssrf.trustEnvProxy,\n\t\t\tonRedirect: ({ from, to, init }) => to.origin === from.origin ? init : { ...init, headers: { \"Content-Type\": \"application/json\" } },\n\t\t\t...(options.lookup ? { lookup: options.lookup } : {}),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Ollama Web Fetch error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Ollama Web Fetch returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\tconst data = parseFetchResponse(rawData);\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst content = data.content.trim();\n\tif (!content) return null;\n\treturn { url, title: data.title, content, error: null };\n}\n"]}
@@ -0,0 +1,216 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { activityMonitor } from "./activity.js";
3
+ import { hasCredentialSource, redactCredential, resolveCredential } from "./credential-source.js";
4
+ import { fetchRemoteUrl, loadFetchContentDomainPolicy, loadSsrfConfig, validateRemoteUrl } from "./ssrf-protection.js";
5
+ import { getWebSearchConfigPath } from "./utils.js";
6
+ const OLLAMA_SEARCH_URL = "https://ollama.com/api/web_search";
7
+ const OLLAMA_FETCH_URL = "https://ollama.com/api/web_fetch";
8
+ const CONFIG_PATH = getWebSearchConfigPath();
9
+ const SEARCH_TIMEOUT_MS = 60_000;
10
+ let cachedConfig = null;
11
+ function loadConfig() {
12
+ if (cachedConfig)
13
+ return cachedConfig;
14
+ if (!existsSync(CONFIG_PATH)) {
15
+ cachedConfig = {};
16
+ return cachedConfig;
17
+ }
18
+ const raw = readFileSync(CONFIG_PATH, "utf-8");
19
+ let parsed;
20
+ try {
21
+ parsed = JSON.parse(raw);
22
+ }
23
+ catch (err) {
24
+ const message = err instanceof Error ? err.message : String(err);
25
+ throw new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);
26
+ }
27
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
28
+ throw new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);
29
+ }
30
+ cachedConfig = parsed;
31
+ return cachedConfig;
32
+ }
33
+ async function getApiKey(signal) {
34
+ return resolveCredential({
35
+ provider: "Ollama",
36
+ configuredValue: loadConfig().ollamaApiKey,
37
+ environmentValue: process.env.OLLAMA_API_KEY,
38
+ signal,
39
+ });
40
+ }
41
+ async function requireApiKey(signal) {
42
+ const apiKey = await getApiKey(signal);
43
+ if (!apiKey) {
44
+ throw new Error("Ollama API key not found. Either:\n" +
45
+ ` 1. Create ${CONFIG_PATH} with { "ollamaApiKey": "your-key" }\n` +
46
+ " 2. Set OLLAMA_API_KEY environment variable\n" +
47
+ "Create a key at https://ollama.com/settings/keys");
48
+ }
49
+ return apiKey;
50
+ }
51
+ function normalizeCount(value) {
52
+ if (typeof value !== "number" || !Number.isFinite(value))
53
+ return 5;
54
+ return Math.max(1, Math.min(Math.floor(value), 10));
55
+ }
56
+ function errorMessage(err) {
57
+ return err instanceof Error ? err.message : String(err);
58
+ }
59
+ function invalidResponse(message) {
60
+ return new Error(`Ollama API returned invalid response: ${message}`);
61
+ }
62
+ function parseSearchResponse(value) {
63
+ if (!value || typeof value !== "object" || Array.isArray(value))
64
+ throw invalidResponse("expected an object envelope");
65
+ const envelope = value;
66
+ if (!Array.isArray(envelope.results))
67
+ throw invalidResponse("expected results array");
68
+ const results = [];
69
+ for (const [index, value] of envelope.results.entries()) {
70
+ if (!value || typeof value !== "object" || Array.isArray(value))
71
+ throw invalidResponse(`expected results[${index}] object`);
72
+ const item = value;
73
+ if (typeof item.title !== "string")
74
+ throw invalidResponse(`expected results[${index}].title string`);
75
+ if (typeof item.url !== "string" || !item.url)
76
+ throw invalidResponse(`expected results[${index}].url non-empty string`);
77
+ if (typeof item.content !== "string")
78
+ throw invalidResponse(`expected results[${index}].content string`);
79
+ results.push({ title: item.title, url: item.url, content: item.content });
80
+ }
81
+ return { results };
82
+ }
83
+ function parseFetchResponse(value) {
84
+ if (!value || typeof value !== "object" || Array.isArray(value))
85
+ throw invalidResponse("expected fetch object envelope");
86
+ const envelope = value;
87
+ if (typeof envelope.title !== "string")
88
+ throw invalidResponse("expected title string");
89
+ if (typeof envelope.content !== "string")
90
+ throw invalidResponse("expected content string");
91
+ return { title: envelope.title, content: envelope.content, links: envelope.links };
92
+ }
93
+ function buildAnswer(results) {
94
+ return results.map((result) => result.snippet
95
+ ? `${result.snippet}\nSource: ${result.title} (${result.url})`
96
+ : `Source: ${result.title} (${result.url})`).join("\n\n");
97
+ }
98
+ export function isOllamaAvailable() {
99
+ return hasCredentialSource({ provider: "Ollama", configuredValue: loadConfig().ollamaApiKey, environmentValue: process.env.OLLAMA_API_KEY });
100
+ }
101
+ export async function searchWithOllama(query, options = {}) {
102
+ const apiKey = await requireApiKey(options.signal);
103
+ const numResults = normalizeCount(options.numResults);
104
+ const activityId = activityMonitor.logStart({ type: "api", query });
105
+ let response;
106
+ try {
107
+ response = await fetch(OLLAMA_SEARCH_URL, {
108
+ method: "POST",
109
+ headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
110
+ body: JSON.stringify({ query, max_results: numResults }),
111
+ signal: options.signal ? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal]) : AbortSignal.timeout(SEARCH_TIMEOUT_MS),
112
+ });
113
+ }
114
+ catch (err) {
115
+ const message = errorMessage(err);
116
+ const redactedMessage = redactCredential(message, apiKey);
117
+ if (redactedMessage.toLowerCase().includes("abort"))
118
+ activityMonitor.logComplete(activityId, 0);
119
+ else
120
+ activityMonitor.logError(activityId, redactedMessage);
121
+ if (redactedMessage === message)
122
+ throw err;
123
+ const redactedError = new Error(redactedMessage);
124
+ if (err instanceof Error)
125
+ redactedError.name = err.name;
126
+ throw redactedError;
127
+ }
128
+ if (!response.ok) {
129
+ activityMonitor.logComplete(activityId, response.status);
130
+ const errorText = redactCredential(await response.text(), apiKey);
131
+ throw new Error(`Ollama API error ${response.status}: ${errorText.slice(0, 300)}`);
132
+ }
133
+ let rawData;
134
+ try {
135
+ rawData = await response.json();
136
+ }
137
+ catch (err) {
138
+ activityMonitor.logComplete(activityId, response.status);
139
+ throw new Error(`Ollama API returned invalid JSON: ${errorMessage(err)}`);
140
+ }
141
+ const data = parseSearchResponse(rawData);
142
+ activityMonitor.logComplete(activityId, response.status);
143
+ const results = data.results.slice(0, numResults).map((result) => ({ title: result.title, url: result.url, snippet: result.content }));
144
+ const mapped = { answer: buildAnswer(results), results };
145
+ if (options.includeContent) {
146
+ const inlineContent = data.results.slice(0, numResults)
147
+ .filter(result => result.content.trim().length > 0)
148
+ .map(result => ({ url: result.url, title: result.title, content: result.content, error: null }));
149
+ if (inlineContent.length > 0)
150
+ mapped.inlineContent = inlineContent;
151
+ }
152
+ return mapped;
153
+ }
154
+ export function isOllamaFetchAvailable() {
155
+ return isOllamaAvailable();
156
+ }
157
+ export async function extractWithOllama(url, signal, options = {}) {
158
+ const ssrf = options.ssrf ?? loadSsrfConfig();
159
+ const domainPolicy = loadFetchContentDomainPolicy();
160
+ await validateRemoteUrl(url, {
161
+ allowRanges: ssrf.allowRanges,
162
+ trustEnvProxy: ssrf.trustEnvProxy,
163
+ domainPolicy,
164
+ ...(options.lookup ? { lookup: options.lookup } : {}),
165
+ });
166
+ const apiKey = await requireApiKey(signal);
167
+ const activityId = activityMonitor.logStart({ type: "api", query: `ollama fetch: ${url}` });
168
+ let response;
169
+ try {
170
+ response = await fetchRemoteUrl(OLLAMA_FETCH_URL, {
171
+ method: "POST",
172
+ headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
173
+ body: JSON.stringify({ url }),
174
+ signal: signal ? AbortSignal.any([AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS), signal]) : AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS),
175
+ }, {
176
+ allowRanges: ssrf.allowRanges,
177
+ trustEnvProxy: ssrf.trustEnvProxy,
178
+ onRedirect: ({ from, to, init }) => to.origin === from.origin ? init : { ...init, headers: { "Content-Type": "application/json" } },
179
+ ...(options.lookup ? { lookup: options.lookup } : {}),
180
+ });
181
+ }
182
+ catch (err) {
183
+ const message = errorMessage(err);
184
+ const redactedMessage = redactCredential(message, apiKey);
185
+ if (redactedMessage.toLowerCase().includes("abort"))
186
+ activityMonitor.logComplete(activityId, 0);
187
+ else
188
+ activityMonitor.logError(activityId, redactedMessage);
189
+ if (redactedMessage === message)
190
+ throw err;
191
+ const redactedError = new Error(redactedMessage);
192
+ if (err instanceof Error)
193
+ redactedError.name = err.name;
194
+ throw redactedError;
195
+ }
196
+ if (!response.ok) {
197
+ activityMonitor.logComplete(activityId, response.status);
198
+ const errorText = redactCredential(await response.text(), apiKey);
199
+ throw new Error(`Ollama Web Fetch error ${response.status}: ${errorText.slice(0, 300)}`);
200
+ }
201
+ let rawData;
202
+ try {
203
+ rawData = await response.json();
204
+ }
205
+ catch (err) {
206
+ activityMonitor.logComplete(activityId, response.status);
207
+ throw new Error(`Ollama Web Fetch returned invalid JSON: ${errorMessage(err)}`);
208
+ }
209
+ const data = parseFetchResponse(rawData);
210
+ activityMonitor.logComplete(activityId, response.status);
211
+ const content = data.content.trim();
212
+ if (!content)
213
+ return null;
214
+ return { url, title: data.title, content, error: null };
215
+ }
216
+ //# sourceMappingURL=ollama.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/ollama.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { ExtractedContent, ExtractOptions } from \"./extract.ts\";\nimport type { SearchOptions, SearchResponse } from \"./perplexity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { fetchRemoteUrl, loadFetchContentDomainPolicy, loadSsrfConfig, validateRemoteUrl, type Lookup, type SsrfConfig } from \"./ssrf-protection.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst OLLAMA_SEARCH_URL = \"https://ollama.com/api/web_search\";\nconst OLLAMA_FETCH_URL = \"https://ollama.com/api/web_fetch\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\n\ninterface WebSearchConfig {\n\tollamaApiKey?: unknown;\n}\n\ninterface OllamaSearchResult {\n\ttitle: string;\n\turl: string;\n\tcontent: string;\n}\n\ninterface OllamaSearchResponse {\n\tresults: OllamaSearchResult[];\n}\n\ninterface OllamaFetchResponse {\n\ttitle: string;\n\tcontent: string;\n\tlinks?: unknown;\n}\n\ninterface OllamaSearchOptions extends SearchOptions {\n\tincludeContent?: boolean;\n}\n\nexport interface OllamaExtractOptions extends Pick<ExtractOptions, \"timeoutMs\" | \"lookup\"> {\n\tssrf?: SsrfConfig;\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`Invalid config in ${CONFIG_PATH}: expected a JSON object`);\n\t}\n\tcachedConfig = parsed as WebSearchConfig;\n\treturn cachedConfig;\n}\n\nasync function getApiKey(signal?: AbortSignal): Promise<string | null> {\n\treturn resolveCredential({\n\t\tprovider: \"Ollama\",\n\t\tconfiguredValue: loadConfig().ollamaApiKey,\n\t\tenvironmentValue: process.env.OLLAMA_API_KEY,\n\t\tsignal,\n\t});\n}\n\nasync function requireApiKey(signal?: AbortSignal): Promise<string> {\n\tconst apiKey = await getApiKey(signal);\n\tif (!apiKey) {\n\t\tthrow new Error(\n\t\t\t\"Ollama API key not found. Either:\\n\" +\n\t\t\t` 1. Create ${CONFIG_PATH} with { \"ollamaApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 2. Set OLLAMA_API_KEY environment variable\\n\" +\n\t\t\t\"Create a key at https://ollama.com/settings/keys\",\n\t\t);\n\t}\n\treturn apiKey;\n}\n\nfunction normalizeCount(value: number | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 5;\n\treturn Math.max(1, Math.min(Math.floor(value), 10));\n}\n\nfunction errorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n\nfunction invalidResponse(message: string): Error {\n\treturn new Error(`Ollama API returned invalid response: ${message}`);\n}\n\nfunction parseSearchResponse(value: unknown): OllamaSearchResponse {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(\"expected an object envelope\");\n\tconst envelope = value as Record<string, unknown>;\n\tif (!Array.isArray(envelope.results)) throw invalidResponse(\"expected results array\");\n\tconst results: OllamaSearchResult[] = [];\n\tfor (const [index, value] of envelope.results.entries()) {\n\t\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(`expected results[${index}] object`);\n\t\tconst item = value as Record<string, unknown>;\n\t\tif (typeof item.title !== \"string\") throw invalidResponse(`expected results[${index}].title string`);\n\t\tif (typeof item.url !== \"string\" || !item.url) throw invalidResponse(`expected results[${index}].url non-empty string`);\n\t\tif (typeof item.content !== \"string\") throw invalidResponse(`expected results[${index}].content string`);\n\t\tresults.push({ title: item.title, url: item.url, content: item.content });\n\t}\n\treturn { results };\n}\n\nfunction parseFetchResponse(value: unknown): OllamaFetchResponse {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw invalidResponse(\"expected fetch object envelope\");\n\tconst envelope = value as Record<string, unknown>;\n\tif (typeof envelope.title !== \"string\") throw invalidResponse(\"expected title string\");\n\tif (typeof envelope.content !== \"string\") throw invalidResponse(\"expected content string\");\n\treturn { title: envelope.title, content: envelope.content, links: envelope.links };\n}\n\nfunction buildAnswer(results: SearchResponse[\"results\"]): string {\n\treturn results.map((result) => result.snippet\n\t\t? `${result.snippet}\\nSource: ${result.title} (${result.url})`\n\t\t: `Source: ${result.title} (${result.url})`).join(\"\\n\\n\");\n}\n\nexport function isOllamaAvailable(): boolean {\n\treturn hasCredentialSource({ provider: \"Ollama\", configuredValue: loadConfig().ollamaApiKey, environmentValue: process.env.OLLAMA_API_KEY });\n}\n\nexport async function searchWithOllama(query: string, options: OllamaSearchOptions = {}): Promise<SearchResponse> {\n\tconst apiKey = await requireApiKey(options.signal);\n\tconst numResults = normalizeCount(options.numResults);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(OLLAMA_SEARCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ query, max_results: numResults }),\n\t\t\tsignal: options.signal ? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal]) : AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Ollama API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Ollama API returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\n\tconst data = parseSearchResponse(rawData);\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst results = data.results.slice(0, numResults).map((result) => ({ title: result.title, url: result.url, snippet: result.content }));\n\tconst mapped: SearchResponse = { answer: buildAnswer(results), results };\n\tif (options.includeContent) {\n\t\tconst inlineContent: ExtractedContent[] = data.results.slice(0, numResults)\n\t\t\t.filter(result => result.content.trim().length > 0)\n\t\t\t.map(result => ({ url: result.url, title: result.title, content: result.content, error: null }));\n\t\tif (inlineContent.length > 0) mapped.inlineContent = inlineContent;\n\t}\n\treturn mapped;\n}\n\nexport function isOllamaFetchAvailable(): boolean {\n\treturn isOllamaAvailable();\n}\n\nexport async function extractWithOllama(url: string, signal?: AbortSignal, options: OllamaExtractOptions = {}): Promise<ExtractedContent | null> {\n\tconst ssrf = options.ssrf ?? loadSsrfConfig();\n\tconst domainPolicy = loadFetchContentDomainPolicy();\n\tawait validateRemoteUrl(url, {\n\t\tallowRanges: ssrf.allowRanges,\n\t\ttrustEnvProxy: ssrf.trustEnvProxy,\n\t\tdomainPolicy,\n\t\t...(options.lookup ? { lookup: options.lookup } : {}),\n\t});\n\tconst apiKey = await requireApiKey(signal);\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query: `ollama fetch: ${url}` });\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetchRemoteUrl(OLLAMA_FETCH_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ url }),\n\t\t\tsignal: signal ? AbortSignal.any([AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS), signal]) : AbortSignal.timeout(options.timeoutMs ?? SEARCH_TIMEOUT_MS),\n\t\t}, {\n\t\t\tallowRanges: ssrf.allowRanges,\n\t\t\ttrustEnvProxy: ssrf.trustEnvProxy,\n\t\t\tonRedirect: ({ from, to, init }) => to.origin === from.origin ? init : { ...init, headers: { \"Content-Type\": \"application/json\" } },\n\t\t\t...(options.lookup ? { lookup: options.lookup } : {}),\n\t\t});\n\t} catch (err) {\n\t\tconst message = errorMessage(err);\n\t\tconst redactedMessage = redactCredential(message, apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) activityMonitor.logComplete(activityId, 0);\n\t\telse activityMonitor.logError(activityId, redactedMessage);\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n\n\tif (!response.ok) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tconst errorText = redactCredential(await response.text(), apiKey);\n\t\tthrow new Error(`Ollama Web Fetch error ${response.status}: ${errorText.slice(0, 300)}`);\n\t}\n\tlet rawData: unknown;\n\ttry {\n\t\trawData = await response.json();\n\t} catch (err) {\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\tthrow new Error(`Ollama Web Fetch returned invalid JSON: ${errorMessage(err)}`);\n\t}\n\tconst data = parseFetchResponse(rawData);\n\tactivityMonitor.logComplete(activityId, response.status);\n\tconst content = data.content.trim();\n\tif (!content) return null;\n\treturn { url, title: data.title, content, error: null };\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import type { ExtensionContext } from "../host.ts";
2
+ import type { SearchOptions, SearchResponse } from "./perplexity.ts";
3
+ type ProviderHeaders = Record<string, string | null>;
4
+ interface OpenAIAuth {
5
+ provider: "openai-codex" | "openai";
6
+ apiKey: string;
7
+ model: string;
8
+ headers: ProviderHeaders;
9
+ responsesUrl: string;
10
+ }
11
+ export declare function resolveOpenAIAuth(ctx?: ExtensionContext, signal?: AbortSignal): Promise<OpenAIAuth | undefined>;
12
+ export declare function isOpenAISearchAvailable(ctx?: ExtensionContext): Promise<boolean>;
13
+ export declare function searchWithOpenAI(query: string, options?: SearchOptions, ctx?: ExtensionContext): Promise<SearchResponse>;
14
+ export {};
15
+ //# sourceMappingURL=openai-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-search.d.ts","sourceRoot":"","sources":["../../../../src/humain/web-access/vendor/openai-search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAgB,MAAM,iBAAiB,CAAC;AAqCnF,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;AAErD,UAAU,UAAU;IACnB,QAAQ,EAAE,cAAc,GAAG,QAAQ,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,eAAe,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACrB;AAkJD,wBAAsB,iBAAiB,CAAC,GAAG,CAAC,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAwBrH;AAED,wBAAsB,uBAAuB,CAAC,GAAG,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAStF;AA6KD,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,EAC3B,GAAG,CAAC,EAAE,gBAAgB,GACpB,OAAO,CAAC,cAAc,CAAC,CA6EzB","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport type { ExtensionContext } from \"../host.ts\";\nimport { activityMonitor } from \"./activity.ts\";\nimport type { SearchOptions, SearchResponse, SearchResult } from \"./perplexity.ts\";\nimport { hasCredentialSource, redactCredential, resolveCredential } from \"./credential-source.ts\";\nimport { getWebSearchConfigPath } from \"./utils.ts\";\n\nconst OPENAI_RESPONSES_URL = \"https://api.openai.com/v1/responses\";\nconst CODEX_RESPONSES_URL = \"https://chatgpt.com/backend-api/codex/responses\";\nconst CONFIG_PATH = getWebSearchConfigPath();\nconst SEARCH_TIMEOUT_MS = 60_000;\n\n// The selected model runs the server-side web_search call and writes the cited summary.\n// Prefer the newest mid-tier (\"terra\") model, then the newest bare mainline id; price\n// tiers (\"pro\"/\"ultra\" id segments) are excluded, and the numeric-aware sort keeps\n// e.g. gpt-5.10 ahead of gpt-5.9.\nconst EXCLUDED_MODEL_SEGMENTS = new Set([\"pro\", \"ultra\"]);\nconst MODEL_PREFERENCE = [\n\t(id: string) => id.includes(\"terra\"),\n\t(id: string) => /^gpt-\\d+(\\.\\d+)?$/.test(id),\n];\nconst SEARCH_PROVIDERS = [\"openai-codex\", \"openai\"] as const;\n\nfunction pickSearchModel<T extends { id: string }>(models: readonly T[]): T | undefined {\n\tconst candidates = models\n\t\t.filter((model) => !model.id.split(\"-\").some((segment) => EXCLUDED_MODEL_SEGMENTS.has(segment)))\n\t\t.sort((a, b) => b.id.localeCompare(a.id, undefined, { numeric: true }));\n\tfor (const prefers of MODEL_PREFERENCE) {\n\t\tconst preferred = candidates.find((model) => prefers(model.id));\n\t\tif (preferred) return preferred;\n\t}\n\treturn candidates[0];\n}\n\ninterface WebSearchConfig {\n\topenaiApiKey?: unknown;\n\topenaiResponsesUrl?: unknown;\n\topenaiSearchModel?: unknown;\n}\n\ntype ProviderHeaders = Record<string, string | null>;\n\ninterface OpenAIAuth {\n\tprovider: \"openai-codex\" | \"openai\";\n\tapiKey: string;\n\tmodel: string;\n\theaders: ProviderHeaders;\n\tresponsesUrl: string;\n}\n\ninterface NormalizedDomainFilters {\n\tallowedDomains?: string[];\n\tblockedDomains?: string[];\n}\n\nlet cachedConfig: WebSearchConfig | null = null;\n\nfunction loadConfig(): WebSearchConfig {\n\tif (cachedConfig) return cachedConfig;\n\tif (!existsSync(CONFIG_PATH)) {\n\t\tcachedConfig = {};\n\t\treturn cachedConfig;\n\t}\n\n\tconst raw = readFileSync(CONFIG_PATH, \"utf-8\");\n\ttry {\n\t\tcachedConfig = JSON.parse(raw) as WebSearchConfig;\n\t\treturn cachedConfig;\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tthrow new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);\n\t}\n}\n\nfunction 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 normalizeDomainFilters(domainFilter: string[] | undefined): NormalizedDomainFilters | null {\n\tif (!domainFilter?.length) return null;\n\n\tconst allowedDomains: string[] = [];\n\tconst blockedDomains: 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(\"-\") ? blockedDomains : allowedDomains;\n\t\tif (!target.includes(domain)) target.push(domain);\n\t}\n\n\treturn allowedDomains.length > 0 || blockedDomains.length > 0\n\t\t? {\n\t\t\t...(allowedDomains.length > 0 ? { allowedDomains: allowedDomains.slice(0, 100) } : {}),\n\t\t\t...(blockedDomains.length > 0 ? { blockedDomains: blockedDomains.slice(0, 100) } : {}),\n\t\t}\n\t\t: null;\n}\n\nfunction decodeJwtPayload(token: string): Record<string, unknown> | null {\n\tconst parts = token.split(\".\");\n\tif (parts.length !== 3 || !parts[1]) return null;\n\ttry {\n\t\tconst padded = parts[1].replace(/-/g, \"+\").replace(/_/g, \"/\").padEnd(Math.ceil(parts[1].length / 4) * 4, \"=\");\n\t\tconst parsed = JSON.parse(Buffer.from(padded, \"base64\").toString(\"utf8\"));\n\t\treturn parsed && typeof parsed === \"object\" ? parsed as Record<string, unknown> : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction isCodexJwt(token: string): boolean {\n\tconst payload = decodeJwtPayload(token);\n\treturn !!payload?.[\"https://api.openai.com/auth\"];\n}\n\nfunction extractAccountId(token: string): string | undefined {\n\tconst payload = decodeJwtPayload(token);\n\tconst auth = payload?.[\"https://api.openai.com/auth\"];\n\tif (!auth || typeof auth !== \"object\") return undefined;\n\tconst id = (auth as Record<string, unknown>).chatgpt_account_id;\n\treturn typeof id === \"string\" && id.trim().length > 0 ? id.trim() : undefined;\n}\n\nfunction resolveConfiguredResponsesUrl(value: unknown): string {\n\tif (value === undefined) return OPENAI_RESPONSES_URL;\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\tthrow new Error(`openaiResponsesUrl in ${CONFIG_PATH} must be an absolute http(s) URL`);\n\t}\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(value.trim());\n\t} catch {\n\t\tthrow new Error(`openaiResponsesUrl in ${CONFIG_PATH} must be an absolute http(s) URL`);\n\t}\n\tif (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n\t\tthrow new Error(`openaiResponsesUrl in ${CONFIG_PATH} must use http or https`);\n\t}\n\treturn url.toString();\n}\n\nfunction resolveConfiguredSearchModel(value: unknown): string | undefined {\n\tif (value == null) return undefined;\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\tthrow new Error(`openaiSearchModel in ${CONFIG_PATH} must be a non-empty string`);\n\t}\n\treturn value.trim();\n}\n\nfunction toRequestHeaders(headers: ProviderHeaders): Record<string, string> {\n\tconst requestHeaders: Record<string, string> = {};\n\tfor (const [name, value] of Object.entries(headers)) {\n\t\tif (value !== null) requestHeaders[name] = value;\n\t}\n\treturn requestHeaders;\n}\n\nasync function resolvePiAuth(ctx: ExtensionContext, responsesUrl: string, modelOverride?: string): Promise<OpenAIAuth | undefined> {\n\tlet models: ReturnType<typeof ctx.modelRegistry.getAll>;\n\ttry {\n\t\tmodels = ctx.modelRegistry.getAll();\n\t} catch {\n\t\treturn undefined;\n\t}\n\tfor (const provider of SEARCH_PROVIDERS) {\n\t\tconst preferred = pickSearchModel(models.filter((model) => model.provider === provider));\n\t\tif (!preferred) continue;\n\t\ttry {\n\t\t\tconst resolved = await ctx.modelRegistry.getApiKeyAndHeaders(preferred);\n\t\t\tif (resolved.ok && resolved.apiKey) {\n\t\t\t\treturn {\n\t\t\t\t\tprovider,\n\t\t\t\t\tapiKey: resolved.apiKey,\n\t\t\t\t\tmodel: modelOverride ?? preferred.id,\n\t\t\t\t\theaders: resolved.headers ?? {},\n\t\t\t\t\tresponsesUrl,\n\t\t\t\t};\n\t\t\t}\n\t\t} catch {\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport async function resolveOpenAIAuth(ctx?: ExtensionContext, signal?: AbortSignal): Promise<OpenAIAuth | undefined> {\n\tconst config = loadConfig();\n\tconst responsesUrl = resolveConfiguredResponsesUrl(config.openaiResponsesUrl);\n\tconst modelOverride = resolveConfiguredSearchModel(config.openaiSearchModel);\n\tif (ctx) {\n\t\tconst auth = await resolvePiAuth(ctx, responsesUrl, modelOverride);\n\t\tif (auth) return auth;\n\t}\n\n\tconst hasSource = hasCredentialSource({\n\t\tprovider: \"OpenAI\",\n\t\tconfiguredValue: config.openaiApiKey,\n\t\tenvironmentValue: process.env.OPENAI_API_KEY,\n\t});\n\tif (!hasSource) return undefined;\n\tconst apiKey = await resolveCredential({\n\t\tprovider: \"OpenAI\",\n\t\tconfiguredValue: config.openaiApiKey,\n\t\tenvironmentValue: process.env.OPENAI_API_KEY,\n\t\tsignal,\n\t});\n\treturn apiKey\n\t\t? { provider: \"openai\", apiKey, model: modelOverride ?? \"gpt-5.6-terra\", headers: {}, responsesUrl }\n\t\t: undefined;\n}\n\nexport async function isOpenAISearchAvailable(ctx?: ExtensionContext): Promise<boolean> {\n\tconst config = loadConfig();\n\tconst responsesUrl = resolveConfiguredResponsesUrl(config.openaiResponsesUrl);\n\tif (ctx && await resolvePiAuth(ctx, responsesUrl)) return true;\n\treturn hasCredentialSource({\n\t\tprovider: \"OpenAI\",\n\t\tconfiguredValue: config.openaiApiKey,\n\t\tenvironmentValue: process.env.OPENAI_API_KEY,\n\t});\n}\n\nfunction buildInstructions(options: SearchOptions): string {\n\tconst lines = [\n\t\t\"Search the web and return a concise answer grounded only in the web results.\",\n\t\t\"Include clickable source citations in the response text when possible.\",\n\t];\n\n\tif (options.recencyFilter) {\n\t\tconst labels: Record<string, string> = {\n\t\t\tday: \"past 24 hours\",\n\t\t\tweek: \"past week\",\n\t\t\tmonth: \"past month\",\n\t\t\tyear: \"past year\",\n\t\t};\n\t\tlines.push(`Prefer sources from the ${labels[options.recencyFilter]}.`);\n\t}\n\n\tif (typeof options.numResults === \"number\" && Number.isFinite(options.numResults) && options.numResults > 0) {\n\t\tlines.push(`Prefer around ${Math.min(Math.floor(options.numResults), 20)} distinct sources.`);\n\t}\n\n\tconst filters = normalizeDomainFilters(options.domainFilter);\n\tif (filters?.allowedDomains?.length) lines.push(`Only use sources from: ${filters.allowedDomains.join(\", \")}.`);\n\tif (filters?.blockedDomains?.length) lines.push(`Do not use sources from: ${filters.blockedDomains.join(\", \")}.`);\n\n\treturn lines.join(\" \");\n}\n\nfunction buildWebSearchTool(options: SearchOptions): Record<string, unknown> {\n\tconst tool: Record<string, unknown> = { type: \"web_search\" };\n\tconst filters = normalizeDomainFilters(options.domainFilter);\n\tif (filters) {\n\t\ttool.filters = {\n\t\t\t...(filters.allowedDomains ? { allowed_domains: filters.allowedDomains } : {}),\n\t\t\t...(filters.blockedDomains ? { blocked_domains: filters.blockedDomains } : {}),\n\t\t};\n\t}\n\treturn tool;\n}\n\nasync function parseOpenAIResponse(response: Response): Promise<Record<string, unknown>> {\n\tconst text = await response.text();\n\tconst trimmed = text.trim();\n\tif (trimmed.startsWith(\"{\") || trimmed.startsWith(\"[\")) {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(trimmed);\n\t\t\tif (Array.isArray(parsed)) return { output: parsed };\n\t\t\treturn parsed && typeof parsed === \"object\" ? parsed as Record<string, unknown> : { output: [] };\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\tthrow new Error(`OpenAI API returned invalid JSON: ${message}`);\n\t\t}\n\t}\n\n\tconst outputItems: unknown[] = [];\n\tlet completedResponse: Record<string, unknown> | null = null;\n\tfor (const line of text.split(\"\\n\")) {\n\t\tif (!line.startsWith(\"data: \")) continue;\n\t\tconst data = line.slice(6).trim();\n\t\tif (!data || data === \"[DONE]\") continue;\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(data) as Record<string, unknown>;\n\t\t\tif (parsed.type === \"response.output_item.done\" && parsed.item) outputItems.push(parsed.item);\n\t\t\tif ((parsed.type === \"response.done\" || parsed.type === \"response.completed\") && parsed.response && typeof parsed.response === \"object\") {\n\t\t\t\tcompletedResponse = parsed.response as Record<string, unknown>;\n\t\t\t}\n\t\t} catch {\n\t\t}\n\t}\n\n\tif (completedResponse) {\n\t\tconst output = Array.isArray(completedResponse.output) ? completedResponse.output : [];\n\t\treturn output.length > 0 ? completedResponse : { ...completedResponse, output: outputItems };\n\t}\n\tif (outputItems.length > 0) return { output: outputItems };\n\tthrow new Error(\"OpenAI API returned no parseable response output\");\n}\n\nfunction cleanSourceUrl(rawUrl: string): string {\n\ttry {\n\t\tconst url = new URL(rawUrl);\n\t\tif (url.searchParams.get(\"utm_source\") === \"openai\") url.searchParams.delete(\"utm_source\");\n\t\treturn url.toString();\n\t} catch {\n\t\treturn rawUrl.replace(/[?&]utm_source=openai$/, \"\");\n\t}\n}\n\nfunction extractSnippetAround(text: string, start: unknown, end: unknown): string {\n\tif (typeof start !== \"number\" || typeof end !== \"number\" || !text) return \"\";\n\tconst before = Math.max(0, start - 100);\n\tconst after = Math.min(text.length, end + 100);\n\tconst snippet = text.slice(before, after).replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, \"$1\").trim();\n\treturn snippet.length > 300 ? `${snippet.slice(0, 297)}...` : snippet;\n}\n\nfunction addResult(results: SearchResult[], seen: Set<string>, url: unknown, title: unknown, snippet = \"\"): void {\n\tif (typeof url !== \"string\" || url.trim().length === 0) return;\n\tconst cleanUrl = cleanSourceUrl(url);\n\tif (seen.has(cleanUrl)) return;\n\tseen.add(cleanUrl);\n\tresults.push({\n\t\ttitle: typeof title === \"string\" && title.trim().length > 0 ? title : cleanUrl,\n\t\turl: cleanUrl,\n\t\tsnippet,\n\t});\n}\n\nfunction extractSearchResults(output: unknown[], numResults: number | undefined): SearchResult[] {\n\tconst results: SearchResult[] = [];\n\tconst seenUrls = new Set<string>();\n\n\tfor (const item of output) {\n\t\tif (!item || typeof item !== \"object\" || (item as { type?: unknown }).type !== \"message\") continue;\n\t\tconst content = (item as { content?: unknown }).content;\n\t\tif (!Array.isArray(content)) continue;\n\t\tfor (const part of content) {\n\t\t\tif (!part || typeof part !== \"object\") continue;\n\t\t\tconst text = typeof (part as { text?: unknown }).text === \"string\" ? (part as { text: string }).text : \"\";\n\t\t\tconst annotations = (part as { annotations?: unknown }).annotations;\n\t\t\tif (!Array.isArray(annotations)) continue;\n\t\t\tfor (const annotation of annotations) {\n\t\t\t\tif (!annotation || typeof annotation !== \"object\" || (annotation as { type?: unknown }).type !== \"url_citation\") continue;\n\t\t\t\taddResult(\n\t\t\t\t\tresults,\n\t\t\t\t\tseenUrls,\n\t\t\t\t\t(annotation as { url?: unknown }).url,\n\t\t\t\t\t(annotation as { title?: unknown }).title,\n\t\t\t\t\textractSnippetAround(text, (annotation as { start_index?: unknown }).start_index, (annotation as { end_index?: unknown }).end_index),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const item of output) {\n\t\tif (!item || typeof item !== \"object\" || (item as { type?: unknown }).type !== \"web_search_call\") continue;\n\t\tconst value = item as { action?: unknown; sources?: unknown; results?: unknown };\n\t\tconst actionSources = value.action && typeof value.action === \"object\"\n\t\t\t? (value.action as { sources?: unknown }).sources\n\t\t\t: undefined;\n\t\tconst sourceGroups = [actionSources, value.sources, value.results];\n\t\tfor (const group of sourceGroups) {\n\t\t\tif (!Array.isArray(group)) continue;\n\t\t\tfor (const source of group) {\n\t\t\t\tif (!source || typeof source !== \"object\") continue;\n\t\t\t\tconst record = source as Record<string, unknown>;\n\t\t\t\taddResult(results, seenUrls, record.url ?? record.source_website_url, record.title ?? record.caption);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (typeof numResults === \"number\" && Number.isFinite(numResults) && numResults > 0) {\n\t\treturn results.slice(0, Math.min(Math.floor(numResults), 20));\n\t}\n\treturn results;\n}\n\nfunction extractAnswer(output: unknown[]): string {\n\tconst parts: string[] = [];\n\tfor (const item of output) {\n\t\tif (!item || typeof item !== \"object\" || (item as { type?: unknown }).type !== \"message\") continue;\n\t\tconst content = (item as { content?: unknown }).content;\n\t\tif (!Array.isArray(content)) continue;\n\t\tfor (const part of content) {\n\t\t\tif (!part || typeof part !== \"object\") continue;\n\t\t\tconst text = (part as { text?: unknown }).text;\n\t\t\tif (typeof text === \"string\" && text.trim().length > 0) parts.push(text);\n\t\t}\n\t}\n\treturn parts.join(\"\\n\").trim();\n}\n\nexport async function searchWithOpenAI(\n\tquery: string,\n\toptions: SearchOptions = {},\n\tctx?: ExtensionContext,\n): Promise<SearchResponse> {\n\tconst auth = await resolveOpenAIAuth(ctx, options.signal);\n\tif (!auth) {\n\t\tthrow new Error(\n\t\t\t\"OpenAI web search unavailable. Either:\\n\" +\n\t\t\t\" 1. Use /login to sign in with a Codex subscription\\n\" +\n\t\t\t` 2. Create ${CONFIG_PATH} with { \"openaiApiKey\": \"your-key\" }\\n` +\n\t\t\t\" 3. Set OPENAI_API_KEY environment variable\",\n\t\t);\n\t}\n\n\tconst activityId = activityMonitor.logStart({ type: \"api\", query });\n\tconst headers: Record<string, string> = {\n\t\t...toRequestHeaders(auth.headers),\n\t\tAuthorization: `Bearer ${auth.apiKey}`,\n\t\t\"Content-Type\": \"application/json\",\n\t\t\"OpenAI-Beta\": \"responses=experimental\",\n\t};\n\tconst useCodexEndpoint = auth.provider === \"openai-codex\" || isCodexJwt(auth.apiKey);\n\tif (useCodexEndpoint) {\n\t\tconst accountId = extractAccountId(auth.apiKey);\n\t\tif (accountId) headers[\"chatgpt-account-id\"] = accountId;\n\t\theaders.originator = \"pi\";\n\t}\n\n\tconst body = {\n\t\tmodel: auth.model,\n\t\tinstructions: buildInstructions(options),\n\t\tinput: [{ role: \"user\", content: [{ type: \"input_text\", text: query }] }],\n\t\ttools: [buildWebSearchTool(options)],\n\t\tinclude: [\"web_search_call.action.sources\"],\n\t\tstore: false,\n\t\tstream: true,\n\t\ttool_choice: \"required\" as const,\n\t\tparallel_tool_calls: true,\n\t};\n\n\ttry {\n\t\tconst response = await fetch(useCodexEndpoint ? CODEX_RESPONSES_URL : auth.responsesUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders,\n\t\t\tbody: JSON.stringify(body),\n\t\t\tsignal: options.signal\n\t\t\t\t? AbortSignal.any([AbortSignal.timeout(SEARCH_TIMEOUT_MS), options.signal])\n\t\t\t\t: AbortSignal.timeout(SEARCH_TIMEOUT_MS),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tactivityMonitor.logError(activityId, `HTTP ${response.status}`);\n\t\t\tconst errorText = redactCredential(await response.text(), auth.apiKey);\n\t\t\tthrow new Error(`OpenAI API error ${response.status}: ${errorText.slice(0, 300)}`);\n\t\t}\n\n\t\tconst parsed = await parseOpenAIResponse(response);\n\t\tconst output = Array.isArray(parsed.output) ? parsed.output : [];\n\t\tconst answer = extractAnswer(output);\n\t\tconst results = extractSearchResults(output, options.numResults);\n\n\t\tif (!answer && results.length === 0) {\n\t\t\tthrow new Error(\"OpenAI web_search returned no answer or sources\");\n\t\t}\n\n\t\tactivityMonitor.logComplete(activityId, response.status);\n\t\treturn { answer, results };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tconst redactedMessage = redactCredential(message, auth.apiKey);\n\t\tif (redactedMessage.toLowerCase().includes(\"abort\")) {\n\t\t\tactivityMonitor.logComplete(activityId, 0);\n\t\t} else {\n\t\t\tactivityMonitor.logError(activityId, redactedMessage);\n\t\t}\n\t\tif (redactedMessage === message) throw err;\n\t\tconst redactedError = new Error(redactedMessage);\n\t\tif (err instanceof Error) redactedError.name = err.name;\n\t\tthrow redactedError;\n\t}\n}\n"]}