@theowlops/boombot 0.0.0-stage → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (544) hide show
  1. package/README.md +69 -3
  2. package/dist/LICENSE +21 -0
  3. package/dist/bin/boombot.js +16 -0
  4. package/dist/cli/api-key.js +123 -0
  5. package/dist/cli/bin-bun.js +17 -0
  6. package/dist/cli/bin.js +34 -0
  7. package/dist/cli/cli/cli-error.js +61 -0
  8. package/dist/cli/cli/dispatch.js +138 -0
  9. package/dist/cli/cli/help.js +83 -0
  10. package/dist/cli/cli/parser.js +89 -0
  11. package/dist/cli/cli/registry.js +185 -0
  12. package/dist/cli/cli/spec.js +41 -0
  13. package/dist/cli/cli/suggest.js +125 -0
  14. package/dist/cli/cli/version.js +30 -0
  15. package/dist/cli/cli/vocabulary.js +87 -0
  16. package/dist/cli/commands/doctor.js +365 -0
  17. package/dist/cli/commands/gateway.js +290 -0
  18. package/dist/cli/commands/migrate.js +270 -0
  19. package/dist/cli/commands/plugin.js +97 -0
  20. package/dist/cli/commands/setup.js +244 -0
  21. package/dist/cli/config-file.js +133 -0
  22. package/dist/cli/master-key.js +78 -0
  23. package/dist/cli/open-browser.js +59 -0
  24. package/dist/cli/web-assets.js +58 -0
  25. package/dist/gateway/auth.js +46 -0
  26. package/dist/gateway/config-format.js +202 -0
  27. package/dist/gateway/config.js +427 -0
  28. package/dist/gateway/context.js +1 -0
  29. package/dist/gateway/env-file.js +129 -0
  30. package/dist/gateway/events.js +172 -0
  31. package/dist/gateway/guard/tagging.js +505 -0
  32. package/dist/gateway/handlers/index.js +66 -0
  33. package/dist/gateway/handlers/memory.js +54 -0
  34. package/dist/gateway/handlers/providers.js +73 -0
  35. package/dist/gateway/handlers/registry.js +39 -0
  36. package/dist/gateway/handlers/sessions.js +188 -0
  37. package/dist/gateway/handlers/system.js +12 -0
  38. package/dist/gateway/handlers/tasks.js +191 -0
  39. package/dist/gateway/handlers/turn.js +100 -0
  40. package/dist/gateway/index.js +126 -0
  41. package/dist/gateway/main.js +23 -0
  42. package/dist/gateway/server.js +354 -0
  43. package/dist/gateway/services/context-limits.js +75 -0
  44. package/dist/gateway/services/history-normalizer.js +42 -0
  45. package/dist/gateway/services/image-pipeline.js +56 -0
  46. package/dist/gateway/services/key-roulette-client.js +43 -0
  47. package/dist/gateway/services/llm-client.js +593 -0
  48. package/dist/gateway/services/llm-decoder.js +200 -0
  49. package/dist/gateway/services/local-fallback.js +135 -0
  50. package/dist/gateway/services/memory.js +511 -0
  51. package/dist/gateway/services/persistent-memory.js +196 -0
  52. package/dist/gateway/services/providers.js +44 -0
  53. package/dist/gateway/services/tasks.js +237 -0
  54. package/dist/gateway/services/verification.js +124 -0
  55. package/dist/gateway/services/vision-payload.js +48 -0
  56. package/dist/gateway/services.js +257 -0
  57. package/dist/gateway/session-snapshot.js +19 -0
  58. package/dist/gateway/sessions.js +701 -0
  59. package/dist/gateway/static.js +239 -0
  60. package/dist/gateway/turns/clarify-tool.js +57 -0
  61. package/dist/gateway/turns/cronjob-tool.js +96 -0
  62. package/dist/gateway/turns/deferred-tools.js +154 -0
  63. package/dist/gateway/turns/execute-code-tool.js +84 -0
  64. package/dist/gateway/turns/file-tool-defs.js +178 -0
  65. package/dist/gateway/turns/file-tool-ops.js +178 -0
  66. package/dist/gateway/turns/file-tool-scan.js +182 -0
  67. package/dist/gateway/turns/file-tool.js +302 -0
  68. package/dist/gateway/turns/index.js +416 -0
  69. package/dist/gateway/turns/jev-middleware.js +91 -0
  70. package/dist/gateway/turns/local-reply.js +156 -0
  71. package/dist/gateway/turns/mcp-client.js +643 -0
  72. package/dist/gateway/turns/memory-tool.js +171 -0
  73. package/dist/gateway/turns/middleware.js +96 -0
  74. package/dist/gateway/turns/python-core.js +397 -0
  75. package/dist/gateway/turns/routing/index.js +3 -0
  76. package/dist/gateway/turns/routing/intent-classifier.js +60 -0
  77. package/dist/gateway/turns/routing/planner-adapter.js +91 -0
  78. package/dist/gateway/turns/routing/types.js +1 -0
  79. package/dist/gateway/turns/runtime-deps.js +228 -0
  80. package/dist/gateway/turns/self-config-tool.js +277 -0
  81. package/dist/gateway/turns/service-types.js +11 -0
  82. package/dist/gateway/turns/service.js +820 -0
  83. package/dist/gateway/turns/session-adapter.js +158 -0
  84. package/dist/gateway/turns/session-tool.js +49 -0
  85. package/dist/gateway/turns/shell-tool.js +190 -0
  86. package/dist/gateway/turns/skill-tool.js +239 -0
  87. package/dist/gateway/turns/spillover.js +201 -0
  88. package/dist/gateway/turns/subagent-tool.js +140 -0
  89. package/dist/gateway/turns/system-prompt.js +121 -0
  90. package/dist/gateway/turns/tool-schema.js +90 -0
  91. package/dist/gateway/turns/turn-utils.js +58 -0
  92. package/dist/gateway/turns/vision-tool.js +120 -0
  93. package/dist/gateway/types.js +1 -0
  94. package/dist/native/win32-x64/boombot-native-host.exe +0 -0
  95. package/dist/node_modules/@boombot/channels/handlers.d.ts +9 -0
  96. package/dist/node_modules/@boombot/channels/handlers.js +109 -0
  97. package/dist/node_modules/@boombot/channels/index.d.ts +12 -0
  98. package/dist/node_modules/@boombot/channels/index.js +12 -0
  99. package/dist/node_modules/@boombot/channels/package.json +9 -0
  100. package/dist/node_modules/@boombot/channels/service.d.ts +62 -0
  101. package/dist/node_modules/@boombot/channels/service.js +608 -0
  102. package/dist/node_modules/@boombot/channels/tool.d.ts +10 -0
  103. package/dist/node_modules/@boombot/channels/tool.js +46 -0
  104. package/dist/node_modules/@boombot/channels/transports/common/dedup.d.ts +17 -0
  105. package/dist/node_modules/@boombot/channels/transports/common/dedup.js +42 -0
  106. package/dist/node_modules/@boombot/channels/transports/common/handoff.d.ts +19 -0
  107. package/dist/node_modules/@boombot/channels/transports/common/handoff.js +32 -0
  108. package/dist/node_modules/@boombot/channels/transports/common/index.d.ts +3 -0
  109. package/dist/node_modules/@boombot/channels/transports/common/index.js +3 -0
  110. package/dist/node_modules/@boombot/channels/transports/common/types.d.ts +99 -0
  111. package/dist/node_modules/@boombot/channels/transports/common/types.js +54 -0
  112. package/dist/node_modules/@boombot/channels/transports/common.d.ts +2 -0
  113. package/dist/node_modules/@boombot/channels/transports/common.js +2 -0
  114. package/dist/node_modules/@boombot/channels/transports/dedup/index.d.ts +1 -0
  115. package/dist/node_modules/@boombot/channels/transports/dedup/index.js +1 -0
  116. package/dist/node_modules/@boombot/channels/transports/dedup.d.ts +2 -0
  117. package/dist/node_modules/@boombot/channels/transports/dedup.js +2 -0
  118. package/dist/node_modules/@boombot/channels/transports/discord/index.d.ts +1 -0
  119. package/dist/node_modules/@boombot/channels/transports/discord/index.js +1 -0
  120. package/dist/node_modules/@boombot/channels/transports/discord/transport.d.ts +36 -0
  121. package/dist/node_modules/@boombot/channels/transports/discord/transport.js +199 -0
  122. package/dist/node_modules/@boombot/channels/transports/discord.d.ts +2 -0
  123. package/dist/node_modules/@boombot/channels/transports/discord.js +2 -0
  124. package/dist/node_modules/@boombot/channels/transports/handoff.d.ts +2 -0
  125. package/dist/node_modules/@boombot/channels/transports/handoff.js +2 -0
  126. package/dist/node_modules/@boombot/channels/transports/messenger/index.d.ts +1 -0
  127. package/dist/node_modules/@boombot/channels/transports/messenger/index.js +1 -0
  128. package/dist/node_modules/@boombot/channels/transports/messenger/transport.d.ts +34 -0
  129. package/dist/node_modules/@boombot/channels/transports/messenger/transport.js +180 -0
  130. package/dist/node_modules/@boombot/channels/transports/messenger.d.ts +2 -0
  131. package/dist/node_modules/@boombot/channels/transports/messenger.js +2 -0
  132. package/dist/node_modules/@boombot/channels/transports/slack/index.d.ts +1 -0
  133. package/dist/node_modules/@boombot/channels/transports/slack/index.js +1 -0
  134. package/dist/node_modules/@boombot/channels/transports/slack/transport.d.ts +35 -0
  135. package/dist/node_modules/@boombot/channels/transports/slack/transport.js +183 -0
  136. package/dist/node_modules/@boombot/channels/transports/slack.d.ts +2 -0
  137. package/dist/node_modules/@boombot/channels/transports/slack.js +2 -0
  138. package/dist/node_modules/@boombot/channels/transports/streamer/index.d.ts +1 -0
  139. package/dist/node_modules/@boombot/channels/transports/streamer/index.js +1 -0
  140. package/dist/node_modules/@boombot/channels/transports/streamer/streamer.d.ts +31 -0
  141. package/dist/node_modules/@boombot/channels/transports/streamer/streamer.js +141 -0
  142. package/dist/node_modules/@boombot/channels/transports/streamer.d.ts +2 -0
  143. package/dist/node_modules/@boombot/channels/transports/streamer.js +2 -0
  144. package/dist/node_modules/@boombot/channels/transports/telegram/index.d.ts +1 -0
  145. package/dist/node_modules/@boombot/channels/transports/telegram/index.js +1 -0
  146. package/dist/node_modules/@boombot/channels/transports/telegram/transport.d.ts +75 -0
  147. package/dist/node_modules/@boombot/channels/transports/telegram/transport.js +395 -0
  148. package/dist/node_modules/@boombot/channels/transports/telegram.d.ts +2 -0
  149. package/dist/node_modules/@boombot/channels/transports/telegram.js +2 -0
  150. package/dist/node_modules/@boombot/channels/transports/tiktok/index.d.ts +1 -0
  151. package/dist/node_modules/@boombot/channels/transports/tiktok/index.js +1 -0
  152. package/dist/node_modules/@boombot/channels/transports/tiktok/transport.d.ts +27 -0
  153. package/dist/node_modules/@boombot/channels/transports/tiktok/transport.js +97 -0
  154. package/dist/node_modules/@boombot/channels/transports/tiktok.d.ts +2 -0
  155. package/dist/node_modules/@boombot/channels/transports/tiktok.js +2 -0
  156. package/dist/node_modules/@boombot/channels/transports/whatsapp/index.d.ts +1 -0
  157. package/dist/node_modules/@boombot/channels/transports/whatsapp/index.js +1 -0
  158. package/dist/node_modules/@boombot/channels/transports/whatsapp/transport.d.ts +38 -0
  159. package/dist/node_modules/@boombot/channels/transports/whatsapp/transport.js +189 -0
  160. package/dist/node_modules/@boombot/channels/transports/whatsapp.d.ts +2 -0
  161. package/dist/node_modules/@boombot/channels/transports/whatsapp.js +2 -0
  162. package/dist/node_modules/@boombot/channels/transports/zalo/index.d.ts +2 -0
  163. package/dist/node_modules/@boombot/channels/transports/zalo/index.js +2 -0
  164. package/dist/node_modules/@boombot/channels/transports/zalo/oa.d.ts +28 -0
  165. package/dist/node_modules/@boombot/channels/transports/zalo/oa.js +94 -0
  166. package/dist/node_modules/@boombot/channels/transports/zalo/personal.d.ts +106 -0
  167. package/dist/node_modules/@boombot/channels/transports/zalo/personal.js +171 -0
  168. package/dist/node_modules/@boombot/channels/transports/zalo-personal.d.ts +2 -0
  169. package/dist/node_modules/@boombot/channels/transports/zalo-personal.js +2 -0
  170. package/dist/node_modules/@boombot/channels/transports/zalo.d.ts +2 -0
  171. package/dist/node_modules/@boombot/channels/transports/zalo.js +2 -0
  172. package/dist/node_modules/@boombot/core/agent-core/index.d.ts +12 -0
  173. package/dist/node_modules/@boombot/core/agent-core/index.js +12 -0
  174. package/dist/node_modules/@boombot/core/agent-core/middleware.d.ts +60 -0
  175. package/dist/node_modules/@boombot/core/agent-core/middleware.js +152 -0
  176. package/dist/node_modules/@boombot/core/agent-core/routing.d.ts +128 -0
  177. package/dist/node_modules/@boombot/core/agent-core/routing.js +437 -0
  178. package/dist/node_modules/@boombot/core/agent-core/runtime-deps.d.ts +88 -0
  179. package/dist/node_modules/@boombot/core/agent-core/runtime-deps.js +8 -0
  180. package/dist/node_modules/@boombot/core/agent-core/tool-errors.d.ts +44 -0
  181. package/dist/node_modules/@boombot/core/agent-core/tool-errors.js +60 -0
  182. package/dist/node_modules/@boombot/core/agent-core/turn-loop.d.ts +21 -0
  183. package/dist/node_modules/@boombot/core/agent-core/turn-loop.js +561 -0
  184. package/dist/node_modules/@boombot/core/agent-core/types.d.ts +189 -0
  185. package/dist/node_modules/@boombot/core/agent-core/types.js +7 -0
  186. package/dist/node_modules/@boombot/core/compaction/compactor.d.ts +19 -0
  187. package/dist/node_modules/@boombot/core/compaction/compactor.js +127 -0
  188. package/dist/node_modules/@boombot/core/compaction/estimator.d.ts +10 -0
  189. package/dist/node_modules/@boombot/core/compaction/estimator.js +48 -0
  190. package/dist/node_modules/@boombot/core/compaction/index.d.ts +3 -0
  191. package/dist/node_modules/@boombot/core/compaction/index.js +3 -0
  192. package/dist/node_modules/@boombot/core/compaction/types.d.ts +31 -0
  193. package/dist/node_modules/@boombot/core/compaction/types.js +7 -0
  194. package/dist/node_modules/@boombot/core/index.d.ts +9 -0
  195. package/dist/node_modules/@boombot/core/index.js +9 -0
  196. package/dist/node_modules/@boombot/core/jev/index.d.ts +2 -0
  197. package/dist/node_modules/@boombot/core/jev/index.js +2 -0
  198. package/dist/node_modules/@boombot/core/jev/jev.d.ts +30 -0
  199. package/dist/node_modules/@boombot/core/jev/jev.js +164 -0
  200. package/dist/node_modules/@boombot/core/jev/types.d.ts +22 -0
  201. package/dist/node_modules/@boombot/core/jev/types.js +1 -0
  202. package/dist/node_modules/@boombot/core/memory/consolidation/budget.d.ts +63 -0
  203. package/dist/node_modules/@boombot/core/memory/consolidation/budget.js +94 -0
  204. package/dist/node_modules/@boombot/core/memory/consolidation/consolidator.d.ts +152 -0
  205. package/dist/node_modules/@boombot/core/memory/consolidation/consolidator.js +318 -0
  206. package/dist/node_modules/@boombot/core/memory/consolidation/index.d.ts +12 -0
  207. package/dist/node_modules/@boombot/core/memory/consolidation/index.js +12 -0
  208. package/dist/node_modules/@boombot/core/memory/curation.d.ts +86 -0
  209. package/dist/node_modules/@boombot/core/memory/curation.js +120 -0
  210. package/dist/node_modules/@boombot/core/memory/errors.d.ts +12 -0
  211. package/dist/node_modules/@boombot/core/memory/errors.js +20 -0
  212. package/dist/node_modules/@boombot/core/memory/hybrid-search.d.ts +29 -0
  213. package/dist/node_modules/@boombot/core/memory/hybrid-search.js +52 -0
  214. package/dist/node_modules/@boombot/core/memory/index.d.ts +23 -0
  215. package/dist/node_modules/@boombot/core/memory/index.js +23 -0
  216. package/dist/node_modules/@boombot/core/memory/indexer.d.ts +47 -0
  217. package/dist/node_modules/@boombot/core/memory/indexer.js +138 -0
  218. package/dist/node_modules/@boombot/core/memory/lifecycle.d.ts +12 -0
  219. package/dist/node_modules/@boombot/core/memory/lifecycle.js +66 -0
  220. package/dist/node_modules/@boombot/core/memory/provider.d.ts +84 -0
  221. package/dist/node_modules/@boombot/core/memory/provider.js +117 -0
  222. package/dist/node_modules/@boombot/core/memory/recall.d.ts +7 -0
  223. package/dist/node_modules/@boombot/core/memory/recall.js +111 -0
  224. package/dist/node_modules/@boombot/core/memory/scope-resolver.d.ts +27 -0
  225. package/dist/node_modules/@boombot/core/memory/scope-resolver.js +60 -0
  226. package/dist/node_modules/@boombot/core/memory/search.d.ts +37 -0
  227. package/dist/node_modules/@boombot/core/memory/search.js +158 -0
  228. package/dist/node_modules/@boombot/core/memory/store.d.ts +60 -0
  229. package/dist/node_modules/@boombot/core/memory/store.js +289 -0
  230. package/dist/node_modules/@boombot/core/memory/types.d.ts +121 -0
  231. package/dist/node_modules/@boombot/core/memory/types.js +21 -0
  232. package/dist/node_modules/@boombot/core/memory/vector-index.d.ts +34 -0
  233. package/dist/node_modules/@boombot/core/memory/vector-index.js +65 -0
  234. package/dist/node_modules/@boombot/core/package.json +9 -0
  235. package/dist/node_modules/@boombot/core/reflection/classifier.d.ts +13 -0
  236. package/dist/node_modules/@boombot/core/reflection/classifier.js +77 -0
  237. package/dist/node_modules/@boombot/core/reflection/index.d.ts +2 -0
  238. package/dist/node_modules/@boombot/core/reflection/index.js +2 -0
  239. package/dist/node_modules/@boombot/core/reflection/types.d.ts +13 -0
  240. package/dist/node_modules/@boombot/core/reflection/types.js +4 -0
  241. package/dist/node_modules/@boombot/core/research/config.d.ts +89 -0
  242. package/dist/node_modules/@boombot/core/research/config.js +206 -0
  243. package/dist/node_modules/@boombot/core/research/crawl.d.ts +36 -0
  244. package/dist/node_modules/@boombot/core/research/crawl.js +179 -0
  245. package/dist/node_modules/@boombot/core/research/factory.d.ts +26 -0
  246. package/dist/node_modules/@boombot/core/research/factory.js +46 -0
  247. package/dist/node_modules/@boombot/core/research/http.d.ts +87 -0
  248. package/dist/node_modules/@boombot/core/research/http.js +250 -0
  249. package/dist/node_modules/@boombot/core/research/index.d.ts +17 -0
  250. package/dist/node_modules/@boombot/core/research/index.js +10 -0
  251. package/dist/node_modules/@boombot/core/research/orchestrator.d.ts +113 -0
  252. package/dist/node_modules/@boombot/core/research/orchestrator.js +252 -0
  253. package/dist/node_modules/@boombot/core/research/parse/docx.d.ts +24 -0
  254. package/dist/node_modules/@boombot/core/research/parse/docx.js +183 -0
  255. package/dist/node_modules/@boombot/core/research/parse/guards.d.ts +89 -0
  256. package/dist/node_modules/@boombot/core/research/parse/guards.js +171 -0
  257. package/dist/node_modules/@boombot/core/research/parse/index.d.ts +68 -0
  258. package/dist/node_modules/@boombot/core/research/parse/index.js +219 -0
  259. package/dist/node_modules/@boombot/core/research/parse/pdf.d.ts +38 -0
  260. package/dist/node_modules/@boombot/core/research/parse/pdf.js +567 -0
  261. package/dist/node_modules/@boombot/core/research/providers/arxiv.d.ts +9 -0
  262. package/dist/node_modules/@boombot/core/research/providers/arxiv.js +72 -0
  263. package/dist/node_modules/@boombot/core/research/providers/brave.d.ts +11 -0
  264. package/dist/node_modules/@boombot/core/research/providers/brave.js +36 -0
  265. package/dist/node_modules/@boombot/core/research/providers/duckduckgo.d.ts +9 -0
  266. package/dist/node_modules/@boombot/core/research/providers/duckduckgo.js +78 -0
  267. package/dist/node_modules/@boombot/core/research/providers/exa.d.ts +11 -0
  268. package/dist/node_modules/@boombot/core/research/providers/exa.js +34 -0
  269. package/dist/node_modules/@boombot/core/research/providers/firecrawl.d.ts +16 -0
  270. package/dist/node_modules/@boombot/core/research/providers/firecrawl.js +47 -0
  271. package/dist/node_modules/@boombot/core/research/providers/index.d.ts +17 -0
  272. package/dist/node_modules/@boombot/core/research/providers/index.js +11 -0
  273. package/dist/node_modules/@boombot/core/research/providers/jina.d.ts +13 -0
  274. package/dist/node_modules/@boombot/core/research/providers/jina.js +114 -0
  275. package/dist/node_modules/@boombot/core/research/providers/openalex.d.ts +14 -0
  276. package/dist/node_modules/@boombot/core/research/providers/openalex.js +66 -0
  277. package/dist/node_modules/@boombot/core/research/providers/semantic-scholar.d.ts +9 -0
  278. package/dist/node_modules/@boombot/core/research/providers/semantic-scholar.js +56 -0
  279. package/dist/node_modules/@boombot/core/research/providers/tavily.d.ts +11 -0
  280. package/dist/node_modules/@boombot/core/research/providers/tavily.js +35 -0
  281. package/dist/node_modules/@boombot/core/research/providers/wikipedia.d.ts +12 -0
  282. package/dist/node_modules/@boombot/core/research/providers/wikipedia.js +47 -0
  283. package/dist/node_modules/@boombot/core/research/tools.d.ts +27 -0
  284. package/dist/node_modules/@boombot/core/research/tools.js +251 -0
  285. package/dist/node_modules/@boombot/core/research/types.d.ts +133 -0
  286. package/dist/node_modules/@boombot/core/research/types.js +8 -0
  287. package/dist/node_modules/@boombot/core/research/wiring.d.ts +25 -0
  288. package/dist/node_modules/@boombot/core/research/wiring.js +51 -0
  289. package/dist/node_modules/@boombot/core/scheduler/cron.d.ts +34 -0
  290. package/dist/node_modules/@boombot/core/scheduler/cron.js +147 -0
  291. package/dist/node_modules/@boombot/core/scheduler/evaluator.d.ts +42 -0
  292. package/dist/node_modules/@boombot/core/scheduler/evaluator.js +148 -0
  293. package/dist/node_modules/@boombot/core/scheduler/index.d.ts +15 -0
  294. package/dist/node_modules/@boombot/core/scheduler/index.js +15 -0
  295. package/dist/node_modules/@boombot/core/scheduler/registry.d.ts +81 -0
  296. package/dist/node_modules/@boombot/core/scheduler/registry.js +263 -0
  297. package/dist/node_modules/@boombot/core/scheduler/runner.d.ts +59 -0
  298. package/dist/node_modules/@boombot/core/scheduler/runner.js +257 -0
  299. package/dist/node_modules/@boombot/core/scheduler/store.d.ts +150 -0
  300. package/dist/node_modules/@boombot/core/scheduler/store.js +526 -0
  301. package/dist/node_modules/@boombot/core/scheduler/timezone.d.ts +35 -0
  302. package/dist/node_modules/@boombot/core/scheduler/timezone.js +96 -0
  303. package/dist/node_modules/@boombot/core/scheduler/types.d.ts +157 -0
  304. package/dist/node_modules/@boombot/core/scheduler/types.js +89 -0
  305. package/dist/node_modules/@boombot/core/task-runner/index.d.ts +7 -0
  306. package/dist/node_modules/@boombot/core/task-runner/index.js +5 -0
  307. package/dist/node_modules/@boombot/core/task-runner/planner.d.ts +37 -0
  308. package/dist/node_modules/@boombot/core/task-runner/planner.js +154 -0
  309. package/dist/node_modules/@boombot/core/task-runner/runner.d.ts +8 -0
  310. package/dist/node_modules/@boombot/core/task-runner/runner.js +564 -0
  311. package/dist/node_modules/@boombot/core/task-runner/store.d.ts +28 -0
  312. package/dist/node_modules/@boombot/core/task-runner/store.js +126 -0
  313. package/dist/node_modules/@boombot/core/task-runner/types.d.ts +138 -0
  314. package/dist/node_modules/@boombot/core/task-runner/types.js +11 -0
  315. package/dist/node_modules/@boombot/core/workflow/dag.d.ts +16 -0
  316. package/dist/node_modules/@boombot/core/workflow/dag.js +109 -0
  317. package/dist/node_modules/@boombot/core/workflow/engine.d.ts +34 -0
  318. package/dist/node_modules/@boombot/core/workflow/engine.js +304 -0
  319. package/dist/node_modules/@boombot/core/workflow/index.d.ts +3 -0
  320. package/dist/node_modules/@boombot/core/workflow/index.js +3 -0
  321. package/dist/node_modules/@boombot/core/workflow/types.d.ts +98 -0
  322. package/dist/node_modules/@boombot/core/workflow/types.js +21 -0
  323. package/dist/node_modules/@boombot/cronjobs/handlers.d.ts +11 -0
  324. package/dist/node_modules/@boombot/cronjobs/handlers.js +174 -0
  325. package/dist/node_modules/@boombot/cronjobs/index.d.ts +2 -0
  326. package/dist/node_modules/@boombot/cronjobs/index.js +2 -0
  327. package/dist/node_modules/@boombot/cronjobs/package.json +9 -0
  328. package/dist/node_modules/@boombot/cronjobs/service.d.ts +53 -0
  329. package/dist/node_modules/@boombot/cronjobs/service.js +200 -0
  330. package/dist/node_modules/@boombot/plugins/index.d.ts +2 -0
  331. package/dist/node_modules/@boombot/plugins/index.js +2 -0
  332. package/dist/node_modules/@boombot/plugins/installer.d.ts +45 -0
  333. package/dist/node_modules/@boombot/plugins/installer.js +487 -0
  334. package/dist/node_modules/@boombot/plugins/manager.d.ts +23 -0
  335. package/dist/node_modules/@boombot/plugins/manager.js +243 -0
  336. package/dist/node_modules/@boombot/plugins/package.json +9 -0
  337. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-channels.d.ts +125 -0
  338. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-channels.js +76 -0
  339. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-plugins.d.ts +220 -0
  340. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-plugins.js +60 -0
  341. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-scheduler.d.ts +33 -0
  342. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-scheduler.js +25 -0
  343. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands.d.ts +4349 -0
  344. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands.js +563 -0
  345. package/dist/node_modules/@boombot/protocol/gateway-protocol/envelope.d.ts +32 -0
  346. package/dist/node_modules/@boombot/protocol/gateway-protocol/envelope.js +61 -0
  347. package/dist/node_modules/@boombot/protocol/gateway-protocol/errors.d.ts +13 -0
  348. package/dist/node_modules/@boombot/protocol/gateway-protocol/errors.js +16 -0
  349. package/dist/node_modules/@boombot/protocol/gateway-protocol/events.d.ts +567 -0
  350. package/dist/node_modules/@boombot/protocol/gateway-protocol/events.js +395 -0
  351. package/dist/node_modules/@boombot/protocol/gateway-protocol/index.d.ts +20 -0
  352. package/dist/node_modules/@boombot/protocol/gateway-protocol/index.js +13 -0
  353. package/dist/node_modules/@boombot/protocol/gateway-protocol/types.d.ts +91 -0
  354. package/dist/node_modules/@boombot/protocol/gateway-protocol/types.js +7 -0
  355. package/dist/node_modules/@boombot/protocol/index.d.ts +4 -0
  356. package/dist/node_modules/@boombot/protocol/index.js +3 -0
  357. package/dist/node_modules/@boombot/protocol/package.json +9 -0
  358. package/dist/node_modules/@boombot/protocol/plugin-sdk/channel.d.ts +41 -0
  359. package/dist/node_modules/@boombot/protocol/plugin-sdk/channel.js +17 -0
  360. package/dist/node_modules/@boombot/protocol/plugin-sdk/index.d.ts +10 -0
  361. package/dist/node_modules/@boombot/protocol/plugin-sdk/index.js +10 -0
  362. package/dist/node_modules/@boombot/protocol/plugin-sdk/manifest.d.ts +58 -0
  363. package/dist/node_modules/@boombot/protocol/plugin-sdk/manifest.js +116 -0
  364. package/dist/node_modules/@boombot/protocol/plugin-sdk/plugin.d.ts +25 -0
  365. package/dist/node_modules/@boombot/protocol/plugin-sdk/plugin.js +1 -0
  366. package/dist/node_modules/@boombot/protocol/providers/cipher.d.ts +7 -0
  367. package/dist/node_modules/@boombot/protocol/providers/cipher.js +52 -0
  368. package/dist/node_modules/@boombot/protocol/providers/index.d.ts +19 -0
  369. package/dist/node_modules/@boombot/protocol/providers/index.js +19 -0
  370. package/dist/node_modules/@boombot/protocol/providers/key-roulette.d.ts +79 -0
  371. package/dist/node_modules/@boombot/protocol/providers/key-roulette.js +81 -0
  372. package/dist/node_modules/@boombot/protocol/providers/probe.d.ts +29 -0
  373. package/dist/node_modules/@boombot/protocol/providers/probe.js +96 -0
  374. package/dist/node_modules/@boombot/protocol/providers/profiles/anthropic.d.ts +11 -0
  375. package/dist/node_modules/@boombot/protocol/providers/profiles/anthropic.js +11 -0
  376. package/dist/node_modules/@boombot/protocol/providers/profiles/custom.d.ts +22 -0
  377. package/dist/node_modules/@boombot/protocol/providers/profiles/custom.js +222 -0
  378. package/dist/node_modules/@boombot/protocol/providers/profiles/deepseek.d.ts +7 -0
  379. package/dist/node_modules/@boombot/protocol/providers/profiles/deepseek.js +9 -0
  380. package/dist/node_modules/@boombot/protocol/providers/profiles/google.d.ts +10 -0
  381. package/dist/node_modules/@boombot/protocol/providers/profiles/google.js +10 -0
  382. package/dist/node_modules/@boombot/protocol/providers/profiles/index.d.ts +31 -0
  383. package/dist/node_modules/@boombot/protocol/providers/profiles/index.js +56 -0
  384. package/dist/node_modules/@boombot/protocol/providers/profiles/local.d.ts +10 -0
  385. package/dist/node_modules/@boombot/protocol/providers/profiles/local.js +11 -0
  386. package/dist/node_modules/@boombot/protocol/providers/profiles/mistral.d.ts +7 -0
  387. package/dist/node_modules/@boombot/protocol/providers/profiles/mistral.js +9 -0
  388. package/dist/node_modules/@boombot/protocol/providers/profiles/openai-compatible.d.ts +10 -0
  389. package/dist/node_modules/@boombot/protocol/providers/profiles/openai-compatible.js +10 -0
  390. package/dist/node_modules/@boombot/protocol/providers/profiles/openai.d.ts +7 -0
  391. package/dist/node_modules/@boombot/protocol/providers/profiles/openai.js +11 -0
  392. package/dist/node_modules/@boombot/protocol/providers/profiles/types.d.ts +58 -0
  393. package/dist/node_modules/@boombot/protocol/providers/profiles/types.js +1 -0
  394. package/dist/node_modules/@boombot/protocol/providers/profiles/xai.d.ts +7 -0
  395. package/dist/node_modules/@boombot/protocol/providers/profiles/xai.js +10 -0
  396. package/dist/node_modules/@boombot/protocol/providers/request-profile.d.ts +102 -0
  397. package/dist/node_modules/@boombot/protocol/providers/request-profile.js +118 -0
  398. package/dist/node_modules/@boombot/protocol/providers/service.d.ts +2 -0
  399. package/dist/node_modules/@boombot/protocol/providers/service.js +418 -0
  400. package/dist/node_modules/@boombot/protocol/providers/types.d.ts +141 -0
  401. package/dist/node_modules/@boombot/protocol/providers/types.js +16 -0
  402. package/dist/node_modules/@boombot/sandbox/fs-path.d.ts +13 -0
  403. package/dist/node_modules/@boombot/sandbox/fs-path.js +79 -0
  404. package/dist/node_modules/@boombot/sandbox/index.d.ts +13 -0
  405. package/dist/node_modules/@boombot/sandbox/index.js +13 -0
  406. package/dist/node_modules/@boombot/sandbox/native.d.ts +39 -0
  407. package/dist/node_modules/@boombot/sandbox/native.js +224 -0
  408. package/dist/node_modules/@boombot/sandbox/package.json +9 -0
  409. package/dist/node_modules/@boombot/sandbox/sandbox.d.ts +92 -0
  410. package/dist/node_modules/@boombot/sandbox/sandbox.js +229 -0
  411. package/dist/node_modules/@boombot/security/harness-guard/boundary.d.ts +22 -0
  412. package/dist/node_modules/@boombot/security/harness-guard/boundary.js +105 -0
  413. package/dist/node_modules/@boombot/security/harness-guard/gates.d.ts +90 -0
  414. package/dist/node_modules/@boombot/security/harness-guard/gates.js +791 -0
  415. package/dist/node_modules/@boombot/security/harness-guard/index.d.ts +23 -0
  416. package/dist/node_modules/@boombot/security/harness-guard/index.js +23 -0
  417. package/dist/node_modules/@boombot/security/harness-guard/policy.d.ts +20 -0
  418. package/dist/node_modules/@boombot/security/harness-guard/policy.js +70 -0
  419. package/dist/node_modules/@boombot/security/harness-guard/sanitizer.d.ts +53 -0
  420. package/dist/node_modules/@boombot/security/harness-guard/sanitizer.js +145 -0
  421. package/dist/node_modules/@boombot/security/harness-guard/types.d.ts +71 -0
  422. package/dist/node_modules/@boombot/security/harness-guard/types.js +10 -0
  423. package/dist/node_modules/@boombot/security/harness-guard/verifier.d.ts +59 -0
  424. package/dist/node_modules/@boombot/security/harness-guard/verifier.js +169 -0
  425. package/dist/node_modules/@boombot/security/index.d.ts +5 -0
  426. package/dist/node_modules/@boombot/security/index.js +9 -0
  427. package/dist/node_modules/@boombot/security/package.json +9 -0
  428. package/dist/node_modules/@boombot/security/policy/approval.d.ts +117 -0
  429. package/dist/node_modules/@boombot/security/policy/approval.js +223 -0
  430. package/dist/node_modules/@boombot/security/reasoning-guard/claim-extractor.d.ts +10 -0
  431. package/dist/node_modules/@boombot/security/reasoning-guard/claim-extractor.js +124 -0
  432. package/dist/node_modules/@boombot/security/reasoning-guard/evidence-ledger.d.ts +25 -0
  433. package/dist/node_modules/@boombot/security/reasoning-guard/evidence-ledger.js +70 -0
  434. package/dist/node_modules/@boombot/security/reasoning-guard/gate.d.ts +38 -0
  435. package/dist/node_modules/@boombot/security/reasoning-guard/gate.js +61 -0
  436. package/dist/node_modules/@boombot/security/reasoning-guard/grounding-check.d.ts +12 -0
  437. package/dist/node_modules/@boombot/security/reasoning-guard/grounding-check.js +234 -0
  438. package/dist/node_modules/@boombot/security/reasoning-guard/index.d.ts +17 -0
  439. package/dist/node_modules/@boombot/security/reasoning-guard/index.js +13 -0
  440. package/dist/node_modules/@boombot/security/reasoning-guard/policy.d.ts +15 -0
  441. package/dist/node_modules/@boombot/security/reasoning-guard/policy.js +39 -0
  442. package/dist/node_modules/@boombot/security/reasoning-guard/types.d.ts +46 -0
  443. package/dist/node_modules/@boombot/security/reasoning-guard/types.js +7 -0
  444. package/dist/node_modules/@boombot/security/security/approval.d.ts +63 -0
  445. package/dist/node_modules/@boombot/security/security/approval.js +140 -0
  446. package/dist/node_modules/@boombot/security/security/audit.d.ts +39 -0
  447. package/dist/node_modules/@boombot/security/security/audit.js +70 -0
  448. package/dist/node_modules/@boombot/security/security/index.d.ts +12 -0
  449. package/dist/node_modules/@boombot/security/security/index.js +12 -0
  450. package/dist/node_modules/@boombot/security/security/trust.d.ts +79 -0
  451. package/dist/node_modules/@boombot/security/security/trust.js +87 -0
  452. package/dist/package.json +5 -0
  453. package/dist/proto/agent_core.proto +56 -0
  454. package/dist/python/agent-core-python/pyproject.toml +40 -0
  455. package/dist/python/agent-core-python/src/boombot_agent/__init__.py +5 -0
  456. package/dist/python/agent-core-python/src/boombot_agent/generated/__init__.py +0 -0
  457. package/dist/python/agent-core-python/src/boombot_agent/generated/agent_core_pb2.py +54 -0
  458. package/dist/python/agent-core-python/src/boombot_agent/generated/agent_core_pb2_grpc.py +140 -0
  459. package/dist/python/agent-core-python/src/boombot_agent/rpc.py +265 -0
  460. package/dist/python/agent-core-python/src/boombot_agent/turn.py +577 -0
  461. package/dist/python/agent-core-python/src/boombot_ml/__init__.py +12 -0
  462. package/dist/python/agent-core-python/src/boombot_ml/embeddings.py +58 -0
  463. package/dist/python/agent-core-python/src/boombot_ml/training.py +156 -0
  464. package/dist/python/agent-core-python/uv.lock +2856 -0
  465. package/dist/web/assets/ChatView-BZrSD-64.js +262 -0
  466. package/dist/web/assets/ChatView-Cahbjez6.css +1 -0
  467. package/dist/web/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  468. package/dist/web/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  469. package/dist/web/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  470. package/dist/web/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  471. package/dist/web/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  472. package/dist/web/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  473. package/dist/web/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  474. package/dist/web/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  475. package/dist/web/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  476. package/dist/web/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  477. package/dist/web/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  478. package/dist/web/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  479. package/dist/web/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  480. package/dist/web/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  481. package/dist/web/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  482. package/dist/web/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  483. package/dist/web/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  484. package/dist/web/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  485. package/dist/web/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  486. package/dist/web/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  487. package/dist/web/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  488. package/dist/web/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  489. package/dist/web/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  490. package/dist/web/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  491. package/dist/web/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  492. package/dist/web/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  493. package/dist/web/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  494. package/dist/web/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  495. package/dist/web/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  496. package/dist/web/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  497. package/dist/web/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  498. package/dist/web/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  499. package/dist/web/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  500. package/dist/web/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  501. package/dist/web/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  502. package/dist/web/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  503. package/dist/web/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  504. package/dist/web/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  505. package/dist/web/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  506. package/dist/web/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  507. package/dist/web/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  508. package/dist/web/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  509. package/dist/web/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  510. package/dist/web/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  511. package/dist/web/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  512. package/dist/web/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  513. package/dist/web/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  514. package/dist/web/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  515. package/dist/web/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  516. package/dist/web/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  517. package/dist/web/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  518. package/dist/web/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  519. package/dist/web/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  520. package/dist/web/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  521. package/dist/web/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  522. package/dist/web/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  523. package/dist/web/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  524. package/dist/web/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  525. package/dist/web/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  526. package/dist/web/assets/MemoryView-BJbXqqs7.css +1 -0
  527. package/dist/web/assets/MemoryView-BfMq_6CD.js +1 -0
  528. package/dist/web/assets/SchedulesView-B22QmPR-.js +1 -0
  529. package/dist/web/assets/SchedulesView-C6XK7A8a.css +1 -0
  530. package/dist/web/assets/SessionsView-C1dqdhxI.css +1 -0
  531. package/dist/web/assets/SessionsView-DS0-aH2a.js +1 -0
  532. package/dist/web/assets/TasksView-Dtasg4hd.css +1 -0
  533. package/dist/web/assets/TasksView-ey0FLsW8.js +2 -0
  534. package/dist/web/assets/Textarea-DN3Zybl1.js +1 -0
  535. package/dist/web/assets/Tooltip-Bn2cqFPz.css +1 -0
  536. package/dist/web/assets/Tooltip-MzV2Gqnc.js +1 -0
  537. package/dist/web/assets/browser-Bnt73-Ub.js +8 -0
  538. package/dist/web/assets/index-BL8bi7Yt.css +1 -0
  539. package/dist/web/assets/index-CuPR73Tn.js +73 -0
  540. package/dist/web/favicon.svg +4 -0
  541. package/dist/web/index.html +26 -0
  542. package/dist/web/logo.jpg +0 -0
  543. package/dist/web/logo.png +0 -0
  544. package/package.json +51 -4
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Brave Search adapter (paid, API key required).
3
+ *
4
+ * Wraps the Brave Search API (`/res/v1/web/search`). The key travels in
5
+ * the `X-Subscription-Token` header — never in the URL, never logged.
6
+ */
7
+ import { fetchJson, truncate, withRetry } from '../http.js';
8
+ const MAX_RESULTS = 20;
9
+ export function createBraveProvider(options) {
10
+ return {
11
+ id: 'brave',
12
+ kind: 'paid',
13
+ async search(query, opts = {}) {
14
+ const limit = Math.min(Math.max(opts.limit ?? 8, 1), MAX_RESULTS);
15
+ const params = new URLSearchParams({
16
+ q: query,
17
+ count: String(limit),
18
+ text_decorations: '0',
19
+ safesearch: 'moderate',
20
+ });
21
+ const url = `https://api.search.brave.com/res/v1/web/search?${params.toString()}`;
22
+ const raw = await withRetry(() => fetchJson(url, {
23
+ signal: opts.signal,
24
+ timeoutMs: 20_000,
25
+ headers: { 'X-Subscription-Token': options.apiKey },
26
+ }));
27
+ const body = raw;
28
+ return (body.web?.results ?? []).slice(0, limit).map((hit) => ({
29
+ title: hit.title ?? '',
30
+ url: hit.url ?? '',
31
+ snippet: truncate(hit.description ?? '', 300),
32
+ source: 'brave',
33
+ }));
34
+ },
35
+ };
36
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * DuckDuckGo Instant Answer provider (free, no key).
3
+ *
4
+ * Uses the public Instant Answer API (`api.duckduckgo.com`, `format=json`,
5
+ * `no_html=1`). Returns the abstract plus related topics — best-effort,
6
+ * general-knowledge search, not a full web index.
7
+ */
8
+ import type { ResearchProvider } from '../types.js';
9
+ export declare function createDuckDuckGoProvider(): ResearchProvider;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * DuckDuckGo Instant Answer provider (free, no key).
3
+ *
4
+ * Uses the public Instant Answer API (`api.duckduckgo.com`, `format=json`,
5
+ * `no_html=1`). Returns the abstract plus related topics — best-effort,
6
+ * general-knowledge search, not a full web index.
7
+ */
8
+ import { fetchJson, truncate, withRetry } from '../http.js';
9
+ const MAX_RESULTS = 20;
10
+ function isTopic(t) {
11
+ return (typeof t === 'object' &&
12
+ t !== null &&
13
+ typeof t.Text === 'string' &&
14
+ typeof t.FirstURL === 'string');
15
+ }
16
+ /** Flatten nested `Topics` groups; entries without a URL are containers, not results. */
17
+ function flattenTopics(raw) {
18
+ const out = [];
19
+ for (const item of raw ?? []) {
20
+ if (item === undefined || item === null)
21
+ continue;
22
+ if ('Topics' in item && Array.isArray(item.Topics)) {
23
+ for (const sub of item.Topics) {
24
+ if (isTopic(sub) && (sub.FirstURL ?? '') !== '')
25
+ out.push(sub);
26
+ }
27
+ }
28
+ else if (isTopic(item) && (item.FirstURL ?? '') !== '') {
29
+ out.push(item);
30
+ }
31
+ }
32
+ return out;
33
+ }
34
+ export function createDuckDuckGoProvider() {
35
+ return {
36
+ id: 'duckduckgo',
37
+ kind: 'free',
38
+ async search(query, opts = {}) {
39
+ const limit = Math.min(Math.max(opts.limit ?? 8, 1), MAX_RESULTS);
40
+ const params = new URLSearchParams({
41
+ q: query,
42
+ format: 'json',
43
+ no_html: '1',
44
+ skip_disambig: '1',
45
+ });
46
+ const url = `https://api.duckduckgo.com/?${params.toString()}`;
47
+ const raw = await withRetry(() => fetchJson(url, { signal: opts.signal, timeoutMs: 2_500 }));
48
+ const body = raw;
49
+ const results = [];
50
+ if (body.AbstractText !== undefined && body.AbstractText !== '' &&
51
+ body.AbstractURL !== undefined && body.AbstractURL !== '') {
52
+ results.push({
53
+ title: body.Heading ?? query,
54
+ url: body.AbstractURL,
55
+ snippet: truncate(body.AbstractText, 300),
56
+ source: 'duckduckgo',
57
+ });
58
+ }
59
+ for (const topic of flattenTopics(body.RelatedTopics)) {
60
+ if (results.length >= limit)
61
+ break;
62
+ const text = topic.Text ?? '';
63
+ const topicUrl = topic.FirstURL ?? '';
64
+ if (text === '' || topicUrl === '')
65
+ continue;
66
+ const dash = text.indexOf('–');
67
+ const title = (dash > 0 ? text.slice(0, dash) : text.slice(0, 80)).trim();
68
+ results.push({
69
+ title: title === '' ? topicUrl : title,
70
+ url: topicUrl,
71
+ snippet: truncate(text, 300),
72
+ source: 'duckduckgo',
73
+ });
74
+ }
75
+ return results.slice(0, limit);
76
+ },
77
+ };
78
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Exa search adapter (paid, API key required).
3
+ *
4
+ * Wraps the Exa Search API via POST. The key travels in the `x-api-key`
5
+ * header — never in the URL, never logged.
6
+ */
7
+ import type { ResearchProvider } from '../types.js';
8
+ export interface ExaProviderOptions {
9
+ readonly apiKey: string;
10
+ }
11
+ export declare function createExaProvider(options: ExaProviderOptions): ResearchProvider;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Exa search adapter (paid, API key required).
3
+ *
4
+ * Wraps the Exa Search API via POST. The key travels in the `x-api-key`
5
+ * header — never in the URL, never logged.
6
+ */
7
+ import { postJson, truncate, withRetry } from '../http.js';
8
+ const MAX_RESULTS = 20;
9
+ export function createExaProvider(options) {
10
+ return {
11
+ id: 'exa',
12
+ kind: 'paid',
13
+ async search(query, opts = {}) {
14
+ const limit = Math.min(Math.max(opts.limit ?? 8, 1), MAX_RESULTS);
15
+ const raw = await withRetry(() => postJson('https://api.exa.ai/search', {
16
+ query,
17
+ numResults: limit,
18
+ contents: { text: { maxCharacters: 2000 } },
19
+ }, {
20
+ signal: opts.signal,
21
+ timeoutMs: 20_000,
22
+ headers: { 'x-api-key': options.apiKey },
23
+ }));
24
+ const body = raw;
25
+ return (body.results ?? []).slice(0, limit).map((hit) => ({
26
+ title: hit.title ?? '',
27
+ url: hit.url ?? '',
28
+ snippet: truncate(hit.text ?? '', 300),
29
+ source: 'exa',
30
+ publishedAt: hit.publishedDate,
31
+ }));
32
+ },
33
+ };
34
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Firecrawl extract adapter (paid, API key required).
3
+ *
4
+ * Wraps the Firecrawl Scrape API (`/v1/scrape`) with `markdown` format and
5
+ * main-content-only extraction. The key travels in the `Authorization:
6
+ * Bearer` header — never in the URL, never logged.
7
+ *
8
+ * Windowing: `opts.offset` re-scrapes the page and serves the slice
9
+ * `[offset, offset + MAX_CHARS)`; `nextOffset`/`totalLength` let callers
10
+ * page through long documents (see `research.extract`'s `offset` param).
11
+ */
12
+ import type { ExtractProvider } from '../types.js';
13
+ export interface FirecrawlProviderOptions {
14
+ readonly apiKey: string;
15
+ }
16
+ export declare function createFirecrawlProvider(options: FirecrawlProviderOptions): ExtractProvider;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Firecrawl extract adapter (paid, API key required).
3
+ *
4
+ * Wraps the Firecrawl Scrape API (`/v1/scrape`) with `markdown` format and
5
+ * main-content-only extraction. The key travels in the `Authorization:
6
+ * Bearer` header — never in the URL, never logged.
7
+ *
8
+ * Windowing: `opts.offset` re-scrapes the page and serves the slice
9
+ * `[offset, offset + MAX_CHARS)`; `nextOffset`/`totalLength` let callers
10
+ * page through long documents (see `research.extract`'s `offset` param).
11
+ */
12
+ import { postJson, TRUNCATED_MARKER, withRetry } from '../http.js';
13
+ const MAX_CHARS = 12_000;
14
+ const TIMEOUT_MS = 45_000;
15
+ export function createFirecrawlProvider(options) {
16
+ return {
17
+ id: 'firecrawl',
18
+ kind: 'paid',
19
+ async extract(url, signal, opts) {
20
+ const raw = await withRetry(() => postJson('https://api.firecrawl.dev/v1/scrape', {
21
+ url,
22
+ formats: ['markdown'],
23
+ onlyMainContent: true,
24
+ maxAge: 3_600_000,
25
+ }, {
26
+ signal,
27
+ timeoutMs: TIMEOUT_MS,
28
+ headers: { Authorization: `Bearer ${options.apiKey}` },
29
+ }));
30
+ const body = raw;
31
+ const markdown = body.data?.markdown ?? '';
32
+ const offset = Math.max(0, Math.floor(opts?.offset ?? 0));
33
+ const slice = markdown.slice(offset, offset + MAX_CHARS);
34
+ const totalLength = markdown.length;
35
+ const hasMore = offset + slice.length < totalLength;
36
+ return {
37
+ url,
38
+ title: body.data?.metadata?.title ?? '',
39
+ markdown: hasMore ? slice + TRUNCATED_MARKER : slice,
40
+ truncated: hasMore,
41
+ offset,
42
+ totalLength,
43
+ nextOffset: hasMore ? offset + MAX_CHARS : undefined,
44
+ };
45
+ },
46
+ };
47
+ }
@@ -0,0 +1,17 @@
1
+ /** Provider factories for `@boombot/core`. */
2
+ export { createWikipediaProvider } from './wikipedia.js';
3
+ export type { WikipediaProviderOptions } from './wikipedia.js';
4
+ export { createDuckDuckGoProvider } from './duckduckgo.js';
5
+ export { createArxivProvider } from './arxiv.js';
6
+ export { createOpenAlexProvider } from './openalex.js';
7
+ export type { OpenAlexProviderOptions } from './openalex.js';
8
+ export { createSemanticScholarProvider } from './semantic-scholar.js';
9
+ export { createJinaProvider } from './jina.js';
10
+ export { createTavilyProvider } from './tavily.js';
11
+ export type { TavilyProviderOptions } from './tavily.js';
12
+ export { createExaProvider } from './exa.js';
13
+ export type { ExaProviderOptions } from './exa.js';
14
+ export { createBraveProvider } from './brave.js';
15
+ export type { BraveProviderOptions } from './brave.js';
16
+ export { createFirecrawlProvider } from './firecrawl.js';
17
+ export type { FirecrawlProviderOptions } from './firecrawl.js';
@@ -0,0 +1,11 @@
1
+ /** Provider factories for `@boombot/core`. */
2
+ export { createWikipediaProvider } from './wikipedia.js';
3
+ export { createDuckDuckGoProvider } from './duckduckgo.js';
4
+ export { createArxivProvider } from './arxiv.js';
5
+ export { createOpenAlexProvider } from './openalex.js';
6
+ export { createSemanticScholarProvider } from './semantic-scholar.js';
7
+ export { createJinaProvider } from './jina.js';
8
+ export { createTavilyProvider } from './tavily.js';
9
+ export { createExaProvider } from './exa.js';
10
+ export { createBraveProvider } from './brave.js';
11
+ export { createFirecrawlProvider } from './firecrawl.js';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Jina Reader extract provider (free, no key).
3
+ *
4
+ * Uses the public Jina AI Reader (`https://r.jina.ai/<url>`) to turn a page
5
+ * into markdown. Free tier is rate-limited — callers should extract only
6
+ * the top few URLs.
7
+ *
8
+ * Windowing: `opts.offset` re-fetches the page and serves the slice
9
+ * `[offset, offset + MAX_CHARS)`; `nextOffset`/`totalLength` let callers
10
+ * page through long documents (see `research.extract`'s `offset` param).
11
+ */
12
+ import type { ExtractProvider } from '../types.js';
13
+ export declare function createJinaProvider(): ExtractProvider;
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Jina Reader extract provider (free, no key).
3
+ *
4
+ * Uses the public Jina AI Reader (`https://r.jina.ai/<url>`) to turn a page
5
+ * into markdown. Free tier is rate-limited — callers should extract only
6
+ * the top few URLs.
7
+ *
8
+ * Windowing: `opts.offset` re-fetches the page and serves the slice
9
+ * `[offset, offset + MAX_CHARS)`; `nextOffset`/`totalLength` let callers
10
+ * page through long documents (see `research.extract`'s `offset` param).
11
+ */
12
+ import { fetchText, withRetry, TRUNCATED_MARKER } from '../http.js';
13
+ const MAX_CHARS = 8000;
14
+ /**
15
+ * Ceiling for one reader fetch. It used to be 30s AND retried, so a slow
16
+ * page held the turn for up to 60s. The retry is gone (`http.ts` no longer
17
+ * retries timeouts); this lowers the remaining worst case to one 15s wait.
18
+ * Extract is asked for by name, so it may cost more than a search engine —
19
+ * but not a minute.
20
+ */
21
+ const TIMEOUT_MS = 15_000;
22
+ function guessTitle(markdown) {
23
+ for (const line of markdown.split('\n')) {
24
+ const trimmed = line.trim();
25
+ if (trimmed.startsWith('# '))
26
+ return trimmed.slice(2).trim();
27
+ if (trimmed.startsWith('Title: '))
28
+ return trimmed.slice(7).trim();
29
+ }
30
+ return '';
31
+ }
32
+ function htmlToMarkdown(html) {
33
+ let text = html;
34
+ text = text.replace(/<head\b[^<]*(?:(?!<\/head>)<[^<]*)*<\/head>/gi, '');
35
+ text = text.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
36
+ text = text.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, '');
37
+ text = text.replace(/<svg\b[^<]*(?:(?!<\/svg>)<[^<]*)*<\/svg>/gi, '');
38
+ text = text.replace(/<noscript\b[^<]*(?:(?!<\/noscript>)<[^<]*)*<\/noscript>/gi, '');
39
+ text = text.replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, '\n# $1\n');
40
+ text = text.replace(/<h2[^>]*>([\s\S]*?)<\/h2>/gi, '\n## $1\n');
41
+ text = text.replace(/<h3[^>]*>([\s\S]*?)<\/h3>/gi, '\n### $1\n');
42
+ text = text.replace(/<h[4-6][^>]*>([\s\S]*?)<\/h[4-6]>/gi, '\n#### $1\n');
43
+ text = text.replace(/<article[^>]*>([\s\S]*?)<\/article>/gi, '\n\n$1\n\n');
44
+ text = text.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, '\n- $1');
45
+ text = text.replace(/<p[^>]*>([\s\S]*?)<\/p>/gi, '\n\n$1\n\n');
46
+ text = text.replace(/<br\s*\/?>/gi, '\n');
47
+ text = text.replace(/<a[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/gi, (_, href, content) => {
48
+ const clean = content.replace(/<[^>]+>/g, '').trim();
49
+ return clean ? ` [${clean}](${href}) ` : '';
50
+ });
51
+ text = text.replace(/<[^>]+>/g, ' ');
52
+ text = text
53
+ .replace(/&amp;/g, '&')
54
+ .replace(/&lt;/g, '<')
55
+ .replace(/&gt;/g, '>')
56
+ .replace(/&quot;/g, '"')
57
+ .replace(/&#39;/g, "'")
58
+ .replace(/&nbsp;/g, ' ');
59
+ return text
60
+ .split('\n')
61
+ .map((line) => line.trim())
62
+ .filter((line, i, arr) => line !== '' || (i > 0 && arr[i - 1] !== ''))
63
+ .join('\n')
64
+ .trim();
65
+ }
66
+ export function createJinaProvider() {
67
+ return {
68
+ id: 'jina',
69
+ kind: 'free',
70
+ async extract(url, signal, opts) {
71
+ let markdown = '';
72
+ try {
73
+ const readerUrl = `https://r.jina.ai/${url}`;
74
+ const raw = await withRetry(() => fetchText(readerUrl, {
75
+ signal,
76
+ timeoutMs: TIMEOUT_MS,
77
+ headers: { 'X-Return-Format': 'markdown' },
78
+ }));
79
+ if (raw.trim().startsWith('{') &&
80
+ (raw.includes('"code":403') ||
81
+ raw.includes('AbuseAlleviationError') ||
82
+ raw.includes('"error"'))) {
83
+ throw new Error('Jina reader returned abuse alleviation error');
84
+ }
85
+ markdown = raw;
86
+ }
87
+ catch {
88
+ // Fall back gracefully to direct fetch with browser user agent
89
+ const directHtml = await fetchText(url, {
90
+ signal,
91
+ timeoutMs: TIMEOUT_MS,
92
+ headers: {
93
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
94
+ Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
95
+ },
96
+ });
97
+ markdown = htmlToMarkdown(directHtml);
98
+ }
99
+ const offset = Math.max(0, Math.floor(opts?.offset ?? 0));
100
+ const slice = markdown.slice(offset, offset + MAX_CHARS);
101
+ const totalLength = markdown.length;
102
+ const hasMore = offset + slice.length < totalLength;
103
+ return {
104
+ url,
105
+ title: guessTitle(slice),
106
+ markdown: hasMore ? slice + TRUNCATED_MARKER : slice,
107
+ truncated: hasMore,
108
+ offset,
109
+ totalLength,
110
+ nextOffset: hasMore ? offset + MAX_CHARS : undefined,
111
+ };
112
+ },
113
+ };
114
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * OpenAlex search provider (free, no key).
3
+ *
4
+ * Queries the OpenAlex works index for scholarly metadata. The abstract
5
+ * comes back as an inverted index (`abstract_inverted_index`), which is
6
+ * reconstructed into readable text; snippets are capped at the first 40
7
+ * words. A `mailto` contact improves rate limits and is polite API use.
8
+ */
9
+ import type { ResearchProvider } from '../types.js';
10
+ export interface OpenAlexProviderOptions {
11
+ /** Contact email sent as `mailto` (polite API use, better rate limits). */
12
+ readonly mailto?: string;
13
+ }
14
+ export declare function createOpenAlexProvider(options?: OpenAlexProviderOptions): ResearchProvider;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * OpenAlex search provider (free, no key).
3
+ *
4
+ * Queries the OpenAlex works index for scholarly metadata. The abstract
5
+ * comes back as an inverted index (`abstract_inverted_index`), which is
6
+ * reconstructed into readable text; snippets are capped at the first 40
7
+ * words. A `mailto` contact improves rate limits and is polite API use.
8
+ */
9
+ import { fetchJson, truncate, withRetry } from '../http.js';
10
+ const MAX_RESULTS = 20;
11
+ const CONTACT_EMAIL = 'research@boombot.example';
12
+ function reconstructAbstract(inverted) {
13
+ if (inverted === undefined)
14
+ return '';
15
+ const words = [];
16
+ for (const [word, positions] of Object.entries(inverted)) {
17
+ for (const pos of positions)
18
+ words[pos] = word;
19
+ }
20
+ return words
21
+ .filter((w) => w !== undefined)
22
+ .slice(0, 40)
23
+ .join(' ');
24
+ }
25
+ function workUrl(work) {
26
+ if (work.doi !== undefined && work.doi !== '') {
27
+ const doi = work.doi.startsWith('https://') ? work.doi : `https://doi.org/${work.doi}`;
28
+ return doi;
29
+ }
30
+ return work.id;
31
+ }
32
+ export function createOpenAlexProvider(options = {}) {
33
+ const mailto = options.mailto ?? CONTACT_EMAIL;
34
+ return {
35
+ id: 'openalex',
36
+ kind: 'free',
37
+ async search(query, opts = {}) {
38
+ const limit = Math.min(Math.max(opts.limit ?? 8, 1), MAX_RESULTS);
39
+ const params = new URLSearchParams({
40
+ search: query,
41
+ 'per-page': String(limit),
42
+ select: 'id,title,doi,abstract_inverted_index,from_publication_date',
43
+ mailto,
44
+ });
45
+ const url = `https://api.openalex.org/works?${params.toString()}`;
46
+ const raw = await withRetry(() => fetchJson(url, { signal: opts.signal, timeoutMs: 15_000 }));
47
+ const body = raw;
48
+ const results = [];
49
+ for (const work of body.results ?? []) {
50
+ const url_ = workUrl(work);
51
+ if (url_ === undefined || work.title === undefined)
52
+ continue;
53
+ results.push({
54
+ title: work.title,
55
+ url: url_,
56
+ snippet: truncate(reconstructAbstract(work.abstract_inverted_index), 300),
57
+ source: 'openalex',
58
+ publishedAt: work.from_publication_date,
59
+ });
60
+ if (results.length >= limit)
61
+ break;
62
+ }
63
+ return results;
64
+ },
65
+ };
66
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Semantic Scholar search provider (free, no key).
3
+ *
4
+ * Uses the Graph API paper search endpoint. A polite User-Agent is sent;
5
+ * the API is rate-limited for unauthenticated callers, so snippets are
6
+ * fetched in a single request and results are capped.
7
+ */
8
+ import type { ResearchProvider } from '../types.js';
9
+ export declare function createSemanticScholarProvider(): ResearchProvider;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Semantic Scholar search provider (free, no key).
3
+ *
4
+ * Uses the Graph API paper search endpoint. A polite User-Agent is sent;
5
+ * the API is rate-limited for unauthenticated callers, so snippets are
6
+ * fetched in a single request and results are capped.
7
+ */
8
+ import { fetchJson, truncate, withRetry } from '../http.js';
9
+ const MAX_RESULTS = 20;
10
+ function paperUrl(paper) {
11
+ if (paper.url !== undefined && paper.url !== null && paper.url !== '') {
12
+ return paper.url;
13
+ }
14
+ const pdf = paper.openAccessPdf?.url;
15
+ if (pdf !== undefined && pdf !== '')
16
+ return pdf;
17
+ const doi = paper.externalIds?.DOI;
18
+ if (doi !== undefined && doi !== '')
19
+ return `https://doi.org/${doi}`;
20
+ return undefined;
21
+ }
22
+ export function createSemanticScholarProvider() {
23
+ return {
24
+ id: 'semanticScholar',
25
+ kind: 'free',
26
+ async search(query, opts = {}) {
27
+ const limit = Math.min(Math.max(opts.limit ?? 8, 1), MAX_RESULTS);
28
+ const params = new URLSearchParams({
29
+ query,
30
+ limit: String(limit),
31
+ fields: 'title,abstract,url,year,openAccessPdf,externalIds',
32
+ });
33
+ const url = `https://api.semanticscholar.org/graph/v1/paper/search?${params.toString()}`;
34
+ const raw = await withRetry(() => fetchJson(url, { signal: opts.signal, timeoutMs: 15_000 }));
35
+ const body = raw;
36
+ const results = [];
37
+ for (const paper of body.data ?? []) {
38
+ const paperUrl_ = paperUrl(paper);
39
+ if (paperUrl_ === undefined || paper.title === undefined)
40
+ continue;
41
+ results.push({
42
+ title: paper.title,
43
+ url: paperUrl_,
44
+ snippet: truncate(paper.abstract ?? '', 300),
45
+ source: 'semanticScholar',
46
+ publishedAt: paper.year !== null && paper.year !== undefined
47
+ ? `${paper.year}-01-01`
48
+ : undefined,
49
+ });
50
+ if (results.length >= limit)
51
+ break;
52
+ }
53
+ return results;
54
+ },
55
+ };
56
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Tavily search adapter (paid, API key required).
3
+ *
4
+ * Wraps the Tavily Search API via POST. The key travels in the
5
+ * `Authorization: Bearer` header — never in the URL, never logged.
6
+ */
7
+ import type { ResearchProvider } from '../types.js';
8
+ export interface TavilyProviderOptions {
9
+ readonly apiKey: string;
10
+ }
11
+ export declare function createTavilyProvider(options: TavilyProviderOptions): ResearchProvider;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Tavily search adapter (paid, API key required).
3
+ *
4
+ * Wraps the Tavily Search API via POST. The key travels in the
5
+ * `Authorization: Bearer` header — never in the URL, never logged.
6
+ */
7
+ import { postJson, truncate, withRetry } from '../http.js';
8
+ const MAX_RESULTS = 20;
9
+ export function createTavilyProvider(options) {
10
+ return {
11
+ id: 'tavily',
12
+ kind: 'paid',
13
+ async search(query, opts = {}) {
14
+ const limit = Math.min(Math.max(opts.limit ?? 8, 1), MAX_RESULTS);
15
+ const raw = await withRetry(() => postJson('https://api.tavily.com/search', {
16
+ query,
17
+ max_results: limit,
18
+ include_answer: false,
19
+ search_depth: 'advanced',
20
+ }, {
21
+ signal: opts.signal,
22
+ timeoutMs: 20_000,
23
+ headers: { Authorization: `Bearer ${options.apiKey}` },
24
+ }));
25
+ const body = raw;
26
+ return (body.results ?? []).slice(0, limit).map((hit) => ({
27
+ title: hit.title ?? '',
28
+ url: hit.url ?? '',
29
+ snippet: truncate(hit.content ?? '', 300),
30
+ source: 'tavily',
31
+ publishedAt: hit.published_date,
32
+ }));
33
+ },
34
+ };
35
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Wikipedia search provider (free, no key).
3
+ *
4
+ * Uses the MediaWiki `action=query&list=search` API. Result URLs are built
5
+ * from page ids (`https://<lang>.wikipedia.org/?curid=<pageid>`).
6
+ */
7
+ import type { ResearchProvider } from '../types.js';
8
+ export interface WikipediaProviderOptions {
9
+ /** Wikipedia language subdomain. Default `'en'`. */
10
+ readonly lang?: string;
11
+ }
12
+ export declare function createWikipediaProvider(options?: WikipediaProviderOptions): ResearchProvider;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Wikipedia search provider (free, no key).
3
+ *
4
+ * Uses the MediaWiki `action=query&list=search` API. Result URLs are built
5
+ * from page ids (`https://<lang>.wikipedia.org/?curid=<pageid>`).
6
+ */
7
+ import { fetchJson, truncate, withRetry } from '../http.js';
8
+ const DEFAULT_LANG = 'en';
9
+ const MAX_RESULTS = 20;
10
+ function stripTags(html) {
11
+ return html
12
+ .replace(/<[^>]*>/g, '')
13
+ .replace(/&amp;/g, '&')
14
+ .replace(/&lt;/g, '<')
15
+ .replace(/&gt;/g, '>')
16
+ .replace(/&quot;/g, '"')
17
+ .replace(/&#39;/g, "'")
18
+ .trim();
19
+ }
20
+ export function createWikipediaProvider(options = {}) {
21
+ const lang = options.lang ?? DEFAULT_LANG;
22
+ return {
23
+ id: 'wikipedia',
24
+ kind: 'free',
25
+ async search(query, opts = {}) {
26
+ const limit = Math.min(Math.max(opts.limit ?? 8, 1), MAX_RESULTS);
27
+ const params = new URLSearchParams({
28
+ action: 'query',
29
+ list: 'search',
30
+ srsearch: query,
31
+ srlimit: String(limit),
32
+ format: 'json',
33
+ srprop: 'snippet',
34
+ });
35
+ const url = `https://${lang}.wikipedia.org/w/api.php?${params.toString()}`;
36
+ const raw = await withRetry(() => fetchJson(url, { signal: opts.signal, timeoutMs: 2_500 }));
37
+ const body = raw;
38
+ const hits = body.query?.search ?? [];
39
+ return hits.slice(0, limit).map((hit) => ({
40
+ title: hit.title ?? '',
41
+ url: `https://${lang}.wikipedia.org/?curid=${hit.pageid ?? 0}`,
42
+ snippet: truncate(stripTags(hit.snippet ?? ''), 300),
43
+ source: 'wikipedia',
44
+ }));
45
+ },
46
+ };
47
+ }