@poolzin/pool-bot 2026.1.39 → 2026.2.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 (511) hide show
  1. package/assets/chrome-extension/README.md +3 -3
  2. package/assets/chrome-extension/background.js +5 -5
  3. package/assets/chrome-extension/manifest.json +3 -3
  4. package/assets/chrome-extension/options.html +4 -4
  5. package/assets/chrome-extension/options.js +1 -1
  6. package/dist/acp/client.js +3 -3
  7. package/dist/acp/types.js +1 -1
  8. package/dist/agents/agent-paths.js +3 -3
  9. package/dist/agents/auth-profiles/paths.js +3 -3
  10. package/dist/agents/bash-tools.exec.js +76 -25
  11. package/dist/agents/cli-runner/helpers.js +10 -12
  12. package/dist/agents/cli-runner.js +2 -2
  13. package/dist/agents/cloudflare-ai-gateway.js +31 -0
  14. package/dist/agents/compaction.js +16 -2
  15. package/dist/agents/context-window-guard.js +13 -10
  16. package/dist/agents/context.js +4 -4
  17. package/dist/agents/docs-path.js +1 -1
  18. package/dist/agents/identity.js +47 -7
  19. package/dist/agents/memory-search.js +25 -8
  20. package/dist/agents/minimax-vlm.js +1 -1
  21. package/dist/agents/model-auth.js +12 -1
  22. package/dist/agents/model-catalog.js +4 -4
  23. package/dist/agents/model-selection.js +31 -4
  24. package/dist/agents/models-config.js +3 -3
  25. package/dist/agents/models-config.providers.js +147 -39
  26. package/dist/agents/pi-embedded-block-chunker.js +117 -42
  27. package/dist/agents/pi-embedded-helpers/errors.js +183 -78
  28. package/dist/agents/pi-embedded-helpers/openai.js +1 -1
  29. package/dist/agents/pi-embedded-helpers.js +1 -1
  30. package/dist/agents/pi-embedded-runner/compact.js +9 -8
  31. package/dist/agents/pi-embedded-runner/model.js +63 -4
  32. package/dist/agents/pi-embedded-runner/run/attempt.js +27 -17
  33. package/dist/agents/pi-embedded-runner/run.js +203 -50
  34. package/dist/agents/pi-embedded-runner/system-prompt.js +10 -2
  35. package/dist/agents/pi-embedded-runner/tool-result-truncation.js +275 -0
  36. package/dist/agents/pi-embedded-runner/utils.js +1 -1
  37. package/dist/agents/pi-embedded-subscribe.js +118 -29
  38. package/dist/agents/pi-model-discovery.js +10 -0
  39. package/dist/agents/pi-tool-definition-adapter.js +50 -9
  40. package/dist/agents/pi-tools.before-tool-call.js +67 -0
  41. package/dist/agents/pi-tools.js +20 -10
  42. package/dist/agents/pi-tools.read.js +2 -2
  43. package/dist/agents/poolbot-tools.js +15 -10
  44. package/dist/agents/sandbox-paths.js +31 -0
  45. package/dist/agents/session-file-repair.js +83 -0
  46. package/dist/agents/session-tool-result-guard.js +94 -15
  47. package/dist/agents/session-transcript-repair.js +68 -0
  48. package/dist/agents/shell-utils.js +51 -0
  49. package/dist/agents/skills/bundled-context.js +23 -0
  50. package/dist/agents/skills/bundled-dir.js +41 -7
  51. package/dist/agents/skills/frontmatter.js +1 -1
  52. package/dist/agents/skills/workspace.js +2 -2
  53. package/dist/agents/skills-install.js +60 -23
  54. package/dist/agents/subagent-announce.js +79 -34
  55. package/dist/agents/system-prompt.js +28 -4
  56. package/dist/agents/together-models.js +127 -0
  57. package/dist/agents/tool-images.js +1 -1
  58. package/dist/agents/tool-policy.conformance.js +14 -0
  59. package/dist/agents/tool-policy.js +25 -1
  60. package/dist/agents/tools/browser-tool.js +3 -3
  61. package/dist/agents/tools/cron-tool.js +166 -19
  62. package/dist/agents/tools/discord-actions-presence.js +78 -0
  63. package/dist/agents/tools/image-tool.js +2 -2
  64. package/dist/agents/tools/memory-tool.js +93 -5
  65. package/dist/agents/tools/message-tool.js +56 -2
  66. package/dist/agents/tools/sessions-history-tool.js +69 -1
  67. package/dist/agents/tools/web-search.js +211 -42
  68. package/dist/agents/usage.js +23 -1
  69. package/dist/agents/workspace-run.js +67 -0
  70. package/dist/agents/workspace-templates.js +44 -0
  71. package/dist/auto-reply/command-auth.js +121 -6
  72. package/dist/auto-reply/commands-registry.data.js +1 -1
  73. package/dist/auto-reply/envelope.js +50 -72
  74. package/dist/auto-reply/reply/commands-compact.js +1 -0
  75. package/dist/auto-reply/reply/commands-context-report.js +3 -2
  76. package/dist/auto-reply/reply/commands-context.js +1 -0
  77. package/dist/auto-reply/reply/commands-models.js +107 -60
  78. package/dist/auto-reply/reply/commands-ptt.js +171 -0
  79. package/dist/auto-reply/reply/commands-session.js +2 -2
  80. package/dist/auto-reply/reply/get-reply-run.js +16 -5
  81. package/dist/auto-reply/reply/groups.js +1 -1
  82. package/dist/auto-reply/reply/inbound-context.js +9 -1
  83. package/dist/auto-reply/reply/inbound-meta.js +130 -0
  84. package/dist/auto-reply/reply/model-selection.js +3 -3
  85. package/dist/auto-reply/reply/untrusted-context.js +15 -0
  86. package/dist/auto-reply/status.js +1 -1
  87. package/dist/auto-reply/thinking.js +88 -43
  88. package/dist/browser/bridge-server.js +13 -0
  89. package/dist/browser/cdp.helpers.js +38 -24
  90. package/dist/browser/client-fetch.js +51 -8
  91. package/dist/browser/config.js +2 -11
  92. package/dist/browser/extension-relay.js +104 -43
  93. package/dist/browser/pw-ai.js +1 -1
  94. package/dist/browser/pw-session.js +143 -8
  95. package/dist/browser/pw-tools-core.interactions.js +125 -27
  96. package/dist/browser/pw-tools-core.responses.js +1 -1
  97. package/dist/browser/pw-tools-core.state.js +1 -1
  98. package/dist/browser/routes/agent.act.js +86 -41
  99. package/dist/browser/routes/dispatcher.js +4 -4
  100. package/dist/browser/screenshot.js +1 -1
  101. package/dist/browser/server-context.js +2 -2
  102. package/dist/browser/server.js +13 -0
  103. package/dist/build-info.json +3 -3
  104. package/dist/canvas-host/a2ui.js +3 -3
  105. package/dist/channels/plugins/catalog.js +2 -2
  106. package/dist/channels/plugins/onboarding/imessage.js +1 -1
  107. package/dist/channels/plugins/onboarding/signal.js +1 -1
  108. package/dist/channels/plugins/onboarding/slack.js +4 -4
  109. package/dist/channels/plugins/onboarding/whatsapp.js +3 -3
  110. package/dist/channels/plugins/pairing-message.js +1 -1
  111. package/dist/channels/reply-prefix.js +8 -1
  112. package/dist/cli/browser-cli-extension.js +2 -2
  113. package/dist/cli/cron-cli/register.cron-add.js +61 -40
  114. package/dist/cli/cron-cli/register.cron-edit.js +60 -34
  115. package/dist/cli/cron-cli/shared.js +56 -41
  116. package/dist/cli/dns-cli.js +26 -14
  117. package/dist/cli/docs-cli.js +1 -1
  118. package/dist/cli/gateway-cli/dev.js +1 -1
  119. package/dist/cli/gateway-cli/register.js +37 -19
  120. package/dist/cli/memory-cli.js +30 -20
  121. package/dist/cli/nodes-cli/register.canvas.js +1 -1
  122. package/dist/cli/parse-bytes.js +37 -0
  123. package/dist/cli/plugins-cli.js +1 -1
  124. package/dist/cli/run-main.js +2 -2
  125. package/dist/cli/security-cli.js +1 -1
  126. package/dist/cli/tagline.js +1 -1
  127. package/dist/cli/update-cli.js +173 -52
  128. package/dist/cli/webhooks-cli.js +5 -5
  129. package/dist/commands/agent.js +1 -0
  130. package/dist/commands/agents.commands.add.js +1 -1
  131. package/dist/commands/auth-choice.apply.api-providers.js +305 -17
  132. package/dist/commands/auth-choice.apply.js +4 -1
  133. package/dist/commands/auth-choice.apply.plugin-provider.js +2 -2
  134. package/dist/commands/auth-choice.apply.xai.js +63 -0
  135. package/dist/commands/auth-choice.preferred-provider.js +7 -1
  136. package/dist/commands/configure.wizard.js +1 -1
  137. package/dist/commands/dashboard.js +1 -1
  138. package/dist/commands/docs.js +1 -1
  139. package/dist/commands/doctor-config-flow.js +61 -5
  140. package/dist/commands/doctor-gateway-services.js +3 -3
  141. package/dist/commands/doctor-state-migrations.js +1 -1
  142. package/dist/commands/doctor-update.js +3 -3
  143. package/dist/commands/doctor.js +1 -1
  144. package/dist/commands/health.js +1 -1
  145. package/dist/commands/model-allowlist.js +29 -0
  146. package/dist/commands/model-picker.js +2 -1
  147. package/dist/commands/models/list.probe.js +2 -2
  148. package/dist/commands/models/list.registry.js +4 -4
  149. package/dist/commands/models/list.status-command.js +44 -24
  150. package/dist/commands/models/shared.js +15 -0
  151. package/dist/commands/onboard-auth.config-core.js +366 -28
  152. package/dist/commands/onboard-auth.credentials.js +71 -9
  153. package/dist/commands/onboard-auth.js +3 -3
  154. package/dist/commands/onboard-auth.models.js +26 -24
  155. package/dist/commands/onboard-custom.js +384 -0
  156. package/dist/commands/onboard-non-interactive/local/auth-choice-inference.js +35 -0
  157. package/dist/commands/onboard-non-interactive/local/auth-choice.js +146 -9
  158. package/dist/commands/onboard-skills.js +63 -38
  159. package/dist/commands/openai-model-default.js +41 -0
  160. package/dist/commands/status-all/report-lines.js +1 -1
  161. package/dist/commands/status.command.js +1 -1
  162. package/dist/commands/uninstall.js +3 -3
  163. package/dist/compat/legacy-names.js +1 -1
  164. package/dist/config/defaults.js +3 -2
  165. package/dist/config/io.js +3 -3
  166. package/dist/config/paths.js +136 -35
  167. package/dist/config/plugin-auto-enable.js +21 -5
  168. package/dist/config/redact-snapshot.js +153 -0
  169. package/dist/config/schema.field-metadata.js +590 -0
  170. package/dist/config/schema.js +3 -3
  171. package/dist/config/sessions/store.js +291 -23
  172. package/dist/config/types.memory.js +1 -0
  173. package/dist/config/version.js +4 -4
  174. package/dist/config/zod-schema.agent-defaults.js +3 -0
  175. package/dist/config/zod-schema.agent-runtime.js +13 -2
  176. package/dist/config/zod-schema.providers-core.js +142 -0
  177. package/dist/config/zod-schema.session.js +3 -0
  178. package/dist/cron/delivery.js +57 -0
  179. package/dist/cron/isolated-agent/delivery-target.js +18 -3
  180. package/dist/cron/isolated-agent/helpers.js +22 -5
  181. package/dist/cron/isolated-agent/run.js +171 -63
  182. package/dist/cron/isolated-agent/session.js +2 -0
  183. package/dist/cron/normalize.js +356 -28
  184. package/dist/cron/parse.js +10 -5
  185. package/dist/cron/run-log.js +35 -10
  186. package/dist/cron/schedule.js +41 -6
  187. package/dist/cron/service/jobs.js +208 -35
  188. package/dist/cron/service/ops.js +72 -16
  189. package/dist/cron/service/state.js +2 -0
  190. package/dist/cron/service/store.js +386 -14
  191. package/dist/cron/service/timer.js +390 -147
  192. package/dist/cron/session-reaper.js +86 -0
  193. package/dist/cron/store.js +23 -8
  194. package/dist/cron/validate-timestamp.js +43 -0
  195. package/dist/daemon/constants.js +7 -7
  196. package/dist/daemon/inspect.js +6 -6
  197. package/dist/daemon/systemd-unit.js +1 -1
  198. package/dist/discord/monitor/agent-components.js +438 -0
  199. package/dist/discord/monitor/allow-list.js +28 -5
  200. package/dist/discord/monitor/gateway-registry.js +29 -0
  201. package/dist/discord/monitor/native-command.js +44 -23
  202. package/dist/discord/monitor/sender-identity.js +45 -0
  203. package/dist/discord/pluralkit.js +27 -0
  204. package/dist/discord/send.outbound.js +92 -5
  205. package/dist/discord/send.shared.js +60 -23
  206. package/dist/discord/targets.js +84 -1
  207. package/dist/entry.js +15 -9
  208. package/dist/extensionAPI.js +8 -0
  209. package/dist/gateway/control-ui.js +8 -1
  210. package/dist/gateway/hooks-mapping.js +3 -0
  211. package/dist/gateway/hooks.js +65 -0
  212. package/dist/gateway/live-image-probe.js +1 -66
  213. package/dist/gateway/net.js +96 -31
  214. package/dist/gateway/node-command-policy.js +50 -15
  215. package/dist/gateway/openai-http.js +2 -2
  216. package/dist/gateway/openresponses-http.js +4 -4
  217. package/dist/gateway/origin-check.js +56 -0
  218. package/dist/gateway/protocol/client-info.js +9 -0
  219. package/dist/gateway/protocol/index.js +9 -2
  220. package/dist/gateway/protocol/schema/agents-models-skills.js +71 -1
  221. package/dist/gateway/protocol/schema/cron.js +22 -10
  222. package/dist/gateway/protocol/schema/protocol-schemas.js +16 -2
  223. package/dist/gateway/protocol/schema/sessions.js +12 -0
  224. package/dist/gateway/server/hooks.js +1 -1
  225. package/dist/gateway/server-broadcast.js +26 -9
  226. package/dist/gateway/server-chat.js +112 -23
  227. package/dist/gateway/server-discovery-runtime.js +10 -2
  228. package/dist/gateway/server-discovery.js +2 -2
  229. package/dist/gateway/server-http.js +110 -12
  230. package/dist/gateway/server-methods/agent-timestamp.js +60 -0
  231. package/dist/gateway/server-methods/agents.js +321 -2
  232. package/dist/gateway/server-methods/usage.js +559 -16
  233. package/dist/gateway/server-runtime-state.js +22 -8
  234. package/dist/gateway/server-startup-memory.js +16 -0
  235. package/dist/gateway/server.impl.js +7 -3
  236. package/dist/gateway/session-utils.fs.js +23 -25
  237. package/dist/gateway/session-utils.js +20 -10
  238. package/dist/gateway/sessions-patch.js +7 -22
  239. package/dist/gateway/test-helpers.server.js +35 -2
  240. package/dist/hooks/frontmatter.js +1 -1
  241. package/dist/hooks/hooks-status.js +1 -1
  242. package/dist/hooks/install.js +2 -2
  243. package/dist/hooks/loader.js +1 -1
  244. package/dist/hooks/workspace.js +3 -3
  245. package/dist/imessage/constants.js +2 -0
  246. package/dist/imessage/monitor/deliver.js +4 -1
  247. package/dist/imessage/monitor/monitor-provider.js +51 -1
  248. package/dist/index.js +2 -2
  249. package/dist/infra/bonjour-discovery.js +131 -70
  250. package/dist/infra/bonjour.js +3 -3
  251. package/dist/infra/control-ui-assets.js +134 -12
  252. package/dist/infra/errors.js +12 -0
  253. package/dist/infra/exec-approvals.js +266 -57
  254. package/dist/infra/format-time/format-datetime.js +79 -0
  255. package/dist/infra/format-time/format-duration.js +81 -0
  256. package/dist/infra/format-time/format-relative.js +80 -0
  257. package/dist/infra/heartbeat-runner.js +140 -49
  258. package/dist/infra/home-dir.js +54 -0
  259. package/dist/infra/net/fetch-guard.js +122 -0
  260. package/dist/infra/net/ssrf.js +65 -29
  261. package/dist/infra/outbound/abort.js +14 -0
  262. package/dist/infra/outbound/message-action-runner.js +77 -13
  263. package/dist/infra/outbound/outbound-session.js +143 -37
  264. package/dist/infra/path-env.js +3 -3
  265. package/dist/infra/poolbot-root.js +43 -1
  266. package/dist/infra/provider-usage.fetch.minimax.js +1 -1
  267. package/dist/infra/restart.js +1 -1
  268. package/dist/infra/session-cost-usage.js +631 -41
  269. package/dist/infra/state-migrations.js +317 -47
  270. package/dist/infra/tailscale.js +1 -1
  271. package/dist/infra/update-global.js +35 -0
  272. package/dist/infra/update-runner.js +149 -43
  273. package/dist/infra/warning-filter.js +65 -0
  274. package/dist/infra/widearea-dns.js +30 -9
  275. package/dist/logging/redact-identifier.js +12 -0
  276. package/dist/macos/relay.js +2 -2
  277. package/dist/media/fetch.js +81 -58
  278. package/dist/media/input-files.js +1 -1
  279. package/dist/media/mime.js +4 -0
  280. package/dist/media/png-encode.js +74 -0
  281. package/dist/media-understanding/apply.js +403 -3
  282. package/dist/media-understanding/attachments.js +38 -27
  283. package/dist/media-understanding/defaults.js +16 -0
  284. package/dist/media-understanding/providers/deepgram/audio.js +22 -14
  285. package/dist/media-understanding/providers/google/audio.js +24 -17
  286. package/dist/media-understanding/providers/google/video.js +24 -17
  287. package/dist/media-understanding/providers/image.js +4 -4
  288. package/dist/media-understanding/providers/index.js +4 -1
  289. package/dist/media-understanding/providers/openai/audio.js +22 -14
  290. package/dist/media-understanding/providers/shared.js +16 -11
  291. package/dist/media-understanding/providers/zai/index.js +6 -0
  292. package/dist/media-understanding/runner.js +158 -90
  293. package/dist/memory/backend-config.js +207 -0
  294. package/dist/memory/batch-voyage.js +277 -0
  295. package/dist/memory/embeddings-voyage.js +75 -0
  296. package/dist/memory/embeddings.js +29 -17
  297. package/dist/memory/internal.js +101 -18
  298. package/dist/memory/manager.js +155 -48
  299. package/dist/memory/search-manager.js +173 -0
  300. package/dist/memory/session-files.js +9 -3
  301. package/dist/memory/types.js +1 -0
  302. package/dist/node-host/runner.js +36 -26
  303. package/dist/node-host/with-timeout.js +27 -0
  304. package/dist/pairing/pairing-messages.js +1 -1
  305. package/dist/plugins/commands.js +5 -1
  306. package/dist/plugins/config-state.js +86 -7
  307. package/dist/plugins/discovery.js +1 -1
  308. package/dist/plugins/install.js +2 -2
  309. package/dist/plugins/source-display.js +51 -0
  310. package/dist/plugins/update.js +1 -1
  311. package/dist/process/exec.js +20 -2
  312. package/dist/routing/resolve-route.js +12 -0
  313. package/dist/routing/session-key.js +15 -0
  314. package/dist/runtime.js +2 -0
  315. package/dist/security/audit-extra.async.js +601 -0
  316. package/dist/security/audit-extra.js +2 -830
  317. package/dist/security/audit-extra.sync.js +505 -0
  318. package/dist/security/audit.js +2 -2
  319. package/dist/security/channel-metadata.js +34 -0
  320. package/dist/security/external-content.js +88 -6
  321. package/dist/security/skill-scanner.js +330 -0
  322. package/dist/sessions/session-key-utils.js +7 -0
  323. package/dist/shared/text/reasoning-tags.js +52 -7
  324. package/dist/signal/monitor/event-handler.js +80 -1
  325. package/dist/slack/monitor/media.js +85 -15
  326. package/dist/tailscale/detect.js +145 -0
  327. package/dist/telegram/bot/helpers.js +109 -28
  328. package/dist/telegram/bot-handlers.js +144 -3
  329. package/dist/telegram/bot-message-context.js +38 -11
  330. package/dist/telegram/bot-message-dispatch.js +48 -15
  331. package/dist/telegram/bot-native-commands.js +86 -29
  332. package/dist/telegram/bot.js +30 -29
  333. package/dist/telegram/model-buttons.js +163 -0
  334. package/dist/telegram/monitor.js +110 -85
  335. package/dist/telegram/send.js +129 -47
  336. package/dist/terminal/restore.js +45 -0
  337. package/dist/test-helpers/state-dir-env.js +16 -0
  338. package/dist/test-helpers/workspace.js +11 -0
  339. package/dist/test-utils/channel-plugins.js +82 -0
  340. package/dist/test-utils/ports.js +73 -0
  341. package/dist/tts/tts.js +12 -6
  342. package/dist/tui/tui-session-actions.js +166 -54
  343. package/dist/utils/fetch-timeout.js +20 -0
  344. package/dist/utils/normalize-secret-input.js +19 -0
  345. package/dist/utils/shell-argv.js +61 -0
  346. package/dist/utils/transcript-tools.js +58 -0
  347. package/dist/utils.js +55 -14
  348. package/dist/version.js +42 -5
  349. package/dist/web/qr-image.js +1 -61
  350. package/dist/wizard/onboarding.finalize.js +7 -7
  351. package/dist/wizard/onboarding.js +3 -3
  352. package/docs/RELEASE_WORKFOTS_COMPARISON.md +3 -3
  353. package/docs/_config.yml +2 -2
  354. package/docs/_layouts/default.html +9 -9
  355. package/docs/concepts/typebox.md +1 -1
  356. package/docs/docs.json +1 -1
  357. package/docs/northflank.mdx +7 -7
  358. package/docs/railway.mdx +3 -3
  359. package/docs/render.mdx +5 -5
  360. package/docs/start/lore.md +2 -2
  361. package/extensions/bluebubbles/index.ts +2 -2
  362. package/extensions/bluebubbles/package.json +1 -1
  363. package/extensions/bluebubbles/src/accounts.ts +8 -8
  364. package/extensions/bluebubbles/src/actions.test.ts +22 -22
  365. package/extensions/bluebubbles/src/actions.ts +5 -5
  366. package/extensions/bluebubbles/src/attachments.ts +2 -2
  367. package/extensions/bluebubbles/src/channel.ts +16 -16
  368. package/extensions/bluebubbles/src/chat.ts +2 -2
  369. package/extensions/bluebubbles/src/media-send.ts +2 -2
  370. package/extensions/bluebubbles/src/monitor.test.ts +46 -46
  371. package/extensions/bluebubbles/src/monitor.ts +5 -5
  372. package/extensions/bluebubbles/src/onboarding.ts +7 -7
  373. package/extensions/bluebubbles/src/reactions.ts +2 -2
  374. package/extensions/bluebubbles/src/send.ts +2 -2
  375. package/extensions/copilot-proxy/README.md +1 -1
  376. package/extensions/copilot-proxy/package.json +1 -1
  377. package/extensions/diagnostics-otel/index.ts +2 -2
  378. package/extensions/diagnostics-otel/package.json +1 -1
  379. package/extensions/diagnostics-otel/src/service.ts +3 -3
  380. package/extensions/discord/index.ts +2 -2
  381. package/extensions/discord/package.json +1 -1
  382. package/extensions/google-antigravity-auth/README.md +1 -1
  383. package/extensions/google-antigravity-auth/index.ts +1 -1
  384. package/extensions/google-antigravity-auth/package.json +1 -1
  385. package/extensions/google-gemini-cli-auth/README.md +1 -1
  386. package/extensions/google-gemini-cli-auth/oauth.ts +1 -1
  387. package/extensions/google-gemini-cli-auth/package.json +1 -1
  388. package/extensions/googlechat/index.ts +3 -3
  389. package/extensions/googlechat/package.json +1 -1
  390. package/extensions/googlechat/src/accounts.ts +8 -8
  391. package/extensions/googlechat/src/actions.ts +6 -6
  392. package/extensions/googlechat/src/channel.ts +21 -21
  393. package/extensions/googlechat/src/monitor.ts +8 -8
  394. package/extensions/googlechat/src/onboarding.ts +10 -10
  395. package/extensions/imessage/index.ts +2 -2
  396. package/extensions/imessage/package.json +1 -1
  397. package/extensions/line/index.ts +2 -2
  398. package/extensions/line/package.json +1 -1
  399. package/extensions/line/src/card-command.ts +2 -2
  400. package/extensions/line/src/channel.logout.test.ts +4 -4
  401. package/extensions/line/src/channel.sendPayload.test.ts +8 -8
  402. package/extensions/line/src/channel.ts +3 -3
  403. package/extensions/llm-task/README.md +3 -3
  404. package/extensions/llm-task/index.ts +2 -2
  405. package/extensions/llm-task/package.json +1 -1
  406. package/extensions/llm-task/src/llm-task-tool.ts +4 -4
  407. package/extensions/lobster/README.md +6 -6
  408. package/extensions/lobster/index.ts +2 -2
  409. package/extensions/lobster/src/lobster-tool.test.ts +4 -4
  410. package/extensions/lobster/src/lobster-tool.ts +2 -2
  411. package/extensions/matrix/index.ts +2 -2
  412. package/extensions/matrix/package.json +1 -1
  413. package/extensions/matrix/src/matrix/client/config.ts +1 -1
  414. package/extensions/matrix/src/matrix/monitor/handler.ts +1 -1
  415. package/extensions/matrix/src/onboarding.ts +1 -1
  416. package/extensions/mattermost/index.ts +2 -2
  417. package/extensions/mattermost/package.json +1 -1
  418. package/extensions/mattermost/src/mattermost/accounts.ts +8 -8
  419. package/extensions/mattermost/src/mattermost/monitor-helpers.ts +5 -5
  420. package/extensions/mattermost/src/mattermost/monitor.ts +2 -2
  421. package/extensions/mattermost/src/onboarding-helpers.ts +3 -3
  422. package/extensions/mattermost/src/onboarding.ts +2 -2
  423. package/extensions/memory-core/index.ts +2 -2
  424. package/extensions/memory-core/package.json +1 -1
  425. package/extensions/memory-lancedb/index.ts +3 -3
  426. package/extensions/memory-lancedb/package.json +1 -1
  427. package/extensions/msteams/index.ts +2 -2
  428. package/extensions/msteams/package.json +1 -1
  429. package/extensions/msteams/src/channel.directory.test.ts +2 -2
  430. package/extensions/msteams/src/channel.ts +2 -2
  431. package/extensions/msteams/src/graph-upload.ts +4 -4
  432. package/extensions/msteams/src/monitor-handler.ts +2 -2
  433. package/extensions/msteams/src/monitor.ts +2 -2
  434. package/extensions/msteams/src/onboarding.ts +9 -9
  435. package/extensions/msteams/src/reply-dispatcher.ts +2 -2
  436. package/extensions/msteams/src/send-context.ts +2 -2
  437. package/extensions/msteams/src/send.ts +4 -4
  438. package/extensions/nextcloud-talk/index.ts +2 -2
  439. package/extensions/nextcloud-talk/package.json +1 -1
  440. package/extensions/nextcloud-talk/src/channel.ts +7 -7
  441. package/extensions/nextcloud-talk/src/inbound.ts +7 -7
  442. package/extensions/nextcloud-talk/src/onboarding.ts +1 -1
  443. package/extensions/nostr/README.md +2 -2
  444. package/extensions/nostr/index.ts +5 -5
  445. package/extensions/nostr/package.json +1 -1
  446. package/extensions/nostr/src/types.ts +4 -4
  447. package/extensions/open-prose/index.ts +2 -2
  448. package/extensions/qwen-portal-auth/README.md +1 -1
  449. package/extensions/signal/index.ts +2 -2
  450. package/extensions/signal/package.json +1 -1
  451. package/extensions/slack/index.ts +2 -2
  452. package/extensions/slack/package.json +1 -1
  453. package/extensions/telegram/index.ts +2 -2
  454. package/extensions/telegram/package.json +1 -1
  455. package/extensions/telegram/src/channel.ts +2 -2
  456. package/extensions/tlon/README.md +2 -2
  457. package/extensions/tlon/index.ts +2 -2
  458. package/extensions/tlon/package.json +1 -1
  459. package/extensions/tlon/src/channel.ts +13 -13
  460. package/extensions/tlon/src/monitor/index.ts +3 -3
  461. package/extensions/tlon/src/onboarding.ts +3 -3
  462. package/extensions/tlon/src/types.ts +3 -3
  463. package/extensions/twitch/README.md +1 -1
  464. package/extensions/twitch/index.ts +2 -2
  465. package/extensions/twitch/package.json +1 -1
  466. package/extensions/twitch/src/config.ts +3 -3
  467. package/extensions/twitch/src/monitor.ts +3 -3
  468. package/extensions/twitch/src/onboarding.ts +9 -9
  469. package/extensions/twitch/src/outbound.test.ts +2 -2
  470. package/extensions/twitch/src/plugin.test.ts +2 -2
  471. package/extensions/twitch/src/plugin.ts +8 -8
  472. package/extensions/twitch/src/send.test.ts +2 -2
  473. package/extensions/twitch/src/send.ts +4 -4
  474. package/extensions/twitch/src/token.test.ts +8 -8
  475. package/extensions/twitch/src/token.ts +3 -3
  476. package/extensions/twitch/src/twitch-client.ts +3 -3
  477. package/extensions/twitch/src/types.ts +3 -3
  478. package/extensions/twitch/src/utils/markdown.ts +1 -1
  479. package/extensions/voice-call/README.md +3 -3
  480. package/extensions/voice-call/package.json +1 -1
  481. package/extensions/voice-call/src/core-bridge.ts +2 -2
  482. package/extensions/voice-call/src/response-generator.ts +1 -1
  483. package/extensions/whatsapp/index.ts +2 -2
  484. package/extensions/whatsapp/package.json +1 -1
  485. package/extensions/zalo/README.md +1 -1
  486. package/extensions/zalo/index.ts +2 -2
  487. package/extensions/zalo/package.json +1 -1
  488. package/extensions/zalo/src/accounts.ts +8 -8
  489. package/extensions/zalo/src/actions.ts +4 -4
  490. package/extensions/zalo/src/channel.directory.test.ts +2 -2
  491. package/extensions/zalo/src/channel.ts +18 -18
  492. package/extensions/zalo/src/monitor.ts +9 -9
  493. package/extensions/zalo/src/monitor.webhook.test.ts +2 -2
  494. package/extensions/zalo/src/onboarding.ts +24 -24
  495. package/extensions/zalo/src/send.ts +2 -2
  496. package/extensions/zalouser/README.md +2 -2
  497. package/extensions/zalouser/index.ts +2 -2
  498. package/extensions/zalouser/package.json +1 -1
  499. package/extensions/zalouser/src/accounts.ts +9 -9
  500. package/extensions/zalouser/src/channel.ts +24 -24
  501. package/extensions/zalouser/src/monitor.ts +4 -4
  502. package/extensions/zalouser/src/onboarding.ts +28 -28
  503. package/package.json +13 -251
  504. package/skills/nano-banana-pro/scripts/generate_image.py +1 -1
  505. package/skills/tmux/scripts/find-sessions.sh +1 -1
  506. package/CHANGELOG.md +0 -102
  507. package/README-header.png +0 -0
  508. package/git-hooks/pre-commit +0 -4
  509. package/scripts/format-staged.js +0 -148
  510. package/scripts/postinstall.js +0 -300
  511. package/scripts/setup-git-hooks.js +0 -96
@@ -0,0 +1,207 @@
1
+ import path from "node:path";
2
+ import { resolveAgentWorkspaceDir } from "../agents/agent-scope.js";
3
+ import { parseDurationMs } from "../cli/parse-duration.js";
4
+ import { resolveUserPath } from "../utils.js";
5
+ import { splitShellArgs } from "../utils/shell-argv.js";
6
+ const DEFAULT_BACKEND = "builtin";
7
+ const DEFAULT_CITATIONS = "auto";
8
+ const DEFAULT_QMD_INTERVAL = "5m";
9
+ const DEFAULT_QMD_DEBOUNCE_MS = 15_000;
10
+ const DEFAULT_QMD_TIMEOUT_MS = 4_000;
11
+ const DEFAULT_QMD_EMBED_INTERVAL = "60m";
12
+ const DEFAULT_QMD_COMMAND_TIMEOUT_MS = 30_000;
13
+ const DEFAULT_QMD_UPDATE_TIMEOUT_MS = 120_000;
14
+ const DEFAULT_QMD_EMBED_TIMEOUT_MS = 120_000;
15
+ const DEFAULT_QMD_LIMITS = {
16
+ maxResults: 6,
17
+ maxSnippetChars: 700,
18
+ maxInjectedChars: 4_000,
19
+ timeoutMs: DEFAULT_QMD_TIMEOUT_MS,
20
+ };
21
+ const DEFAULT_QMD_SCOPE = {
22
+ default: "deny",
23
+ rules: [
24
+ {
25
+ action: "allow",
26
+ match: { chatType: "direct" },
27
+ },
28
+ ],
29
+ };
30
+ function sanitizeName(input) {
31
+ const lower = input.toLowerCase().replace(/[^a-z0-9-]+/g, "-");
32
+ const trimmed = lower.replace(/^-+|-+$/g, "");
33
+ return trimmed || "collection";
34
+ }
35
+ function ensureUniqueName(base, existing) {
36
+ let name = sanitizeName(base);
37
+ if (!existing.has(name)) {
38
+ existing.add(name);
39
+ return name;
40
+ }
41
+ let suffix = 2;
42
+ while (existing.has(`${name}-${suffix}`)) {
43
+ suffix += 1;
44
+ }
45
+ const unique = `${name}-${suffix}`;
46
+ existing.add(unique);
47
+ return unique;
48
+ }
49
+ function resolvePath(raw, workspaceDir) {
50
+ const trimmed = raw.trim();
51
+ if (!trimmed) {
52
+ throw new Error("path required");
53
+ }
54
+ if (trimmed.startsWith("~") || path.isAbsolute(trimmed)) {
55
+ return path.normalize(resolveUserPath(trimmed));
56
+ }
57
+ return path.normalize(path.resolve(workspaceDir, trimmed));
58
+ }
59
+ function resolveIntervalMs(raw) {
60
+ const value = raw?.trim();
61
+ if (!value) {
62
+ return parseDurationMs(DEFAULT_QMD_INTERVAL, { defaultUnit: "m" });
63
+ }
64
+ try {
65
+ return parseDurationMs(value, { defaultUnit: "m" });
66
+ }
67
+ catch {
68
+ return parseDurationMs(DEFAULT_QMD_INTERVAL, { defaultUnit: "m" });
69
+ }
70
+ }
71
+ function resolveEmbedIntervalMs(raw) {
72
+ const value = raw?.trim();
73
+ if (!value) {
74
+ return parseDurationMs(DEFAULT_QMD_EMBED_INTERVAL, { defaultUnit: "m" });
75
+ }
76
+ try {
77
+ return parseDurationMs(value, { defaultUnit: "m" });
78
+ }
79
+ catch {
80
+ return parseDurationMs(DEFAULT_QMD_EMBED_INTERVAL, { defaultUnit: "m" });
81
+ }
82
+ }
83
+ function resolveDebounceMs(raw) {
84
+ if (typeof raw === "number" && Number.isFinite(raw) && raw >= 0) {
85
+ return Math.floor(raw);
86
+ }
87
+ return DEFAULT_QMD_DEBOUNCE_MS;
88
+ }
89
+ function resolveTimeoutMs(raw, fallback) {
90
+ if (typeof raw === "number" && Number.isFinite(raw) && raw > 0) {
91
+ return Math.floor(raw);
92
+ }
93
+ return fallback;
94
+ }
95
+ function resolveLimits(raw) {
96
+ const parsed = { ...DEFAULT_QMD_LIMITS };
97
+ if (raw?.maxResults && raw.maxResults > 0) {
98
+ parsed.maxResults = Math.floor(raw.maxResults);
99
+ }
100
+ if (raw?.maxSnippetChars && raw.maxSnippetChars > 0) {
101
+ parsed.maxSnippetChars = Math.floor(raw.maxSnippetChars);
102
+ }
103
+ if (raw?.maxInjectedChars && raw.maxInjectedChars > 0) {
104
+ parsed.maxInjectedChars = Math.floor(raw.maxInjectedChars);
105
+ }
106
+ if (raw?.timeoutMs && raw.timeoutMs > 0) {
107
+ parsed.timeoutMs = Math.floor(raw.timeoutMs);
108
+ }
109
+ return parsed;
110
+ }
111
+ function resolveSessionConfig(cfg, workspaceDir) {
112
+ const enabled = Boolean(cfg?.enabled);
113
+ const exportDirRaw = cfg?.exportDir?.trim();
114
+ const exportDir = exportDirRaw ? resolvePath(exportDirRaw, workspaceDir) : undefined;
115
+ const retentionDays = cfg?.retentionDays && cfg.retentionDays > 0 ? Math.floor(cfg.retentionDays) : undefined;
116
+ return {
117
+ enabled,
118
+ exportDir,
119
+ retentionDays,
120
+ };
121
+ }
122
+ function resolveCustomPaths(rawPaths, workspaceDir, existing) {
123
+ if (!rawPaths?.length) {
124
+ return [];
125
+ }
126
+ const collections = [];
127
+ rawPaths.forEach((entry, index) => {
128
+ const trimmedPath = entry?.path?.trim();
129
+ if (!trimmedPath) {
130
+ return;
131
+ }
132
+ let resolved;
133
+ try {
134
+ resolved = resolvePath(trimmedPath, workspaceDir);
135
+ }
136
+ catch {
137
+ return;
138
+ }
139
+ const pattern = entry.pattern?.trim() || "**/*.md";
140
+ const baseName = entry.name?.trim() || `custom-${index + 1}`;
141
+ const name = ensureUniqueName(baseName, existing);
142
+ collections.push({
143
+ name,
144
+ path: resolved,
145
+ pattern,
146
+ kind: "custom",
147
+ });
148
+ });
149
+ return collections;
150
+ }
151
+ function resolveDefaultCollections(include, workspaceDir, existing) {
152
+ if (!include) {
153
+ return [];
154
+ }
155
+ const entries = [
156
+ { path: workspaceDir, pattern: "MEMORY.md", base: "memory-root" },
157
+ { path: workspaceDir, pattern: "memory.md", base: "memory-alt" },
158
+ { path: path.join(workspaceDir, "memory"), pattern: "**/*.md", base: "memory-dir" },
159
+ ];
160
+ return entries.map((entry) => ({
161
+ name: ensureUniqueName(entry.base, existing),
162
+ path: entry.path,
163
+ pattern: entry.pattern,
164
+ kind: "memory",
165
+ }));
166
+ }
167
+ export function resolveMemoryBackendConfig(params) {
168
+ const backend = params.cfg.memory?.backend ?? DEFAULT_BACKEND;
169
+ const citations = params.cfg.memory?.citations ?? DEFAULT_CITATIONS;
170
+ if (backend !== "qmd") {
171
+ return { backend: "builtin", citations };
172
+ }
173
+ const workspaceDir = resolveAgentWorkspaceDir(params.cfg, params.agentId);
174
+ const qmdCfg = params.cfg.memory?.qmd;
175
+ const includeDefaultMemory = qmdCfg?.includeDefaultMemory !== false;
176
+ const nameSet = new Set();
177
+ const collections = [
178
+ ...resolveDefaultCollections(includeDefaultMemory, workspaceDir, nameSet),
179
+ ...resolveCustomPaths(qmdCfg?.paths, workspaceDir, nameSet),
180
+ ];
181
+ const rawCommand = qmdCfg?.command?.trim() || "qmd";
182
+ const parsedCommand = splitShellArgs(rawCommand);
183
+ const command = parsedCommand?.[0] || rawCommand.split(/\s+/)[0] || "qmd";
184
+ const resolved = {
185
+ command,
186
+ collections,
187
+ includeDefaultMemory,
188
+ sessions: resolveSessionConfig(qmdCfg?.sessions, workspaceDir),
189
+ update: {
190
+ intervalMs: resolveIntervalMs(qmdCfg?.update?.interval),
191
+ debounceMs: resolveDebounceMs(qmdCfg?.update?.debounceMs),
192
+ onBoot: qmdCfg?.update?.onBoot !== false,
193
+ waitForBootSync: qmdCfg?.update?.waitForBootSync === true,
194
+ embedIntervalMs: resolveEmbedIntervalMs(qmdCfg?.update?.embedInterval),
195
+ commandTimeoutMs: resolveTimeoutMs(qmdCfg?.update?.commandTimeoutMs, DEFAULT_QMD_COMMAND_TIMEOUT_MS),
196
+ updateTimeoutMs: resolveTimeoutMs(qmdCfg?.update?.updateTimeoutMs, DEFAULT_QMD_UPDATE_TIMEOUT_MS),
197
+ embedTimeoutMs: resolveTimeoutMs(qmdCfg?.update?.embedTimeoutMs, DEFAULT_QMD_EMBED_TIMEOUT_MS),
198
+ },
199
+ limits: resolveLimits(qmdCfg?.limits),
200
+ scope: qmdCfg?.scope ?? DEFAULT_QMD_SCOPE,
201
+ };
202
+ return {
203
+ backend: "qmd",
204
+ citations,
205
+ qmd: resolved,
206
+ };
207
+ }
@@ -0,0 +1,277 @@
1
+ import { createInterface } from "node:readline";
2
+ import { Readable } from "node:stream";
3
+ import { retryAsync } from "../infra/retry.js";
4
+ import { hashText, runWithConcurrency } from "./internal.js";
5
+ export const VOYAGE_BATCH_ENDPOINT = "/v1/embeddings";
6
+ const VOYAGE_BATCH_COMPLETION_WINDOW = "12h";
7
+ const VOYAGE_BATCH_MAX_REQUESTS = 50000;
8
+ function getVoyageBaseUrl(client) {
9
+ return client.baseUrl?.replace(/\/$/, "") ?? "";
10
+ }
11
+ function getVoyageHeaders(client, params) {
12
+ const headers = client.headers ? { ...client.headers } : {};
13
+ if (params.json) {
14
+ if (!headers["Content-Type"] && !headers["content-type"]) {
15
+ headers["Content-Type"] = "application/json";
16
+ }
17
+ }
18
+ else {
19
+ delete headers["Content-Type"];
20
+ delete headers["content-type"];
21
+ }
22
+ return headers;
23
+ }
24
+ function splitVoyageBatchRequests(requests) {
25
+ if (requests.length <= VOYAGE_BATCH_MAX_REQUESTS) {
26
+ return [requests];
27
+ }
28
+ const groups = [];
29
+ for (let i = 0; i < requests.length; i += VOYAGE_BATCH_MAX_REQUESTS) {
30
+ groups.push(requests.slice(i, i + VOYAGE_BATCH_MAX_REQUESTS));
31
+ }
32
+ return groups;
33
+ }
34
+ async function submitVoyageBatch(params) {
35
+ const baseUrl = getVoyageBaseUrl(params.client);
36
+ const jsonl = params.requests.map((request) => JSON.stringify(request)).join("\n");
37
+ const form = new FormData();
38
+ form.append("purpose", "batch");
39
+ form.append("file", new Blob([jsonl], { type: "application/jsonl" }), `memory-embeddings.${hashText(String(Date.now()))}.jsonl`);
40
+ // 1. Upload file using Voyage Files API
41
+ const fileRes = await fetch(`${baseUrl}/files`, {
42
+ method: "POST",
43
+ headers: getVoyageHeaders(params.client, { json: false }),
44
+ body: form,
45
+ });
46
+ if (!fileRes.ok) {
47
+ const text = await fileRes.text();
48
+ throw new Error(`voyage batch file upload failed: ${fileRes.status} ${text}`);
49
+ }
50
+ const filePayload = (await fileRes.json());
51
+ if (!filePayload.id) {
52
+ throw new Error("voyage batch file upload failed: missing file id");
53
+ }
54
+ // 2. Create batch job using Voyage Batches API
55
+ const batchRes = await retryAsync(async () => {
56
+ const res = await fetch(`${baseUrl}/batches`, {
57
+ method: "POST",
58
+ headers: getVoyageHeaders(params.client, { json: true }),
59
+ body: JSON.stringify({
60
+ input_file_id: filePayload.id,
61
+ endpoint: VOYAGE_BATCH_ENDPOINT,
62
+ completion_window: VOYAGE_BATCH_COMPLETION_WINDOW,
63
+ request_params: {
64
+ model: params.client.model,
65
+ input_type: "document",
66
+ },
67
+ metadata: {
68
+ source: "clawdbot-memory",
69
+ agent: params.agentId,
70
+ },
71
+ }),
72
+ });
73
+ if (!res.ok) {
74
+ const text = await res.text();
75
+ const err = new Error(`voyage batch create failed: ${res.status} ${text}`);
76
+ err.status = res.status;
77
+ throw err;
78
+ }
79
+ return res;
80
+ }, {
81
+ attempts: 3,
82
+ minDelayMs: 300,
83
+ maxDelayMs: 2000,
84
+ jitter: 0.2,
85
+ shouldRetry: (err) => {
86
+ const status = err.status;
87
+ return status === 429 || (typeof status === "number" && status >= 500);
88
+ },
89
+ });
90
+ return (await batchRes.json());
91
+ }
92
+ async function fetchVoyageBatchStatus(params) {
93
+ const baseUrl = getVoyageBaseUrl(params.client);
94
+ const res = await fetch(`${baseUrl}/batches/${params.batchId}`, {
95
+ headers: getVoyageHeaders(params.client, { json: true }),
96
+ });
97
+ if (!res.ok) {
98
+ const text = await res.text();
99
+ throw new Error(`voyage batch status failed: ${res.status} ${text}`);
100
+ }
101
+ return (await res.json());
102
+ }
103
+ async function readVoyageBatchError(params) {
104
+ try {
105
+ const baseUrl = getVoyageBaseUrl(params.client);
106
+ const res = await fetch(`${baseUrl}/files/${params.errorFileId}/content`, {
107
+ headers: getVoyageHeaders(params.client, { json: true }),
108
+ });
109
+ if (!res.ok) {
110
+ const text = await res.text();
111
+ throw new Error(`voyage batch error file content failed: ${res.status} ${text}`);
112
+ }
113
+ const text = await res.text();
114
+ if (!text.trim()) {
115
+ return undefined;
116
+ }
117
+ const lines = text
118
+ .split("\n")
119
+ .map((line) => line.trim())
120
+ .filter(Boolean)
121
+ .map((line) => JSON.parse(line));
122
+ const first = lines.find((line) => line.error?.message || line.response?.body?.error);
123
+ const message = first?.error?.message ??
124
+ (typeof first?.response?.body?.error?.message === "string"
125
+ ? first?.response?.body?.error?.message
126
+ : undefined);
127
+ return message;
128
+ }
129
+ catch (err) {
130
+ const message = err instanceof Error ? err.message : String(err);
131
+ return message ? `error file unavailable: ${message}` : undefined;
132
+ }
133
+ }
134
+ async function waitForVoyageBatch(params) {
135
+ const start = Date.now();
136
+ let current = params.initial;
137
+ while (true) {
138
+ const status = current ??
139
+ (await fetchVoyageBatchStatus({
140
+ client: params.client,
141
+ batchId: params.batchId,
142
+ }));
143
+ const state = status.status ?? "unknown";
144
+ if (state === "completed") {
145
+ if (!status.output_file_id) {
146
+ throw new Error(`voyage batch ${params.batchId} completed without output file`);
147
+ }
148
+ return {
149
+ outputFileId: status.output_file_id,
150
+ errorFileId: status.error_file_id ?? undefined,
151
+ };
152
+ }
153
+ if (["failed", "expired", "cancelled", "canceled"].includes(state)) {
154
+ const detail = status.error_file_id
155
+ ? await readVoyageBatchError({ client: params.client, errorFileId: status.error_file_id })
156
+ : undefined;
157
+ const suffix = detail ? `: ${detail}` : "";
158
+ throw new Error(`voyage batch ${params.batchId} ${state}${suffix}`);
159
+ }
160
+ if (!params.wait) {
161
+ throw new Error(`voyage batch ${params.batchId} still ${state}; wait disabled`);
162
+ }
163
+ if (Date.now() - start > params.timeoutMs) {
164
+ throw new Error(`voyage batch ${params.batchId} timed out after ${params.timeoutMs}ms`);
165
+ }
166
+ params.debug?.(`voyage batch ${params.batchId} ${state}; waiting ${params.pollIntervalMs}ms`);
167
+ await new Promise((resolve) => setTimeout(resolve, params.pollIntervalMs));
168
+ current = undefined;
169
+ }
170
+ }
171
+ export async function runVoyageEmbeddingBatches(params) {
172
+ if (params.requests.length === 0) {
173
+ return new Map();
174
+ }
175
+ const groups = splitVoyageBatchRequests(params.requests);
176
+ const byCustomId = new Map();
177
+ const tasks = groups.map((group, groupIndex) => async () => {
178
+ const batchInfo = await submitVoyageBatch({
179
+ client: params.client,
180
+ requests: group,
181
+ agentId: params.agentId,
182
+ });
183
+ if (!batchInfo.id) {
184
+ throw new Error("voyage batch create failed: missing batch id");
185
+ }
186
+ params.debug?.("memory embeddings: voyage batch created", {
187
+ batchId: batchInfo.id,
188
+ status: batchInfo.status,
189
+ group: groupIndex + 1,
190
+ groups: groups.length,
191
+ requests: group.length,
192
+ });
193
+ if (!params.wait && batchInfo.status !== "completed") {
194
+ throw new Error(`voyage batch ${batchInfo.id} submitted; enable remote.batch.wait to await completion`);
195
+ }
196
+ const completed = batchInfo.status === "completed"
197
+ ? {
198
+ outputFileId: batchInfo.output_file_id ?? "",
199
+ errorFileId: batchInfo.error_file_id ?? undefined,
200
+ }
201
+ : await waitForVoyageBatch({
202
+ client: params.client,
203
+ batchId: batchInfo.id,
204
+ wait: params.wait,
205
+ pollIntervalMs: params.pollIntervalMs,
206
+ timeoutMs: params.timeoutMs,
207
+ debug: params.debug,
208
+ initial: batchInfo,
209
+ });
210
+ if (!completed.outputFileId) {
211
+ throw new Error(`voyage batch ${batchInfo.id} completed without output file`);
212
+ }
213
+ const baseUrl = getVoyageBaseUrl(params.client);
214
+ const contentRes = await fetch(`${baseUrl}/files/${completed.outputFileId}/content`, {
215
+ headers: getVoyageHeaders(params.client, { json: true }),
216
+ });
217
+ if (!contentRes.ok) {
218
+ const text = await contentRes.text();
219
+ throw new Error(`voyage batch file content failed: ${contentRes.status} ${text}`);
220
+ }
221
+ const errors = [];
222
+ const remaining = new Set(group.map((request) => request.custom_id));
223
+ if (contentRes.body) {
224
+ const reader = createInterface({
225
+ input: Readable.fromWeb(contentRes.body),
226
+ terminal: false,
227
+ });
228
+ for await (const rawLine of reader) {
229
+ if (!rawLine.trim()) {
230
+ continue;
231
+ }
232
+ const line = JSON.parse(rawLine);
233
+ const customId = line.custom_id;
234
+ if (!customId) {
235
+ continue;
236
+ }
237
+ remaining.delete(customId);
238
+ if (line.error?.message) {
239
+ errors.push(`${customId}: ${line.error.message}`);
240
+ continue;
241
+ }
242
+ const response = line.response;
243
+ const statusCode = response?.status_code ?? 0;
244
+ if (statusCode >= 400) {
245
+ const message = response?.body?.error?.message ??
246
+ (typeof response?.body === "string" ? response.body : undefined) ??
247
+ "unknown error";
248
+ errors.push(`${customId}: ${message}`);
249
+ continue;
250
+ }
251
+ const data = response?.body?.data ?? [];
252
+ const embedding = data[0]?.embedding ?? [];
253
+ if (embedding.length === 0) {
254
+ errors.push(`${customId}: empty embedding`);
255
+ continue;
256
+ }
257
+ byCustomId.set(customId, embedding);
258
+ }
259
+ }
260
+ if (errors.length > 0) {
261
+ throw new Error(`voyage batch ${batchInfo.id} failed: ${errors.join("; ")}`);
262
+ }
263
+ if (remaining.size > 0) {
264
+ throw new Error(`voyage batch ${batchInfo.id} missing ${remaining.size} embedding responses`);
265
+ }
266
+ });
267
+ params.debug?.("memory embeddings: voyage batch submit", {
268
+ requests: params.requests.length,
269
+ groups: groups.length,
270
+ wait: params.wait,
271
+ concurrency: params.concurrency,
272
+ pollIntervalMs: params.pollIntervalMs,
273
+ timeoutMs: params.timeoutMs,
274
+ });
275
+ await runWithConcurrency(tasks, params.concurrency);
276
+ return byCustomId;
277
+ }
@@ -0,0 +1,75 @@
1
+ import { requireApiKey, resolveApiKeyForProvider } from "../agents/model-auth.js";
2
+ export const DEFAULT_VOYAGE_EMBEDDING_MODEL = "voyage-4-large";
3
+ const DEFAULT_VOYAGE_BASE_URL = "https://api.voyageai.com/v1";
4
+ export function normalizeVoyageModel(model) {
5
+ const trimmed = model.trim();
6
+ if (!trimmed) {
7
+ return DEFAULT_VOYAGE_EMBEDDING_MODEL;
8
+ }
9
+ if (trimmed.startsWith("voyage/")) {
10
+ return trimmed.slice("voyage/".length);
11
+ }
12
+ return trimmed;
13
+ }
14
+ export async function createVoyageEmbeddingProvider(options) {
15
+ const client = await resolveVoyageEmbeddingClient(options);
16
+ const url = `${client.baseUrl.replace(/\/$/, "")}/embeddings`;
17
+ const embed = async (input, input_type) => {
18
+ if (input.length === 0) {
19
+ return [];
20
+ }
21
+ const body = {
22
+ model: client.model,
23
+ input,
24
+ };
25
+ if (input_type) {
26
+ body.input_type = input_type;
27
+ }
28
+ const res = await fetch(url, {
29
+ method: "POST",
30
+ headers: client.headers,
31
+ body: JSON.stringify(body),
32
+ });
33
+ if (!res.ok) {
34
+ const text = await res.text();
35
+ throw new Error(`voyage embeddings failed: ${res.status} ${text}`);
36
+ }
37
+ const payload = (await res.json());
38
+ const data = payload.data ?? [];
39
+ return data.map((entry) => entry.embedding ?? []);
40
+ };
41
+ return {
42
+ provider: {
43
+ id: "voyage",
44
+ model: client.model,
45
+ embedQuery: async (text) => {
46
+ const [vec] = await embed([text], "query");
47
+ return vec ?? [];
48
+ },
49
+ embedBatch: async (texts) => embed(texts, "document"),
50
+ },
51
+ client,
52
+ };
53
+ }
54
+ export async function resolveVoyageEmbeddingClient(options) {
55
+ const remote = options.remote;
56
+ const remoteApiKey = remote?.apiKey?.trim();
57
+ const remoteBaseUrl = remote?.baseUrl?.trim();
58
+ const apiKey = remoteApiKey
59
+ ? remoteApiKey
60
+ : requireApiKey(await resolveApiKeyForProvider({
61
+ provider: "voyage",
62
+ cfg: options.config,
63
+ agentDir: options.agentDir,
64
+ }), "voyage");
65
+ const providerConfig = options.config.models?.providers?.voyage;
66
+ const baseUrl = remoteBaseUrl || providerConfig?.baseUrl?.trim() || DEFAULT_VOYAGE_BASE_URL;
67
+ const headerOverrides = Object.assign({}, providerConfig?.headers, remote?.headers);
68
+ const headers = {
69
+ "Content-Type": "application/json",
70
+ Authorization: `Bearer ${apiKey}`,
71
+ ...headerOverrides,
72
+ };
73
+ const model = normalizeVoyageModel(options.model);
74
+ return { baseUrl, headers, model };
75
+ }
@@ -1,15 +1,27 @@
1
1
  import fsSync from "node:fs";
2
+ import { formatErrorMessage } from "../infra/errors.js";
2
3
  import { resolveUserPath } from "../utils.js";
3
4
  import { createGeminiEmbeddingProvider } from "./embeddings-gemini.js";
4
5
  import { createOpenAiEmbeddingProvider } from "./embeddings-openai.js";
6
+ import { createVoyageEmbeddingProvider } from "./embeddings-voyage.js";
5
7
  import { importNodeLlamaCpp } from "./node-llama.js";
8
+ function sanitizeAndNormalizeEmbedding(vec) {
9
+ const sanitized = vec.map((value) => (Number.isFinite(value) ? value : 0));
10
+ const magnitude = Math.sqrt(sanitized.reduce((sum, value) => sum + value * value, 0));
11
+ if (magnitude < 1e-10) {
12
+ return sanitized;
13
+ }
14
+ return sanitized.map((value) => value / magnitude);
15
+ }
6
16
  const DEFAULT_LOCAL_MODEL = "hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf";
7
17
  function canAutoSelectLocal(options) {
8
18
  const modelPath = options.local?.modelPath?.trim();
9
- if (!modelPath)
19
+ if (!modelPath) {
10
20
  return false;
11
- if (/^(hf:|https?:)/i.test(modelPath))
21
+ }
22
+ if (/^(hf:|https?:)/i.test(modelPath)) {
12
23
  return false;
24
+ }
13
25
  const resolved = resolveUserPath(modelPath);
14
26
  try {
15
27
  return fsSync.statSync(resolved).isFile();
@@ -19,7 +31,7 @@ function canAutoSelectLocal(options) {
19
31
  }
20
32
  }
21
33
  function isMissingApiKeyError(err) {
22
- const message = formatError(err);
34
+ const message = formatErrorMessage(err);
23
35
  return message.includes("No API key found for provider");
24
36
  }
25
37
  async function createLocalEmbeddingProvider(options) {
@@ -49,13 +61,13 @@ async function createLocalEmbeddingProvider(options) {
49
61
  embedQuery: async (text) => {
50
62
  const ctx = await ensureContext();
51
63
  const embedding = await ctx.getEmbeddingFor(text);
52
- return Array.from(embedding.vector);
64
+ return sanitizeAndNormalizeEmbedding(Array.from(embedding.vector));
53
65
  },
54
66
  embedBatch: async (texts) => {
55
67
  const ctx = await ensureContext();
56
68
  const embeddings = await Promise.all(texts.map(async (text) => {
57
69
  const embedding = await ctx.getEmbeddingFor(text);
58
- return Array.from(embedding.vector);
70
+ return sanitizeAndNormalizeEmbedding(Array.from(embedding.vector));
59
71
  }));
60
72
  return embeddings;
61
73
  },
@@ -73,10 +85,14 @@ export async function createEmbeddingProvider(options) {
73
85
  const { provider, client } = await createGeminiEmbeddingProvider(options);
74
86
  return { provider, gemini: client };
75
87
  }
88
+ if (id === "voyage") {
89
+ const { provider, client } = await createVoyageEmbeddingProvider(options);
90
+ return { provider, voyage: client };
91
+ }
76
92
  const { provider, client } = await createOpenAiEmbeddingProvider(options);
77
93
  return { provider, openAi: client };
78
94
  };
79
- const formatPrimaryError = (err, provider) => provider === "local" ? formatLocalSetupError(err) : formatError(err);
95
+ const formatPrimaryError = (err, provider) => provider === "local" ? formatLocalSetupError(err) : formatErrorMessage(err);
80
96
  if (requestedProvider === "auto") {
81
97
  const missingKeyErrors = [];
82
98
  let localError = null;
@@ -89,7 +105,7 @@ export async function createEmbeddingProvider(options) {
89
105
  localError = formatLocalSetupError(err);
90
106
  }
91
107
  }
92
- for (const provider of ["openai", "gemini"]) {
108
+ for (const provider of ["openai", "gemini", "voyage"]) {
93
109
  try {
94
110
  const result = await createProvider(provider);
95
111
  return { ...result, requestedProvider };
@@ -100,7 +116,7 @@ export async function createEmbeddingProvider(options) {
100
116
  missingKeyErrors.push(message);
101
117
  continue;
102
118
  }
103
- throw new Error(message);
119
+ throw new Error(message, { cause: err });
104
120
  }
105
121
  }
106
122
  const details = [...missingKeyErrors, localError].filter(Boolean);
@@ -126,17 +142,12 @@ export async function createEmbeddingProvider(options) {
126
142
  };
127
143
  }
128
144
  catch (fallbackErr) {
129
- throw new Error(`${reason}\n\nFallback to ${fallback} failed: ${formatError(fallbackErr)}`);
145
+ throw new Error(`${reason}\n\nFallback to ${fallback} failed: ${formatErrorMessage(fallbackErr)}`, { cause: fallbackErr });
130
146
  }
131
147
  }
132
- throw new Error(reason);
148
+ throw new Error(reason, { cause: primaryErr });
133
149
  }
134
150
  }
135
- function formatError(err) {
136
- if (err instanceof Error)
137
- return err.message;
138
- return String(err);
139
- }
140
151
  function isNodeLlamaCppMissing(err) {
141
152
  if (!(err instanceof Error))
142
153
  return false;
@@ -147,7 +158,7 @@ function isNodeLlamaCppMissing(err) {
147
158
  return false;
148
159
  }
149
160
  function formatLocalSetupError(err) {
150
- const detail = formatError(err);
161
+ const detail = formatErrorMessage(err);
151
162
  const missing = isNodeLlamaCppMissing(err);
152
163
  return [
153
164
  "Local embeddings unavailable.",
@@ -160,10 +171,11 @@ function formatLocalSetupError(err) {
160
171
  "To enable local embeddings:",
161
172
  "1) Use Node 22 LTS (recommended for installs/updates)",
162
173
  missing
163
- ? "2) Reinstall Moltbot (this should install node-llama-cpp): npm i -g poolbot@latest"
174
+ ? "2) Reinstall Poolbot (this should install node-llama-cpp): npm i -g poolbot@latest"
164
175
  : null,
165
176
  "3) If you use pnpm: pnpm approve-builds (select node-llama-cpp), then pnpm rebuild node-llama-cpp",
166
177
  'Or set agents.defaults.memorySearch.provider = "openai" (remote).',
178
+ 'Or set agents.defaults.memorySearch.provider = "voyage" (remote).',
167
179
  ]
168
180
  .filter(Boolean)
169
181
  .join("\n");