@desplega.ai/agent-swarm 1.158.0 → 1.160.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/README.md +1 -1
  2. package/dist/{acp-adapter-xaq4n6pc.js → acp-adapter-2mjwcsfh.js} +124 -27
  3. package/dist/{actions-p9hz5yat.js → actions-e43rxskr.js} +35 -30
  4. package/dist/{anthropic-messages-51pz26qe.js → anthropic-messages-5qx80j9k.js} +106 -16
  5. package/dist/{app-g26wdcz6.js → app-mc7xfagn.js} +12 -10
  6. package/dist/{assistant-wydfqkb3.js → assistant-sedkzv3b.js} +42 -31
  7. package/dist/{azure-openai-responses-8gksqtmz.js → azure-openai-responses-nfb21z9a.js} +13 -14
  8. package/dist/{boot-reembed-se8zmdcp.js → boot-reembed-cqz9swn5.js} +13 -12
  9. package/dist/{boot-reembed-g5ckg9yb.js → boot-reembed-m3656j2n.js} +14 -13
  10. package/dist/{boot-scrub-logs-wfxqan61.js → boot-scrub-logs-xbxf5d7w.js} +11 -9
  11. package/dist/boot-seeds-gsetbs5y.js +28 -0
  12. package/dist/{claude-adapter-tv2x4f36.js → claude-adapter-dc6289mc.js} +28 -23
  13. package/dist/{claude-managed-adapter-41b2s7fd.js → claude-managed-adapter-naaw51me.js} +4 -3
  14. package/dist/{claude-managed-setup-60g8aazx.js → claude-managed-setup-eacvchx0.js} +12 -3
  15. package/dist/claude-sdk-session-bqp2xvym.js +29722 -0
  16. package/dist/{cli-987hg0aa.js → cli-0jwe9034.js} +2 -2
  17. package/dist/{cli-vj6h9kc2.js → cli-0m7wct0d.js} +59 -1
  18. package/dist/{cli-c07r9a2m.js → cli-0q3avq3s.js} +12 -11
  19. package/dist/{cli-19jenss3.js → cli-0wgxmwf6.js} +31 -10
  20. package/dist/cli-0x01kwrd.js +491 -0
  21. package/dist/cli-0xqde53b.js +176 -0
  22. package/dist/cli-10nhj6xq.js +8355 -0
  23. package/dist/{cli-tt9k8r35.js → cli-12tszpk9.js} +479 -910
  24. package/dist/{cli-5b6b62tz.js → cli-13hw4z91.js} +1 -1
  25. package/dist/{cli-cqt19wg6.js → cli-1a2j50m0.js} +11 -2
  26. package/dist/{cli-xberxa1r.js → cli-25fcq4b4.js} +2 -2
  27. package/dist/{cli-npssxgaz.js → cli-2pdaysab.js} +52 -2
  28. package/dist/cli-3qhyh31j.js +166 -0
  29. package/dist/cli-447dt1h3.js +3828 -0
  30. package/dist/cli-4derpgyk.js +115 -0
  31. package/dist/{cli-00w2c66p.js → cli-523679eh.js} +13 -2
  32. package/dist/{cli-y95wp3tg.js → cli-58e8yr0d.js} +1 -1
  33. package/dist/{cli-24k806sc.js → cli-5nbmpy8w.js} +3 -3
  34. package/dist/{cli-53sz8gkz.js → cli-6cs6wzxt.js} +1 -1
  35. package/dist/cli-741yb0xx.js +1027 -0
  36. package/dist/cli-74h9hscv.js +69 -0
  37. package/dist/cli-7cxw8b60.js +14910 -0
  38. package/dist/{cli-xhaeg2nc.js → cli-7e398j1h.js} +1 -1
  39. package/dist/cli-7kyk9jr3.js +22 -0
  40. package/dist/cli-89s4ngw3.js +183 -0
  41. package/dist/{cli-9b13ggd1.js → cli-89v6kyq7.js} +1 -0
  42. package/dist/{cli-ftfvggzx.js → cli-9hsgwz4w.js} +1045 -581
  43. package/dist/{cli-rqz8qbw7.js → cli-a8dvhzrt.js} +59 -20
  44. package/dist/{cli-j57qkrpq.js → cli-azhgzetg.js} +395 -56
  45. package/dist/cli-br0qdrnp.js +2150 -0
  46. package/dist/{cli-rj19hc34.js → cli-btfv8y88.js} +1 -1
  47. package/dist/{cli-8qmme6vd.js → cli-c8a36vcc.js} +2 -2
  48. package/dist/cli-cpvsaqsw.js +333 -0
  49. package/dist/cli-d5czme6m.js +17805 -0
  50. package/dist/{cli-h38x0qhg.js → cli-et8m9xsv.js} +4 -3
  51. package/dist/{cli-x24pshtq.js → cli-evvtk35y.js} +6 -6
  52. package/dist/{cli-7s3syk22.js → cli-f8gy6r2r.js} +5 -5
  53. package/dist/{cli-zt1227k1.js → cli-fkqhbg8g.js} +5 -3
  54. package/dist/{cli-9httdpyq.js → cli-g2whhdrf.js} +1 -1
  55. package/dist/cli-gt4hxb8p.js +99 -0
  56. package/dist/{cli-s8eet254.js → cli-jajnsm8q.js} +37184 -53838
  57. package/dist/{cli-7gtvvpbh.js → cli-jayjpjmb.js} +21 -12
  58. package/dist/{cli-68w09sjw.js → cli-jyk0ynw2.js} +27 -89
  59. package/dist/{cli-aehm1rbq.js → cli-jz4w45qt.js} +1152 -61
  60. package/dist/cli-kmcpfwn2.js +333856 -0
  61. package/dist/{cli-4198qc9v.js → cli-ktmyrtpn.js} +19 -3
  62. package/dist/{cli-j55n64b6.js → cli-mfe5btp9.js} +505 -189
  63. package/dist/{cli-q67y4wzm.js → cli-phsaj4xq.js} +24 -2
  64. package/dist/{cli-1hkrch3k.js → cli-pm1rst0h.js} +46 -7
  65. package/dist/{cli-pw9rj5t9.js → cli-pqetb83f.js} +1 -176
  66. package/dist/{cli-ggm92wcn.js → cli-ptr8h7kp.js} +20 -1
  67. package/dist/{cli-s8s499xy.js → cli-qbksc292.js} +3 -2
  68. package/dist/{cli-47m6dkd3.js → cli-qydf22qq.js} +597 -346
  69. package/dist/{cli-3gmcwfyx.js → cli-r1mxd1xh.js} +13 -6
  70. package/dist/cli-rb9m6rpe.js +4980 -0
  71. package/dist/cli-rykfmgwg.js +102 -0
  72. package/dist/{cli-5d10vd2m.js → cli-shkxm1vn.js} +6 -5
  73. package/dist/{cli-eetrvv91.js → cli-t3p77qk1.js} +1 -1
  74. package/dist/cli-tfky2838.js +756 -0
  75. package/dist/{cli-g8djp6qe.js → cli-tmqt7dpj.js} +40 -0
  76. package/dist/{cli-fgqxwrpv.js → cli-tpq83z89.js} +1631 -127
  77. package/dist/cli-trc24wk2.js +143 -0
  78. package/dist/{cli-aky8tctm.js → cli-tzx2ke1v.js} +3 -3
  79. package/dist/cli-v7fn5gms.js +1425 -0
  80. package/dist/{cli-wscdvcqz.js → cli-vctdqs5h.js} +1 -1
  81. package/dist/{cli-cw9zck8j.js → cli-xjcywfsf.js} +8 -4
  82. package/dist/{cli-k0g1sjzm.js → cli-ybgv4kw2.js} +18 -11
  83. package/dist/{cli-rjehvrts.js → cli-ydmcgve1.js} +8 -8
  84. package/dist/{cli-vhjwh6cz.js → cli-ygwm91nt.js} +1 -1
  85. package/dist/{cli-mcnhgnn1.js → cli-ykk5jaax.js} +184 -26
  86. package/dist/{cli-de1396j2.js → cli-ywybs5as.js} +7 -1
  87. package/dist/cli-zpep9q5e.js +491 -0
  88. package/dist/cli.js +41 -32
  89. package/dist/cloudflare-workers-ai-system-one-k6fbxw9d.js +46 -0
  90. package/dist/{codex-adapter-cnm8wk11.js → codex-adapter-nmxcatww.js} +26 -17
  91. package/dist/{codex-hook-9hptmdhj.js → codex-hook-20me6byw.js} +2 -2
  92. package/dist/{codex-login-x3jk4etn.js → codex-login-w6fz4xbz.js} +50 -5
  93. package/dist/{codex-session-runner-gfg547zj.js → codex-session-runner-90aa80ev.js} +24 -17
  94. package/dist/{commands-e3bn0p75.js → commands-8wcq1kn7.js} +11 -9
  95. package/dist/{db-03v9kzr2.js → db-j40kc4se.js} +25 -11
  96. package/dist/{devin-adapter-8vgkwh29.js → devin-adapter-dpsv6hd9.js} +1 -1
  97. package/dist/{dispatcher-nrmg8yht.js → dispatcher-4zqy768d.js} +34 -29
  98. package/dist/{dsh-adapter-k03nfqa6.js → dsh-adapter-mpnzgztj.js} +3 -3
  99. package/dist/{e2b-93x1k0j5.js → e2b-ez07znam.js} +4 -3
  100. package/dist/execute-6e7qeyk4.js +1017 -0
  101. package/dist/{google-generative-ai-bxmv50nc.js → google-generative-ai-k6n5nbpp.js} +6 -5
  102. package/dist/{google-vertex-809af514.js → google-vertex-44xxtcvp.js} +6 -5
  103. package/dist/{handlers-aqcedbyb.js → handlers-kjdce1w5.js} +37 -32
  104. package/dist/{hook-ybvmrmhq.js → hook-czx13n12.js} +19 -15
  105. package/dist/{hook-7vkskkre.js → hook-r2t4bqfg.js} +18 -14
  106. package/dist/{http-2eqa8t24.js → http-3bbb19be.js} +900 -145
  107. package/dist/{index-f6cryxwe.js → index-4a5njnm1.js} +2 -59
  108. package/dist/{index-x71bvq0p.js → index-668me3f0.js} +35 -30
  109. package/dist/{index-c6zsv1bd.js → index-7aj368tw.js} +13 -12
  110. package/dist/{index-1yks3qcr.js → index-fg0dsp6c.js} +34 -29
  111. package/dist/{index-chgdkq36.js → index-kkv84jq9.js} +34 -29
  112. package/dist/{index-a3vn96n8.js → index-zg7vp46x.js} +198 -54
  113. package/dist/{keepalive-vtkf5n99.js → keepalive-yra8dy57.js} +13 -11
  114. package/dist/{lead-h3sp357x.js → lead-va0pad2c.js} +54 -49
  115. package/dist/llama-cpp-classify-tgj35k8d.js +335 -0
  116. package/dist/{maintenance-jzeqtk3q.js → maintenance-hqewtmyg.js} +14 -13
  117. package/dist/{mistral-conversations-zx0kn554.js → mistral-conversations-pc3ntnxt.js} +14 -17
  118. package/dist/{oauth-refresh-sweep-qp3dzmdp.js → oauth-refresh-sweep-7rdt1m9n.js} +12 -10
  119. package/dist/{onboard-tmsp0qbz.js → onboard-j6ms6d0x.js} +6 -5
  120. package/dist/{openai-codex-responses-4vjqzvjp.js → openai-codex-responses-bbancrr0.js} +21 -8
  121. package/dist/{openai-completions-9hjrqbw8.js → openai-completions-jpaj5g2b.js} +9 -12
  122. package/dist/{openai-responses-7b1pn0xt.js → openai-responses-200k1wx4.js} +23 -18
  123. package/dist/{opencode-adapter-x6x2da1z.js → opencode-adapter-89rabkw2.js} +8 -7
  124. package/dist/{openrouter-images-9f9ek4rw.js → openrouter-images-8yx3487g.js} +5 -7
  125. package/dist/{otel-impl-9mz73q65.js → otel-impl-a792rjz0.js} +1 -1
  126. package/dist/{pi-messages-txpjj39q.js → pi-messages-vxdt8v7j.js} +2 -1
  127. package/dist/{pi-mono-adapter-m6dvv0dz.js → pi-mono-adapter-g7qzvr3v.js} +295 -70
  128. package/dist/pricing-refresh-wx0tp7cb.js +39 -0
  129. package/dist/quickjs-r1pq2107.wasm +0 -0
  130. package/dist/{rbac-roles-c9wqz83x.js → rbac-roles-8tzawacv.js} +12 -10
  131. package/dist/{render-v2-gryrh9h8.js → render-v2-mm7zswb8.js} +12 -10
  132. package/dist/runtime-zyssgse0.js +24 -0
  133. package/dist/{setup-q9720bt6.js → setup-8y70ys6t.js} +6 -5
  134. package/dist/typesafe-system-one-2ef30pec.js +27 -0
  135. package/dist/{virtual-modules-3htpgn8x.js → virtual-modules-6nmk7h3n.js} +22 -13
  136. package/dist/{work-objects-b76x7deb.js → work-objects-fg6xkb0n.js} +37 -32
  137. package/dist/{worker-6vrxbv41.js → worker-wmwhxsph.js} +54 -49
  138. package/openapi.json +1314 -91
  139. package/package.json +12 -11
  140. package/src/be/db/agents.ts +20 -0
  141. package/src/be/db/api-keys.ts +70 -0
  142. package/src/be/db/tasks/human-free.ts +442 -0
  143. package/src/be/db/tasks/read.ts +56 -1
  144. package/src/be/db/tasks/write.ts +107 -11
  145. package/src/be/db.ts +274 -188
  146. package/src/be/harness-model-support.ts +182 -0
  147. package/src/be/human-free-drain.ts +67 -0
  148. package/src/be/memory/providers/sqlite-store.ts +51 -15
  149. package/src/be/migrations/182_task_human_free_flag.sql +63 -0
  150. package/src/be/migrations/183_human_free_reclassify_queue.sql +25 -0
  151. package/src/be/migrations/184_model_catalog.sql +120 -0
  152. package/src/be/migrations/185_api_key_auth_failures.sql +6 -0
  153. package/src/be/migrations/186_api_key_seat_mismatch.sql +8 -0
  154. package/src/be/model-catalog-store.ts +644 -0
  155. package/src/be/model-tier-keys.ts +46 -0
  156. package/src/be/model-tier-resolution.ts +534 -0
  157. package/src/be/model-validation.ts +188 -0
  158. package/src/be/models-catalog.ts +61 -7
  159. package/src/be/modelsdev-cache.json +82 -0
  160. package/src/be/modelsdev-cache.ts +2 -0
  161. package/src/be/pricing-refresh.ts +154 -12
  162. package/src/be/scripts/typecheck.ts +15 -0
  163. package/src/be/seed/runner.ts +18 -12
  164. package/src/be/seed/types.ts +1 -0
  165. package/src/be/seed-scripts/catalog/task-failure-audit.ts +61 -9
  166. package/src/be/swarm-config-guard.ts +8 -0
  167. package/src/cli.tsx +10 -0
  168. package/src/commands/claude-managed-setup.ts +3 -1
  169. package/src/commands/codex-login.ts +67 -0
  170. package/src/commands/credential-outcome-report.ts +191 -0
  171. package/src/commands/rate-limit-outcome.ts +34 -4
  172. package/src/commands/runner.ts +357 -186
  173. package/src/commands/seat-mismatch-report.ts +46 -0
  174. package/src/extensions/apply-task-create.ts +27 -1
  175. package/src/extensions/contract-types.generated.ts +1 -1
  176. package/src/heartbeat/heartbeat.ts +79 -17
  177. package/src/heartbeat/templates.ts +2 -2
  178. package/src/http/agents.ts +62 -1
  179. package/src/http/api-keys.ts +140 -2
  180. package/src/http/codex-oauth-keep-warm.ts +3 -5
  181. package/src/http/index.ts +8 -0
  182. package/src/http/memory.ts +12 -5
  183. package/src/http/models-catalog.ts +357 -8
  184. package/src/http/poll.ts +54 -3
  185. package/src/http/schedules.ts +51 -6
  186. package/src/http/script-runs.ts +12 -0
  187. package/src/http/session-data.ts +2 -5
  188. package/src/http/stats.ts +6 -8
  189. package/src/http/status.ts +15 -1
  190. package/src/http/tasks.ts +90 -7
  191. package/src/http/usage-cache.ts +56 -15
  192. package/src/http/workflows.ts +46 -8
  193. package/src/mcp-client/http-client.ts +5 -0
  194. package/src/memory/recall-query.ts +74 -0
  195. package/src/prompts/base-prompt.ts +15 -4
  196. package/src/prompts/session-templates.ts +23 -1
  197. package/src/providers/acp-adapter.ts +1 -0
  198. package/src/providers/claude-adapter.ts +14 -5
  199. package/src/providers/claude-managed-adapter.ts +1 -0
  200. package/src/providers/claude-managed-models.ts +47 -161
  201. package/src/providers/claude-sdk-session.ts +3 -1
  202. package/src/providers/codex-adapter.ts +14 -14
  203. package/src/providers/codex-models.ts +65 -198
  204. package/src/providers/devin-adapter.ts +1 -0
  205. package/src/providers/dsh-adapter.ts +2 -1
  206. package/src/providers/harness-version.ts +83 -7
  207. package/src/providers/opencode-adapter.ts +53 -1
  208. package/src/providers/pi-binary-root/src/extensions/codemode/worker.ts +11 -0
  209. package/src/providers/pi-codemode-runtime.ts +17 -0
  210. package/src/providers/pi-mono-adapter.ts +361 -83
  211. package/src/providers/pi-mono-extension.ts +16 -1
  212. package/src/providers/reasoning-effort.ts +44 -140
  213. package/src/providers/types.ts +8 -0
  214. package/src/rbac/legacy-policy.ts +43 -0
  215. package/src/rbac/permissions.ts +15 -0
  216. package/src/scripts-runtime/sdk-allowlist.ts +4 -0
  217. package/src/scripts-runtime/types/stdlib.d.ts +15 -0
  218. package/src/scripts-runtime/types/swarm-extension.d.ts +3 -0
  219. package/src/scripts-runtime/types/swarm-sdk.d.ts +15 -0
  220. package/src/server.ts +6 -0
  221. package/src/slack/assistant.ts +13 -0
  222. package/src/slack/message-text.ts +56 -2
  223. package/src/slack/render-v2.ts +87 -37
  224. package/src/slack/session-status.ts +541 -0
  225. package/src/slack/thread-buffer.ts +10 -2
  226. package/src/tasks/sibling-awareness.ts +3 -2
  227. package/src/telemetry.ts +5 -4
  228. package/src/templates.d.ts +6 -0
  229. package/src/tests/agents-list-model-display.test.ts +4 -6
  230. package/src/tests/api-key-auth-failure-route.test.ts +142 -0
  231. package/src/tests/api-key-tracking.test.ts +368 -1
  232. package/src/tests/base-prompt.test.ts +43 -2
  233. package/src/tests/claude-adapter.test.ts +68 -0
  234. package/src/tests/claude-managed-adapter.test.ts +12 -18
  235. package/src/tests/codex-adapter.test.ts +2 -1
  236. package/src/tests/codex-auth-failure.test.ts +52 -0
  237. package/src/tests/codex-gpt6-release.test.ts +66 -5
  238. package/src/tests/codex-login.test.ts +116 -0
  239. package/src/tests/context-window.test.ts +7 -5
  240. package/src/tests/credential-exhaustion-policy.test.ts +118 -3
  241. package/src/tests/credential-outcome-report.test.ts +171 -0
  242. package/src/tests/credential-status-api.test.ts +103 -2
  243. package/src/tests/db-extraction-contract.test.ts +1 -0
  244. package/src/tests/db-task-read-contract.test.ts +10 -1
  245. package/src/tests/db-task-write-contract.test.ts +535 -2
  246. package/src/tests/docs-index-footprint.test.js +3 -3
  247. package/src/tests/dokploy-deploy.test.ts +315 -0
  248. package/src/tests/dsh-adapter.test.ts +1 -1
  249. package/src/tests/explicit-model-validation.test.ts +583 -0
  250. package/src/tests/extensions-pre-task.test.ts +73 -0
  251. package/src/tests/fetch-resolved-env.test.ts +46 -0
  252. package/src/tests/hang-watchdog-worker.ts +47 -0
  253. package/src/tests/hang-watchdog.test.ts +45 -0
  254. package/src/tests/hang-watchdog.ts +30 -0
  255. package/src/tests/harness-model-guard.test.ts +123 -0
  256. package/src/tests/harness-model-support.test.ts +374 -0
  257. package/src/tests/harness-version.test.ts +70 -3
  258. package/src/tests/heartbeat-checklist-config.test.ts +71 -0
  259. package/src/tests/heartbeat-checklist.test.ts +4 -2
  260. package/src/tests/heartbeat-orphan-resume.test.ts +48 -0
  261. package/src/tests/http-task-write-ownership.test.ts +172 -0
  262. package/src/tests/human-free-flag.test.ts +279 -0
  263. package/src/tests/human-free-oracle.ts +57 -0
  264. package/src/tests/human-free-reclassify.test.ts +669 -0
  265. package/src/tests/memory-fts-populate.test.ts +139 -0
  266. package/src/tests/memory-http-recall-gating.test.ts +125 -1
  267. package/src/tests/migration-046-budgets.test.ts +3 -3
  268. package/src/tests/model-catalog-migration.test.ts +134 -0
  269. package/src/tests/model-catalog-table.test.ts +249 -0
  270. package/src/tests/model-catalog-write-access.test.ts +387 -0
  271. package/src/tests/model-rate-limit-windows.test.ts +19 -0
  272. package/src/tests/model-tier-resolution.test.ts +611 -0
  273. package/src/tests/models-catalog.test.ts +1 -1
  274. package/src/tests/multi-runtime-enabled-stats.test.ts +65 -1
  275. package/src/tests/opencode-adapter.test.ts +157 -2
  276. package/src/tests/package-publish.test.ts +137 -36
  277. package/src/tests/pi-codemode.test.ts +246 -0
  278. package/src/tests/pi-mono-adapter.test.ts +3 -0
  279. package/src/tests/pi-native-mcp.test.ts +193 -0
  280. package/src/tests/pi-tool-exposure.test.ts +374 -0
  281. package/src/tests/preload.ts +3 -0
  282. package/src/tests/pricing-routes.test.ts +2 -2
  283. package/src/tests/prompt-template-session.test.ts +5 -3
  284. package/src/tests/rate-limit-event.test.ts +65 -0
  285. package/src/tests/rate-limit-outcome.test.ts +90 -0
  286. package/src/tests/rbac-engine.test.ts +77 -3
  287. package/src/tests/reasoning-effort.test.ts +109 -0
  288. package/src/tests/refresh-modelsdev-carryforward.test.ts +5 -5
  289. package/src/tests/runner-key-completion-outcome.test.ts +112 -0
  290. package/src/tests/runner-key-outcome-late-reset.test.ts +224 -0
  291. package/src/tests/runner-registration-retry.test.ts +149 -0
  292. package/src/tests/runtime-model-catalog.test.ts +86 -0
  293. package/src/tests/script-connections.test.ts +9 -0
  294. package/src/tests/seat-mismatch-report.test.ts +85 -0
  295. package/src/tests/seed-scripts.test.ts +138 -0
  296. package/src/tests/seed.test.ts +25 -0
  297. package/src/tests/session-costs.test.ts +14 -11
  298. package/src/tests/slack-message-text.test.ts +101 -0
  299. package/src/tests/slack-render-v2.test.ts +96 -0
  300. package/src/tests/slack-session-status.test.ts +626 -0
  301. package/src/tests/slack-thread-buffer-context.test.ts +93 -0
  302. package/src/tests/status.test.ts +29 -0
  303. package/src/tests/steering-promotion.test.ts +51 -0
  304. package/src/tests/store-progress-ownership.test.ts +136 -0
  305. package/src/tests/subscription-plans.test.ts +28 -0
  306. package/src/tests/task-cascade-fail.test.ts +148 -2
  307. package/src/tests/task-citations.test.ts +3 -2
  308. package/src/tests/tool-annotations.test.ts +1 -1
  309. package/src/tests/usage-cache.test.ts +166 -0
  310. package/src/tests/workflow-agent-task.test.ts +30 -0
  311. package/src/tests/workflow-executors.test.ts +5 -2
  312. package/src/tests/workflow-system-one-decision-review.test.ts +1021 -0
  313. package/src/tests/workflow-system-one-decision-save-warnings.test.ts +365 -0
  314. package/src/tests/workflow-system-one-decision.test.ts +2063 -0
  315. package/src/tests/workflow-triggers-v2.test.ts +320 -0
  316. package/src/tools/model-catalog/index.ts +137 -0
  317. package/src/tools/schedules/create-schedule.ts +17 -2
  318. package/src/tools/schedules/patch-schedule.ts +31 -1
  319. package/src/tools/schedules/update-schedule.ts +31 -1
  320. package/src/tools/send-task.ts +18 -1
  321. package/src/tools/store-progress.ts +49 -4
  322. package/src/tools/task-action.ts +14 -1
  323. package/src/tools/tool-config.ts +3 -1
  324. package/src/tools/workflows/create-workflow.ts +17 -4
  325. package/src/tools/workflows/patch-workflow-node.ts +17 -7
  326. package/src/tools/workflows/patch-workflow.ts +9 -2
  327. package/src/tools/workflows/update-workflow.ts +17 -4
  328. package/src/types.ts +41 -1
  329. package/src/utils/codex-auth-failure.ts +34 -0
  330. package/src/utils/context-window.ts +47 -53
  331. package/src/utils/credentials.ts +72 -30
  332. package/src/utils/error-tracker.ts +80 -0
  333. package/src/utils/harness-cli-version.ts +115 -0
  334. package/src/utils/harness-model-error.ts +33 -0
  335. package/src/utils/model-rate-limit-windows.ts +12 -0
  336. package/src/utils/runtime-model-catalog.ts +152 -0
  337. package/src/utils/spawn-model-guard.ts +43 -0
  338. package/src/utils/subscription-plans.ts +22 -0
  339. package/src/workflows/approval-resolution.ts +39 -0
  340. package/src/workflows/definition.ts +7 -0
  341. package/src/workflows/engine.ts +69 -1
  342. package/src/workflows/executors/agent-task.ts +16 -6
  343. package/src/workflows/executors/base.ts +53 -0
  344. package/src/workflows/executors/human-in-the-loop.ts +8 -8
  345. package/src/workflows/executors/index.ts +1 -0
  346. package/src/workflows/executors/registry.ts +2 -0
  347. package/src/workflows/executors/system-one-decision.ts +1232 -0
  348. package/src/workflows/executors/system-one-providers.ts +301 -0
  349. package/src/workflows/executors/workflow-llm.ts +13 -1
  350. package/src/workflows/model-validation.ts +45 -0
  351. package/src/workflows/patch-definition.ts +5 -0
  352. package/src/workflows/readiness.ts +86 -0
  353. package/src/workflows/recovery.ts +12 -12
  354. package/src/workflows/resume.ts +23 -9
  355. package/src/workflows/triggers.ts +85 -0
  356. package/templates/schedules/daily-blocker-digest/content.md +4 -5
  357. package/templates/skills/agent-browser/SKILL.md +6 -5
  358. package/templates/skills/agent-browser/content.md +6 -5
  359. package/templates/skills/heartbeat-runbook/config.json +1 -1
  360. package/templates/skills/heartbeat-runbook/content.md +2 -2
  361. package/templates/skills/swarm-scripts/SKILL.md +1 -1
  362. package/templates/skills/swarm-scripts/content.md +1 -1
  363. package/templates/skills/workflow-iterate/content.md +82 -1
  364. package/templates/workflows/claude-code-changelog-watch/content.md +2 -0
  365. package/templates/workflows/pr-review-status-sweep/content.md +2 -0
  366. package/dist/boot-seeds-s3q01xj3.js +0 -26
  367. package/dist/claude-sdk-session-t442qz6f.js +0 -39108
  368. package/dist/cli-0xjkj1j7.js +0 -61
  369. package/dist/cli-20cj37vt.js +0 -335561
  370. package/dist/cli-2djtr51b.js +0 -48
  371. package/dist/cli-65hjmev5.js +0 -1141
  372. package/dist/cli-aw1jwp1r.js +0 -14075
  373. package/dist/cli-h967nb6r.js +0 -6603
  374. package/dist/cli-vapyk8sw.js +0 -20
  375. package/dist/cli-ws6rqycm.js +0 -247
  376. package/dist/pricing-refresh-v1cbr9te.js +0 -27
  377. package/src/providers/modelsdev-reasoning.json +0 -6453
  378. package/dist/{index-f24115ge.js → index-2wsdsnmm.js} +3 -3
@@ -1,5 +1,17 @@
1
1
  import {
2
- __esm
2
+ contentSha256,
3
+ init_profile_sync
4
+ } from "./cli-25fcq4b4.js";
5
+ import {
6
+ getDb,
7
+ getDbClient,
8
+ init_db,
9
+ isSqliteVecAvailable
10
+ } from "./cli-qydf22qq.js";
11
+ import {
12
+ __esm,
13
+ __export,
14
+ __toCommonJS
3
15
  } from "./cli-bc05qbss.js";
4
16
 
5
17
  // node_modules/openai/internal/tslib.mjs
@@ -7951,70 +7963,12 @@ var init_client = __esm(() => {
7951
7963
  });
7952
7964
 
7953
7965
  // node_modules/openai/azure.mjs
7954
- var AzureOpenAI, _deployments_endpoints;
7966
+ var _deployments_endpoints;
7955
7967
  var init_azure = __esm(() => {
7956
7968
  init_headers();
7957
7969
  init_error2();
7958
7970
  init_utils2();
7959
7971
  init_client();
7960
- AzureOpenAI = class AzureOpenAI extends OpenAI {
7961
- constructor({ baseURL = readEnv("OPENAI_BASE_URL"), apiKey = readEnv("AZURE_OPENAI_API_KEY"), apiVersion = readEnv("OPENAI_API_VERSION"), endpoint, deployment, azureADTokenProvider, dangerouslyAllowBrowser, ...opts } = {}) {
7962
- if (!apiVersion) {
7963
- throw new OpenAIError("The OPENAI_API_VERSION environment variable is missing or empty; either provide it, or instantiate the AzureOpenAI client with an apiVersion option, like new AzureOpenAI({ apiVersion: 'My API Version' }).");
7964
- }
7965
- if (typeof azureADTokenProvider === "function") {
7966
- dangerouslyAllowBrowser = true;
7967
- }
7968
- if (!azureADTokenProvider && !apiKey) {
7969
- throw new OpenAIError("Missing credentials. Please pass one of `apiKey` and `azureADTokenProvider`, or set the `AZURE_OPENAI_API_KEY` environment variable.");
7970
- }
7971
- if (azureADTokenProvider && apiKey) {
7972
- throw new OpenAIError("The `apiKey` and `azureADTokenProvider` arguments are mutually exclusive; only one can be passed at a time.");
7973
- }
7974
- opts.defaultQuery = { ...opts.defaultQuery, "api-version": apiVersion };
7975
- if (!baseURL) {
7976
- if (!endpoint) {
7977
- endpoint = process.env["AZURE_OPENAI_ENDPOINT"];
7978
- }
7979
- if (!endpoint) {
7980
- throw new OpenAIError("Must provide one of the `baseURL` or `endpoint` arguments, or the `AZURE_OPENAI_ENDPOINT` environment variable");
7981
- }
7982
- baseURL = `${endpoint}/openai`;
7983
- } else {
7984
- if (endpoint) {
7985
- throw new OpenAIError("baseURL and endpoint are mutually exclusive");
7986
- }
7987
- }
7988
- super({
7989
- apiKey: azureADTokenProvider ?? apiKey,
7990
- baseURL,
7991
- ...opts,
7992
- ...dangerouslyAllowBrowser !== undefined ? { dangerouslyAllowBrowser } : {}
7993
- });
7994
- this.apiVersion = "";
7995
- this.apiVersion = apiVersion;
7996
- this.deploymentName = deployment;
7997
- }
7998
- async buildRequest(options, props = {}) {
7999
- if (_deployments_endpoints.has(options.path) && options.method === "post" && options.body !== undefined) {
8000
- if (!isObj(options.body)) {
8001
- throw new Error("Expected request body to be an object");
8002
- }
8003
- const model = this.deploymentName || options.body["model"] || options.__metadata?.["model"];
8004
- if (model !== undefined && !this.baseURL.includes("/deployments")) {
8005
- options.path = `/deployments/${model}${options.path}`;
8006
- }
8007
- }
8008
- return super.buildRequest(options, props);
8009
- }
8010
- async authHeaders(opts, schemes) {
8011
- const security = schemes ?? { bearerAuth: true, adminAPIKeyAuth: true };
8012
- if (security.bearerAuth && typeof this._options.apiKey === "string") {
8013
- return buildHeaders([{ "api-key": this.apiKey }]);
8014
- }
8015
- return super.authHeaders(opts, security);
8016
- }
8017
- };
8018
7972
  _deployments_endpoints = new Set([
8019
7973
  "/completions",
8020
7974
  "/chat/completions",
@@ -8039,4 +7993,1141 @@ var init_openai = __esm(() => {
8039
7993
  init_azure();
8040
7994
  });
8041
7995
 
8042
- export { OpenAI, AzureOpenAI, init_openai };
7996
+ // src/be/memory/constants.ts
7997
+ function numEnv(key, fallback) {
7998
+ const val = process.env[key];
7999
+ if (val === undefined)
8000
+ return fallback;
8001
+ const parsed = Number(val);
8002
+ return Number.isNaN(parsed) ? fallback : parsed;
8003
+ }
8004
+ function recencyDecayHalfLifeDays(source = "task_completion") {
8005
+ const raw = process.env.MEMORY_RECENCY_HALF_LIFE_DAYS;
8006
+ if (raw != null && raw !== "") {
8007
+ const parsed = Number(raw);
8008
+ if (Number.isFinite(parsed))
8009
+ return parsed;
8010
+ }
8011
+ return DEFAULT_RECENCY_DECAY_HALF_LIFE[source];
8012
+ }
8013
+ function minSimilarity() {
8014
+ return numEnv("MEMORY_MIN_SIMILARITY", 0.1);
8015
+ }
8016
+ function accessBoostMaxMultiplier() {
8017
+ return numEnv("MEMORY_ACCESS_BOOST_MAX", 1.5);
8018
+ }
8019
+ function isHybridSearchEnabled() {
8020
+ const val = process.env.MEMORY_HYBRID_SEARCH?.trim().toLowerCase();
8021
+ return val !== "0" && val !== "false";
8022
+ }
8023
+ function isGraphExpansionEnabled() {
8024
+ const val = process.env.MEMORY_GRAPH_EXPANSION?.trim().toLowerCase();
8025
+ return val !== "0" && val !== "false";
8026
+ }
8027
+ var TTL_DEFAULTS, DEFAULT_RECENCY_DECAY_HALF_LIFE, SOURCE_QUALITY_MULTIPLIER, ACCESS_BOOST_RECENCY_WINDOW_HOURS, CANDIDATE_SET_MULTIPLIER, EMBEDDING_DIMENSIONS, DEFAULT_EMBEDDING_MODEL = "openai/text-embedding-3-small", PROTECTED_SOURCES;
8028
+ var init_constants = __esm(() => {
8029
+ TTL_DEFAULTS = {
8030
+ task_completion: 7,
8031
+ session_summary: 3,
8032
+ file_index: 30,
8033
+ manual: null
8034
+ };
8035
+ DEFAULT_RECENCY_DECAY_HALF_LIFE = {
8036
+ manual: Number.POSITIVE_INFINITY,
8037
+ file_index: 180,
8038
+ task_completion: 14,
8039
+ session_summary: 7
8040
+ };
8041
+ SOURCE_QUALITY_MULTIPLIER = {
8042
+ manual: 1.5,
8043
+ file_index: 1,
8044
+ task_completion: 0.7,
8045
+ session_summary: 0.5
8046
+ };
8047
+ ACCESS_BOOST_RECENCY_WINDOW_HOURS = numEnv("MEMORY_ACCESS_RECENCY_HOURS", 48);
8048
+ CANDIDATE_SET_MULTIPLIER = numEnv("MEMORY_CANDIDATE_MULTIPLIER", 3);
8049
+ EMBEDDING_DIMENSIONS = numEnv("EMBEDDING_DIMENSIONS", 512);
8050
+ PROTECTED_SOURCES = new Set(["manual"]);
8051
+ });
8052
+
8053
+ // src/be/memory/providers/openai-embedding.ts
8054
+ var exports_openai_embedding = {};
8055
+ __export(exports_openai_embedding, {
8056
+ OpenAIEmbeddingProvider: () => OpenAIEmbeddingProvider
8057
+ });
8058
+
8059
+ class OpenAIEmbeddingProvider {
8060
+ name;
8061
+ dimensions;
8062
+ client = null;
8063
+ model;
8064
+ apiKey;
8065
+ constructor(config) {
8066
+ this.apiKey = config?.apiKey ?? process.env.EMBEDDING_API_KEY ?? process.env.OPENAI_API_KEY;
8067
+ this.model = config?.model ?? process.env.EMBEDDING_MODEL ?? "text-embedding-3-small";
8068
+ this.dimensions = config?.dimensions ?? EMBEDDING_DIMENSIONS;
8069
+ this.name = config?.model ? `openai/${config.model}` : process.env.EMBEDDING_MODEL ?? DEFAULT_EMBEDDING_MODEL;
8070
+ }
8071
+ isConfigured() {
8072
+ return !!this.apiKey;
8073
+ }
8074
+ getClient() {
8075
+ if (!this.apiKey)
8076
+ return null;
8077
+ if (!this.client)
8078
+ this.client = new OpenAI({
8079
+ baseURL: process.env.EMBEDDING_API_BASE_URL,
8080
+ apiKey: this.apiKey
8081
+ });
8082
+ return this.client;
8083
+ }
8084
+ async embed(text) {
8085
+ const client = this.getClient();
8086
+ if (!client)
8087
+ return null;
8088
+ try {
8089
+ const cleaned = text.replace(/[\n\r]/g, " ").trim();
8090
+ if (!cleaned)
8091
+ return null;
8092
+ const response = await client.embeddings.create({
8093
+ model: this.model,
8094
+ input: cleaned,
8095
+ dimensions: this.dimensions,
8096
+ encoding_format: "float"
8097
+ });
8098
+ const values2 = response.data[0]?.embedding;
8099
+ if (!values2)
8100
+ return null;
8101
+ if (values2.length !== this.dimensions) {
8102
+ console.error(`[memory] Embedding dimension mismatch: expected=${this.dimensions} got=${values2.length}. Provider may not support the 'dimensions' parameter.`);
8103
+ return null;
8104
+ }
8105
+ return new Float32Array(values2);
8106
+ } catch (err) {
8107
+ console.error("[memory] Embedding failed:", err.message);
8108
+ return null;
8109
+ }
8110
+ }
8111
+ async embedBatch(texts) {
8112
+ const client = this.getClient();
8113
+ if (!client)
8114
+ return texts.map(() => null);
8115
+ const cleaned = texts.map((t) => t.replace(/[\n\r]/g, " ").trim());
8116
+ const nonEmptyIndices = [];
8117
+ const nonEmptyTexts = [];
8118
+ for (let i = 0;i < cleaned.length; i++) {
8119
+ if (cleaned[i]) {
8120
+ nonEmptyIndices.push(i);
8121
+ nonEmptyTexts.push(cleaned[i]);
8122
+ }
8123
+ }
8124
+ if (nonEmptyTexts.length === 0)
8125
+ return texts.map(() => null);
8126
+ try {
8127
+ const response = await client.embeddings.create({
8128
+ model: this.model,
8129
+ input: nonEmptyTexts,
8130
+ dimensions: this.dimensions,
8131
+ encoding_format: "float"
8132
+ });
8133
+ const results = texts.map(() => null);
8134
+ for (const item of response.data) {
8135
+ const originalIndex = nonEmptyIndices[item.index];
8136
+ if (originalIndex !== undefined && item.embedding) {
8137
+ if (item.embedding.length !== this.dimensions) {
8138
+ console.error(`[memory] Batch embedding dimension mismatch: expected=${this.dimensions} got=${item.embedding.length}. Provider may not support the 'dimensions' parameter.`);
8139
+ continue;
8140
+ }
8141
+ results[originalIndex] = new Float32Array(item.embedding);
8142
+ }
8143
+ }
8144
+ return results;
8145
+ } catch (err) {
8146
+ console.error("[memory] Batch embedding failed:", err.message);
8147
+ return texts.map(() => null);
8148
+ }
8149
+ }
8150
+ }
8151
+ var init_openai_embedding = __esm(() => {
8152
+ init_openai();
8153
+ init_constants();
8154
+ });
8155
+
8156
+ // src/be/embedding.ts
8157
+ function cosineSimilarity(a, b) {
8158
+ if (a.length !== b.length)
8159
+ throw new Error("Vectors must have the same length");
8160
+ if (a.length === 0)
8161
+ return 0;
8162
+ let dotProduct = 0;
8163
+ let normA = 0;
8164
+ let normB = 0;
8165
+ for (let i = 0;i < a.length; i++) {
8166
+ const ai = a[i];
8167
+ const bi = b[i];
8168
+ dotProduct += ai * bi;
8169
+ normA += ai * ai;
8170
+ normB += bi * bi;
8171
+ }
8172
+ const denominator = Math.sqrt(normA) * Math.sqrt(normB);
8173
+ if (denominator === 0)
8174
+ return 0;
8175
+ return dotProduct / denominator;
8176
+ }
8177
+ function serializeEmbedding(embedding) {
8178
+ return Buffer.from(embedding.buffer, embedding.byteOffset, embedding.byteLength);
8179
+ }
8180
+ function deserializeEmbedding(buffer) {
8181
+ const copy = new ArrayBuffer(buffer.length);
8182
+ const view = new Uint8Array(copy);
8183
+ view.set(buffer);
8184
+ return new Float32Array(copy);
8185
+ }
8186
+ var init_embedding = () => {};
8187
+
8188
+ // src/be/memory/reranker.ts
8189
+ function recencyDecay(createdAt, now, source) {
8190
+ const halfLife = recencyDecayHalfLifeDays(source);
8191
+ if (!Number.isFinite(halfLife))
8192
+ return 1;
8193
+ const ageDays = (now.getTime() - new Date(createdAt).getTime()) / MS_PER_DAY;
8194
+ if (ageDays <= 0)
8195
+ return 1;
8196
+ return 2 ** (-ageDays / halfLife);
8197
+ }
8198
+ function accessBoost(accessedAt, accessCount, now) {
8199
+ if (accessCount <= 0)
8200
+ return 1;
8201
+ const hoursSinceAccess = (now.getTime() - new Date(accessedAt).getTime()) / MS_PER_HOUR;
8202
+ const recencyFactor = hoursSinceAccess <= ACCESS_BOOST_RECENCY_WINDOW_HOURS ? 1 : 0.5;
8203
+ const boost = 1 + Math.min(accessCount / 10, accessBoostMaxMultiplier() - 1) * recencyFactor;
8204
+ return boost;
8205
+ }
8206
+ function sourceQuality(source) {
8207
+ return SOURCE_QUALITY_MULTIPLIER[source] ?? 1;
8208
+ }
8209
+ function readDemotionFloor() {
8210
+ const raw = process.env.MEMORY_DEMOTION_FLOOR;
8211
+ const n = raw == null || raw === "" ? 1 : Number(raw);
8212
+ return Number.isFinite(n) ? n : 1;
8213
+ }
8214
+ function usefulness(alpha, beta) {
8215
+ const denom = alpha + beta;
8216
+ if (denom <= 0)
8217
+ return 1;
8218
+ const mean = alpha / denom;
8219
+ return Math.max(readDemotionFloor(), Math.min(2, 2 * mean));
8220
+ }
8221
+ function computeScore(candidate, now) {
8222
+ const decay = candidate.recencyDecayApplied ? 1 : recencyDecay(candidate.createdAt, now, candidate.source);
8223
+ return candidate.similarity * decay * accessBoost(candidate.accessedAt, candidate.accessCount, now) * sourceQuality(candidate.source) * usefulness(candidate.alpha, candidate.beta);
8224
+ }
8225
+ function rerank(candidates, options) {
8226
+ const { limit: limit2, now = new Date } = options;
8227
+ const uncapped = new Map;
8228
+ for (const candidate of candidates)
8229
+ uncapped.set(candidate.id, computeScore(candidate, now));
8230
+ const byId = new Map(candidates.map((c) => [c.id, c]));
8231
+ const capped = new Map;
8232
+ const cappedScore = (candidate, seen) => {
8233
+ const cached = capped.get(candidate.id);
8234
+ if (cached !== undefined)
8235
+ return cached;
8236
+ let score = uncapped.get(candidate.id);
8237
+ const parent = candidate.graphParentId ? byId.get(candidate.graphParentId) : undefined;
8238
+ if (parent && !seen.has(parent.id)) {
8239
+ seen.add(candidate.id);
8240
+ score = Math.min(score, cappedScore(parent, seen));
8241
+ }
8242
+ capped.set(candidate.id, score);
8243
+ return score;
8244
+ };
8245
+ const scored = candidates.map((candidate) => {
8246
+ const rawSimilarity = candidate.rawSimilarity ?? candidate.similarity;
8247
+ const compositeScore = cappedScore(candidate, new Set);
8248
+ return {
8249
+ ...candidate,
8250
+ rawSimilarity,
8251
+ compositeScore,
8252
+ similarity: compositeScore
8253
+ };
8254
+ });
8255
+ scored.sort((a, b) => b.similarity - a.similarity || b.rawSimilarity - a.rawSimilarity);
8256
+ return scored.slice(0, limit2);
8257
+ }
8258
+ var MS_PER_DAY, MS_PER_HOUR;
8259
+ var init_reranker = __esm(() => {
8260
+ init_constants();
8261
+ MS_PER_DAY = 1000 * 60 * 60 * 24;
8262
+ MS_PER_HOUR = 1000 * 60 * 60;
8263
+ });
8264
+
8265
+ // src/be/memory/providers/sqlite-store.ts
8266
+ var exports_sqlite_store = {};
8267
+ __export(exports_sqlite_store, {
8268
+ FTS_DELETE_EXTRA_SQL: () => FTS_DELETE_EXTRA_SQL,
8269
+ FTS_MISSING_IDS_SQL: () => FTS_MISSING_IDS_SQL,
8270
+ SqliteMemoryStore: () => SqliteMemoryStore,
8271
+ applyEditMode: () => applyEditMode,
8272
+ computeRrfScore: () => computeRrfScore,
8273
+ fusedSimilarity: () => fusedSimilarity,
8274
+ rowToCandidate: () => rowToCandidate
8275
+ });
8276
+ function rowToAgentMemory(row) {
8277
+ return {
8278
+ id: row.id,
8279
+ agentId: row.agentId,
8280
+ scope: row.scope,
8281
+ key: row.key ?? null,
8282
+ name: row.name,
8283
+ content: row.content,
8284
+ summary: row.summary,
8285
+ source: row.source,
8286
+ sourceTaskId: row.sourceTaskId,
8287
+ sourcePath: row.sourcePath,
8288
+ chunkIndex: row.chunkIndex,
8289
+ totalChunks: row.totalChunks,
8290
+ tags: JSON.parse(row.tags || "[]"),
8291
+ createdAt: row.createdAt,
8292
+ updatedAt: row.updatedAt ?? null,
8293
+ accessedAt: row.accessedAt,
8294
+ expiresAt: row.expiresAt ?? null,
8295
+ accessCount: row.accessCount ?? 0,
8296
+ embeddingModel: row.embeddingModel ?? null,
8297
+ contentHash: row.contentHash ?? null,
8298
+ version: row.version ?? 1
8299
+ };
8300
+ }
8301
+ function rowToCandidate(row, similarity) {
8302
+ return {
8303
+ ...rowToAgentMemory(row),
8304
+ similarity,
8305
+ accessCount: row.accessCount ?? 0,
8306
+ expiresAt: row.expiresAt ?? null,
8307
+ embeddingModel: row.embeddingModel ?? null,
8308
+ alpha: row.alpha ?? 1,
8309
+ beta: row.beta ?? 1
8310
+ };
8311
+ }
8312
+ function retrievalSourceFor(sources) {
8313
+ if (sources.has("fts") && sources.has("vec"))
8314
+ return "hybrid";
8315
+ if (sources.has("fts"))
8316
+ return "fts";
8317
+ if (sources.has("vec"))
8318
+ return "vec";
8319
+ return "fallback";
8320
+ }
8321
+ function computeRrfScore(rank, decayFactor, k = 60) {
8322
+ return 1 / (k + rank + 1) * decayFactor;
8323
+ }
8324
+ function fusedSimilarity(cosine, rrfScore, k = 60) {
8325
+ const agreement = Math.min(1, rrfScore * (k + 1) / 2);
8326
+ return cosine * (0.5 + 0.5 * agreement);
8327
+ }
8328
+ function applyEditMode(mode, currentContent, fields) {
8329
+ if (mode === "replace") {
8330
+ if (fields.content == null)
8331
+ throw new Error("replace mode requires content");
8332
+ return fields.content;
8333
+ }
8334
+ if (!fields.oldString || fields.newString == null) {
8335
+ throw new Error("exact mode requires oldString and newString");
8336
+ }
8337
+ const first = currentContent.indexOf(fields.oldString);
8338
+ if (first === -1)
8339
+ throw new Error("oldString not found");
8340
+ if (currentContent.indexOf(fields.oldString, first + fields.oldString.length) !== -1) {
8341
+ throw new Error("oldString is ambiguous");
8342
+ }
8343
+ return currentContent.slice(0, first) + fields.newString + currentContent.slice(first + fields.oldString.length);
8344
+ }
8345
+ function computeExpiresAt(source) {
8346
+ const ttlDays = TTL_DEFAULTS[source];
8347
+ if (ttlDays == null)
8348
+ return null;
8349
+ return new Date(Date.now() + ttlDays * 86400000).toISOString();
8350
+ }
8351
+
8352
+ class SqliteMemoryStore {
8353
+ vecInitialized = false;
8354
+ ftsInitialized = false;
8355
+ ftsPopulate = null;
8356
+ lastPopulate = null;
8357
+ constructor() {
8358
+ this.ensureVecTable();
8359
+ this.ensureFtsTable();
8360
+ }
8361
+ ensureFtsTable() {
8362
+ if (this.ftsInitialized)
8363
+ return;
8364
+ const db = getDb();
8365
+ try {
8366
+ db.run(`
8367
+ CREATE VIRTUAL TABLE IF NOT EXISTS memory_fts USING fts5(
8368
+ memory_id UNINDEXED,
8369
+ name,
8370
+ content,
8371
+ tokenize='porter unicode61'
8372
+ )
8373
+ `);
8374
+ this.ftsInitialized = true;
8375
+ this.ftsPopulate = this.populateFtsTable().catch((err) => {
8376
+ console.error("[memory-fts] Failed to populate memory_fts:", err.message);
8377
+ });
8378
+ } catch (err) {
8379
+ this.ftsInitialized = false;
8380
+ console.error("[memory-fts] Failed to initialize memory_fts:", err.message);
8381
+ }
8382
+ }
8383
+ async getFtsTableSchema() {
8384
+ try {
8385
+ const row = await getDbClient().get("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memory_fts'");
8386
+ return row?.sql ?? null;
8387
+ } catch {
8388
+ return null;
8389
+ }
8390
+ }
8391
+ async populateFtsTable() {
8392
+ const client = getDbClient();
8393
+ const startedAt = performance.now();
8394
+ const deletedExtra = await client.run(FTS_DELETE_EXTRA_SQL);
8395
+ if (deletedExtra.changes > 0) {
8396
+ console.warn(`[memory-fts] removed_extra_rows count=${deletedExtra.changes}`);
8397
+ }
8398
+ const missing = await client.query(FTS_MISSING_IDS_SQL);
8399
+ for (let i = 0;i < missing.length; i += FTS_POPULATE_BATCH_SIZE) {
8400
+ const ids = missing.slice(i, i + FTS_POPULATE_BATCH_SIZE).map((row) => row.id);
8401
+ const placeholders = ids.map(() => "?").join(",");
8402
+ await client.run(`INSERT INTO memory_fts(memory_id, name, content)
8403
+ SELECT m.id, m.name, m.content
8404
+ FROM agent_memory m
8405
+ WHERE m.id IN (${placeholders})
8406
+ AND m.id NOT IN (SELECT memory_id FROM memory_fts WHERE memory_id IS NOT NULL)`, ids);
8407
+ await new Promise((resolve) => setImmediate(resolve));
8408
+ }
8409
+ console.log(`[memory-fts] populate missing=${missing.length} ms=${Math.round(performance.now() - startedAt)}`);
8410
+ }
8411
+ whenFtsPopulated() {
8412
+ return this.ftsPopulate ?? Promise.resolve();
8413
+ }
8414
+ async syncFtsRow(memoryId, name, content) {
8415
+ if (!this.ftsInitialized && !await this.getFtsTableSchema())
8416
+ return;
8417
+ try {
8418
+ await getDbClient().run("DELETE FROM memory_fts WHERE memory_id = ?", [memoryId]);
8419
+ await getDbClient().run("INSERT INTO memory_fts(memory_id, name, content) VALUES (?, ?, ?)", [
8420
+ memoryId,
8421
+ name,
8422
+ content
8423
+ ]);
8424
+ } catch (err) {
8425
+ console.error(`[memory-fts] sync failed memory_id=${memoryId}: ${err.message}`);
8426
+ }
8427
+ }
8428
+ async deleteFtsRows(ids) {
8429
+ if (ids.length === 0 || !await this.getFtsTableSchema())
8430
+ return;
8431
+ const placeholders = ids.map(() => "?").join(",");
8432
+ await getDbClient().run(`DELETE FROM memory_fts WHERE memory_id IN (${placeholders})`, ids);
8433
+ }
8434
+ ensureVecTable() {
8435
+ if (this.vecInitialized)
8436
+ return;
8437
+ if (!isSqliteVecAvailable()) {
8438
+ console.warn("[memory-vec] sqlite-vec extension_loaded=false; retrieval_mode=fallback");
8439
+ return;
8440
+ }
8441
+ const db = getDb();
8442
+ try {
8443
+ console.log(`[memory-vec] sqlite-vec extension_loaded=true vector_dimensions=${EMBEDDING_DIMENSIONS}`);
8444
+ const existingSchema = this.getVecTableSchema();
8445
+ if (existingSchema && !existingSchema.includes("distance_metric=cosine")) {
8446
+ console.warn("[memory-vec] Existing memory_vec table is missing cosine distance metric; rebuilding from agent_memory");
8447
+ db.run("DROP TABLE memory_vec");
8448
+ }
8449
+ db.run(`
8450
+ CREATE VIRTUAL TABLE IF NOT EXISTS memory_vec USING vec0(
8451
+ memory_id TEXT PRIMARY KEY,
8452
+ embedding float[${EMBEDDING_DIMENSIONS}] distance_metric=cosine
8453
+ )
8454
+ `);
8455
+ const healthBefore = this.getHealthCounts();
8456
+ if (healthBefore.missingFromVec > 0 || healthBefore.extraInVec > 0) {
8457
+ this.populateVecTable(healthBefore.memoryVec);
8458
+ } else {
8459
+ console.log(`[memory-vec] populate skipped attempted=0 inserted=0 memory_vec=${healthBefore.memoryVec} valid_embedding=${healthBefore.validEmbedding}`);
8460
+ }
8461
+ this.vecInitialized = true;
8462
+ } catch (err) {
8463
+ this.vecInitialized = false;
8464
+ console.error("[memory-vec] Failed to initialize memory_vec:", err.message);
8465
+ }
8466
+ }
8467
+ getVecTableSchema() {
8468
+ try {
8469
+ return getDb().prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memory_vec'").get()?.sql ?? null;
8470
+ } catch {
8471
+ return null;
8472
+ }
8473
+ }
8474
+ getVecCount() {
8475
+ if (!this.getVecTableSchema())
8476
+ return 0;
8477
+ return getDb().prepare("SELECT COUNT(*) as count FROM memory_vec").get()?.count ?? 0;
8478
+ }
8479
+ populateVecTable(beforeCount) {
8480
+ const db = getDb();
8481
+ const deletedExtra = db.prepare(`DELETE FROM memory_vec
8482
+ WHERE memory_id NOT IN (SELECT id FROM agent_memory)`).run();
8483
+ if (deletedExtra.changes > 0) {
8484
+ console.warn(`[memory-vec] removed_extra_rows count=${deletedExtra.changes}`);
8485
+ }
8486
+ const rows = db.prepare("SELECT id, embedding FROM agent_memory WHERE embedding IS NOT NULL").all();
8487
+ const deleteVec = db.prepare("DELETE FROM memory_vec WHERE memory_id = ?");
8488
+ const insertVec = db.prepare("INSERT INTO memory_vec(memory_id, embedding) VALUES (?, ?)");
8489
+ let attempted = 0;
8490
+ let inserted = 0;
8491
+ let skippedInvalidDimensions = 0;
8492
+ let failed = 0;
8493
+ for (const row of rows) {
8494
+ const embeddingBuffer = this.toVecBuffer(row.embedding);
8495
+ if (!embeddingBuffer) {
8496
+ skippedInvalidDimensions++;
8497
+ continue;
8498
+ }
8499
+ attempted++;
8500
+ try {
8501
+ deleteVec.run(row.id);
8502
+ insertVec.run(row.id, embeddingBuffer);
8503
+ inserted++;
8504
+ } catch (err) {
8505
+ failed++;
8506
+ console.error(`[memory-vec] populate failed memory_id=${row.id}: ${err.message}`);
8507
+ }
8508
+ }
8509
+ const afterCount = this.getVecCount();
8510
+ this.lastPopulate = {
8511
+ attempted,
8512
+ inserted,
8513
+ skippedInvalidDimensions,
8514
+ failed,
8515
+ beforeCount,
8516
+ afterCount
8517
+ };
8518
+ console.log(`[memory-vec] populate attempted=${attempted} inserted=${inserted} skipped_invalid_dimensions=${skippedInvalidDimensions} failed=${failed} before_count=${beforeCount} after_count=${afterCount}`);
8519
+ if (failed > 0 || afterCount < attempted) {
8520
+ console.error(`[memory-vec] populate incomplete attempted=${attempted} after_count=${afterCount} failed=${failed}`);
8521
+ }
8522
+ }
8523
+ toVecBuffer(embedding) {
8524
+ if (embedding instanceof Float32Array) {
8525
+ if (embedding.length !== EMBEDDING_DIMENSIONS)
8526
+ return null;
8527
+ return serializeEmbedding(embedding);
8528
+ }
8529
+ if (embedding.length !== VECTOR_BYTES)
8530
+ return null;
8531
+ return embedding;
8532
+ }
8533
+ async store(input) {
8534
+ const id = crypto.randomUUID();
8535
+ const now = new Date().toISOString();
8536
+ const expiresAt = computeExpiresAt(input.source);
8537
+ const key = input.key ?? `${input.scope}/${input.source}/${id}`;
8538
+ const contentHash = contentSha256(input.content);
8539
+ const version = 1;
8540
+ const row = await getDbClient().transaction(async (tx) => {
8541
+ const inserted = await tx.get(`INSERT INTO agent_memory (id, agentId, scope, key, name, content, summary, source, sourceTaskId, sourcePath, chunkIndex, totalChunks, tags, createdAt, updatedAt, accessedAt, expiresAt, accessCount, embeddingModel, contextKey, contentHash, version)
8542
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`, [
8543
+ id,
8544
+ input.agentId ?? null,
8545
+ input.scope,
8546
+ key,
8547
+ input.name,
8548
+ input.content,
8549
+ input.summary ?? null,
8550
+ input.source,
8551
+ input.sourceTaskId ?? null,
8552
+ input.sourcePath ?? null,
8553
+ input.chunkIndex ?? 0,
8554
+ input.totalChunks ?? 1,
8555
+ JSON.stringify(input.tags ?? []),
8556
+ now,
8557
+ now,
8558
+ now,
8559
+ expiresAt,
8560
+ 0,
8561
+ null,
8562
+ input.contextKey ?? null,
8563
+ contentHash,
8564
+ version
8565
+ ]);
8566
+ if (!inserted)
8567
+ throw new Error("Failed to create memory");
8568
+ await tx.run(`INSERT INTO agent_memory_version (id, memory_id, version, content, contentHash, intent, operation, changedByAgentId, createdAt, updatedAt, created_by, updated_by)
8569
+ VALUES (?, ?, ?, ?, ?, ?, 'create', ?, ?, ?, ?, ?)`, [
8570
+ crypto.randomUUID(),
8571
+ inserted.id,
8572
+ version,
8573
+ input.content,
8574
+ contentHash,
8575
+ input.intent ?? "create memory",
8576
+ input.agentId ?? null,
8577
+ now,
8578
+ now,
8579
+ input.agentId ?? null,
8580
+ input.agentId ?? null
8581
+ ]);
8582
+ return inserted;
8583
+ });
8584
+ await this.syncFtsRow(row.id, row.name, row.content);
8585
+ return rowToAgentMemory(row);
8586
+ }
8587
+ async storeBatch(inputs) {
8588
+ const results = [];
8589
+ await getDbClient().transaction(async () => {
8590
+ for (const input of inputs) {
8591
+ results.push(await this.store(input));
8592
+ }
8593
+ });
8594
+ return results;
8595
+ }
8596
+ async get(id) {
8597
+ const db = getDbClient();
8598
+ const row = await db.get("SELECT * FROM agent_memory WHERE id = ?", [id]);
8599
+ if (!row)
8600
+ return null;
8601
+ await db.run("UPDATE agent_memory SET accessedAt = ?, accessCount = accessCount + 1 WHERE id = ?", [new Date().toISOString(), id]);
8602
+ return rowToAgentMemory(row);
8603
+ }
8604
+ async peek(id) {
8605
+ const row = await getDbClient().get("SELECT * FROM agent_memory WHERE id = ?", [
8606
+ id
8607
+ ]);
8608
+ if (!row)
8609
+ return null;
8610
+ return rowToAgentMemory(row);
8611
+ }
8612
+ async search(embedding, agentId, options = {}) {
8613
+ const { scope = "all", limit: limit2 = 10, source, isLead = false, includeExpired = false } = options;
8614
+ const health = this.getHealth();
8615
+ if (isHybridSearchEnabled() && options.queryText && this.ftsInitialized && await this.getFtsTableSchema() && health.retrievalMode === "vec" && embedding.length === EMBEDDING_DIMENSIONS) {
8616
+ console.log(`[memory-search] retrieval_path=hybrid scope=${scope} limit=${limit2} vec_rows=${health.counts.memoryVec} searchable=${health.counts.searchable}`);
8617
+ return this.searchHybrid(embedding, options.queryText, agentId, {
8618
+ scope,
8619
+ limit: limit2,
8620
+ source,
8621
+ isLead,
8622
+ includeExpired
8623
+ });
8624
+ }
8625
+ if (health.retrievalMode === "vec" && embedding.length === EMBEDDING_DIMENSIONS) {
8626
+ console.log(`[memory-search] retrieval_path=vec scope=${scope} limit=${limit2} vec_rows=${health.counts.memoryVec} searchable=${health.counts.searchable}`);
8627
+ return this.searchWithVec(embedding, agentId, {
8628
+ scope,
8629
+ limit: limit2,
8630
+ source,
8631
+ isLead,
8632
+ includeExpired
8633
+ });
8634
+ }
8635
+ if (options.queryText && this.ftsInitialized && await this.getFtsTableSchema()) {
8636
+ console.log(`[memory-search] retrieval_path=fts scope=${scope} limit=${limit2} reason=${embedding.length !== EMBEDDING_DIMENSIONS ? "query_dimension_mismatch" : health.reasons.join("|") || "vec_unavailable"}`);
8637
+ return this.searchFts(options.queryText, agentId, {
8638
+ scope,
8639
+ limit: limit2,
8640
+ source,
8641
+ isLead,
8642
+ includeExpired
8643
+ });
8644
+ }
8645
+ console.log(`[memory-search] retrieval_path=fallback scope=${scope} limit=${limit2} reason=${embedding.length !== EMBEDDING_DIMENSIONS ? "query_dimension_mismatch" : health.reasons.join("|") || "vec_unavailable"}`);
8646
+ return this.searchBruteForce(embedding, agentId, {
8647
+ scope,
8648
+ limit: limit2,
8649
+ source,
8650
+ isLead,
8651
+ includeExpired
8652
+ });
8653
+ }
8654
+ async searchHybrid(queryEmbedding, queryText, agentId, options) {
8655
+ const overfetchLimit = Math.min(Math.max(options.limit * 4, options.limit), 100);
8656
+ const vectorCandidates = await this.searchWithVec(queryEmbedding, agentId, {
8657
+ ...options,
8658
+ limit: overfetchLimit
8659
+ });
8660
+ const ftsCandidates = await this.searchFts(queryText, agentId, {
8661
+ ...options,
8662
+ limit: overfetchLimit
8663
+ });
8664
+ const byId = new Map;
8665
+ const rrf = new Map;
8666
+ const cosines = new Map;
8667
+ const sources = new Map;
8668
+ const add = (candidate, rank) => {
8669
+ byId.set(candidate.id, byId.get(candidate.id) ?? candidate);
8670
+ const retrievalSource = candidate.retrievalSource === "fts" ? "fts" : "vec";
8671
+ const candidateSources = sources.get(candidate.id) ?? new Set;
8672
+ candidateSources.add(retrievalSource);
8673
+ sources.set(candidate.id, candidateSources);
8674
+ if (retrievalSource === "vec")
8675
+ cosines.set(candidate.id, candidate.similarity);
8676
+ rrf.set(candidate.id, (rrf.get(candidate.id) ?? 0) + computeRrfScore(rank, 1));
8677
+ };
8678
+ vectorCandidates.forEach(add);
8679
+ ftsCandidates.forEach(add);
8680
+ await this.fillCosines(queryEmbedding, [...byId.keys()], cosines);
8681
+ return [...byId.values()].map((candidate) => {
8682
+ const similarity = fusedSimilarity(cosines.get(candidate.id) ?? 0, rrf.get(candidate.id) ?? 0);
8683
+ return {
8684
+ ...candidate,
8685
+ rawSimilarity: similarity,
8686
+ similarity,
8687
+ retrievalSource: retrievalSourceFor(sources.get(candidate.id) ?? new Set),
8688
+ recencyDecayApplied: false
8689
+ };
8690
+ }).sort((a, b) => b.similarity - a.similarity).slice(0, options.limit);
8691
+ }
8692
+ async fillCosines(queryEmbedding, ids, cosines) {
8693
+ const missing = ids.filter((id) => !cosines.has(id));
8694
+ if (missing.length === 0)
8695
+ return;
8696
+ const rows = await getDbClient().query(`SELECT id, embedding FROM agent_memory WHERE id IN (${missing.map(() => "?").join(",")})`, missing);
8697
+ for (const row of rows) {
8698
+ if (!row.embedding)
8699
+ continue;
8700
+ const embedding = deserializeEmbedding(row.embedding);
8701
+ if (embedding.length !== queryEmbedding.length)
8702
+ continue;
8703
+ cosines.set(row.id, Math.max(0, cosineSimilarity(queryEmbedding, embedding)));
8704
+ }
8705
+ }
8706
+ async searchFts(queryText, agentId, options) {
8707
+ const match = this.buildFtsMatch(queryText);
8708
+ if (!match)
8709
+ return [];
8710
+ const { scope, limit: limit2, source, isLead, includeExpired } = options;
8711
+ const conditions = ["memory_fts MATCH ?"];
8712
+ const params = [match];
8713
+ this.addScopeConditions(conditions, params, agentId, scope, isLead, "m");
8714
+ if (source) {
8715
+ conditions.push("m.source = ?");
8716
+ params.push(source);
8717
+ }
8718
+ if (!includeExpired) {
8719
+ conditions.push("(m.expiresAt IS NULL OR m.expiresAt > datetime('now'))");
8720
+ }
8721
+ try {
8722
+ const sqlLimit = Math.min(Math.max(limit2 * 4, limit2), 100);
8723
+ const rows = await getDbClient().query(`SELECT m.*, bm25(memory_fts) AS rank
8724
+ FROM memory_fts
8725
+ JOIN agent_memory m ON m.id = memory_fts.memory_id
8726
+ WHERE ${conditions.join(" AND ")}
8727
+ ORDER BY rank
8728
+ LIMIT ?`, [...params, sqlLimit]);
8729
+ const now = new Date;
8730
+ return rows.map((row, index) => {
8731
+ const rawSimilarity = 1 / (index + 1);
8732
+ return {
8733
+ ...rowToCandidate(row, rawSimilarity * recencyDecay(row.createdAt, now, row.source)),
8734
+ rawSimilarity,
8735
+ retrievalSource: "fts",
8736
+ recencyDecayApplied: true
8737
+ };
8738
+ }).sort((a, b) => b.similarity - a.similarity).slice(0, limit2);
8739
+ } catch (err) {
8740
+ console.warn("[memory-fts] query failed:", err.message);
8741
+ return [];
8742
+ }
8743
+ }
8744
+ buildFtsMatch(queryText) {
8745
+ const terms = queryText.trim().split(/[^\p{L}\p{N}_-]+/u).map((term) => term.trim()).filter((term) => term.length > 0).slice(0, 12);
8746
+ if (terms.length === 0)
8747
+ return null;
8748
+ return terms.map((term) => `"${term.replaceAll('"', '""')}"`).join(" OR ");
8749
+ }
8750
+ async searchWithVec(queryEmbedding, agentId, options) {
8751
+ const { scope, limit: limit2, source, isLead, includeExpired } = options;
8752
+ const embeddingBuffer = serializeEmbedding(queryEmbedding);
8753
+ const knnLimit = Math.min(Math.max(limit2, this.getVecCount()), 4096);
8754
+ const conditions = ["v.embedding MATCH ?"];
8755
+ const params = [embeddingBuffer];
8756
+ this.addScopeConditions(conditions, params, agentId, scope, isLead, "m");
8757
+ if (source) {
8758
+ conditions.push("m.source = ?");
8759
+ params.push(source);
8760
+ }
8761
+ if (!includeExpired) {
8762
+ conditions.push("(m.expiresAt IS NULL OR m.expiresAt > datetime('now'))");
8763
+ }
8764
+ conditions.push("v.k = ?");
8765
+ params.push(knnLimit);
8766
+ const rows = await getDbClient().query(`SELECT m.*, v.distance
8767
+ FROM memory_vec v
8768
+ JOIN agent_memory m ON m.id = v.memory_id
8769
+ WHERE ${conditions.join(" AND ")}
8770
+ ORDER BY v.distance
8771
+ LIMIT ?`, [...params, limit2]);
8772
+ const candidates = [];
8773
+ for (const row of rows) {
8774
+ const similarity = 1 - row.distance;
8775
+ if (similarity < minSimilarity())
8776
+ continue;
8777
+ candidates.push({ ...rowToCandidate(row, similarity), retrievalSource: "vec" });
8778
+ }
8779
+ return candidates;
8780
+ }
8781
+ async searchBruteForce(queryEmbedding, agentId, options) {
8782
+ const { scope, limit: limit2, source, isLead, includeExpired } = options;
8783
+ const conditions = ["embedding IS NOT NULL"];
8784
+ const params = [];
8785
+ this.addScopeConditions(conditions, params, agentId, scope, isLead);
8786
+ if (source) {
8787
+ conditions.push("source = ?");
8788
+ params.push(source);
8789
+ }
8790
+ if (!includeExpired) {
8791
+ conditions.push("(expiresAt IS NULL OR expiresAt > datetime('now'))");
8792
+ }
8793
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
8794
+ const rows = await getDbClient().query(`SELECT * FROM agent_memory ${whereClause}`, params);
8795
+ const candidates = [];
8796
+ for (const row of rows) {
8797
+ if (!row.embedding)
8798
+ continue;
8799
+ const emb = deserializeEmbedding(row.embedding);
8800
+ if (emb.length !== queryEmbedding.length)
8801
+ continue;
8802
+ const similarity = cosineSimilarity(queryEmbedding, emb);
8803
+ if (similarity < minSimilarity())
8804
+ continue;
8805
+ candidates.push({ ...rowToCandidate(row, similarity), retrievalSource: "fallback" });
8806
+ }
8807
+ candidates.sort((a, b) => b.similarity - a.similarity);
8808
+ return candidates.slice(0, limit2);
8809
+ }
8810
+ addScopeConditions(conditions, params, agentId, scope, isLead, tableAlias = "") {
8811
+ const col = (name) => tableAlias ? `${tableAlias}.${name}` : name;
8812
+ if (!isLead) {
8813
+ if (scope === "agent") {
8814
+ conditions.push(`${col("agentId")} = ? AND ${col("scope")} = 'agent'`);
8815
+ params.push(agentId);
8816
+ } else if (scope === "swarm") {
8817
+ conditions.push(`${col("scope")} = 'swarm'`);
8818
+ } else {
8819
+ conditions.push(`(${col("agentId")} = ? OR ${col("scope")} = 'swarm')`);
8820
+ params.push(agentId);
8821
+ }
8822
+ } else {
8823
+ if (scope === "agent") {
8824
+ conditions.push(`${col("scope")} = 'agent'`);
8825
+ } else if (scope === "swarm") {
8826
+ conditions.push(`${col("scope")} = 'swarm'`);
8827
+ }
8828
+ }
8829
+ }
8830
+ buildListWhereClause(agentId, options) {
8831
+ const { scope = "all", isLead = false, ownerAgentId, source, sourcePath } = options;
8832
+ const conditions = [];
8833
+ const params = [];
8834
+ this.addScopeConditions(conditions, params, agentId, scope, isLead);
8835
+ if (ownerAgentId) {
8836
+ conditions.push("agentId = ?");
8837
+ params.push(ownerAgentId);
8838
+ }
8839
+ if (source) {
8840
+ conditions.push("source = ?");
8841
+ params.push(source);
8842
+ }
8843
+ const sourcePathNeedle = sourcePath?.trim().toLowerCase();
8844
+ if (sourcePathNeedle) {
8845
+ conditions.push("instr(lower(coalesce(sourcePath, '')), ?) > 0");
8846
+ params.push(sourcePathNeedle);
8847
+ }
8848
+ return {
8849
+ whereClause: conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "",
8850
+ params
8851
+ };
8852
+ }
8853
+ async list(agentId, options = {}) {
8854
+ const { limit: limit2 = 20, offset = 0 } = options;
8855
+ const { whereClause, params } = this.buildListWhereClause(agentId, options);
8856
+ const queryParams = [...params, limit2, offset];
8857
+ const rows = await getDbClient().query(`SELECT * FROM agent_memory ${whereClause} ORDER BY createdAt DESC LIMIT ? OFFSET ?`, queryParams);
8858
+ return rows.map(rowToAgentMemory);
8859
+ }
8860
+ async count(agentId, options = {}) {
8861
+ const { whereClause, params } = this.buildListWhereClause(agentId, options);
8862
+ const row = await getDbClient().get(`SELECT COUNT(*) AS count FROM agent_memory ${whereClause}`, params);
8863
+ return row?.count ?? 0;
8864
+ }
8865
+ isSourceProtected(source) {
8866
+ return PROTECTED_SOURCES.has(source);
8867
+ }
8868
+ async edit(input) {
8869
+ if (!input.id && !(input.key && input.scope)) {
8870
+ throw new Error("memory edit requires either id or key+scope");
8871
+ }
8872
+ const { result, ftsContent } = await getDbClient().transaction(async (tx) => {
8873
+ const row = input.id ? await tx.get("SELECT * FROM agent_memory WHERE id = ?", [input.id]) : await tx.get(`SELECT * FROM agent_memory
8874
+ WHERE key = ? AND scope = ? AND coalesce(agentId, '') = coalesce(?, '')
8875
+ ORDER BY chunkIndex ASC
8876
+ LIMIT 1`, [input.key, input.scope, input.agentId ?? null]);
8877
+ if (!row)
8878
+ throw new Error("memory not found");
8879
+ if ((row.totalChunks ?? 1) !== 1)
8880
+ throw new Error("memory edit only supports single-chunk rows");
8881
+ if (input.expectedVersion && input.expectedVersion !== (row.version ?? 1)) {
8882
+ throw new Error("memory version conflict");
8883
+ }
8884
+ const previousVersion = row.version ?? 1;
8885
+ const nextContent = applyEditMode(input.mode, row.content, {
8886
+ content: input.content,
8887
+ oldString: input.oldString,
8888
+ newString: input.newString
8889
+ });
8890
+ const nextHash = contentSha256(nextContent);
8891
+ if (nextHash === row.contentHash) {
8892
+ return {
8893
+ result: {
8894
+ memory: rowToAgentMemory(row),
8895
+ changed: false,
8896
+ previousVersion,
8897
+ version: previousVersion,
8898
+ contentHash: nextHash
8899
+ },
8900
+ ftsContent: null
8901
+ };
8902
+ }
8903
+ const nextVersion = previousVersion + 1;
8904
+ const now = new Date().toISOString();
8905
+ await tx.run(`INSERT INTO agent_memory_version (id, memory_id, version, content, contentHash, intent, operation, changedByAgentId, createdAt, updatedAt, created_by, updated_by)
8906
+ VALUES (?, ?, ?, ?, ?, ?, 'edit', ?, ?, ?, ?, ?)`, [
8907
+ crypto.randomUUID(),
8908
+ row.id,
8909
+ nextVersion,
8910
+ nextContent,
8911
+ nextHash,
8912
+ input.intent,
8913
+ input.changedByAgentId ?? null,
8914
+ now,
8915
+ now,
8916
+ input.changedByAgentId ?? null,
8917
+ input.changedByAgentId ?? null
8918
+ ]);
8919
+ await tx.run(`UPDATE agent_memory
8920
+ SET content = ?, contentHash = ?, version = ?, updatedAt = ?
8921
+ WHERE id = ?`, [nextContent, nextHash, nextVersion, now, row.id]);
8922
+ return {
8923
+ result: {
8924
+ memory: rowToAgentMemory({
8925
+ ...row,
8926
+ content: nextContent,
8927
+ contentHash: nextHash,
8928
+ version: nextVersion,
8929
+ updatedAt: now
8930
+ }),
8931
+ changed: true,
8932
+ previousVersion,
8933
+ version: nextVersion,
8934
+ contentHash: nextHash
8935
+ },
8936
+ ftsContent: nextContent
8937
+ };
8938
+ });
8939
+ if (ftsContent !== null) {
8940
+ await this.syncFtsRow(result.memory.id, result.memory.name, ftsContent);
8941
+ }
8942
+ return result;
8943
+ }
8944
+ async listForCuration(agentId) {
8945
+ const db = getDbClient();
8946
+ const protectedList = [...PROTECTED_SOURCES].map((s) => `'${s}'`).join(",");
8947
+ if (agentId) {
8948
+ return db.query(`SELECT id, source, name, createdAt FROM agent_memory
8949
+ WHERE agentId = ? AND source NOT IN (${protectedList})`, [agentId]);
8950
+ }
8951
+ return db.query(`SELECT id, source, name, createdAt FROM agent_memory
8952
+ WHERE source NOT IN (${protectedList})`);
8953
+ }
8954
+ async listForReembedding(options) {
8955
+ const db = getDbClient();
8956
+ if (options?.agentId) {
8957
+ return db.query("SELECT id, content FROM agent_memory WHERE agentId = ?", [options.agentId]);
8958
+ }
8959
+ return db.query("SELECT id, content FROM agent_memory");
8960
+ }
8961
+ async purgeByIds(ids) {
8962
+ if (ids.length === 0)
8963
+ return;
8964
+ if (this.vecInitialized && this.getVecTableSchema()) {
8965
+ const placeholders = ids.map(() => "?").join(",");
8966
+ await getDbClient().run(`DELETE FROM memory_vec WHERE memory_id IN (${placeholders})`, ids);
8967
+ }
8968
+ await this.deleteFtsRows(ids);
8969
+ }
8970
+ async delete(id) {
8971
+ await this.purgeByIds([id]);
8972
+ const result = await getDbClient().run("DELETE FROM agent_memory WHERE id = ?", [id]);
8973
+ return result.changes > 0;
8974
+ }
8975
+ async deleteBySourcePath(sourcePath, agentId) {
8976
+ const db = getDbClient();
8977
+ const ids = await db.query("SELECT id FROM agent_memory WHERE sourcePath = ? AND agentId = ?", [sourcePath, agentId]);
8978
+ await this.purgeByIds(ids.map((r) => r.id));
8979
+ const result = await db.run("DELETE FROM agent_memory WHERE sourcePath = ? AND agentId = ?", [
8980
+ sourcePath,
8981
+ agentId
8982
+ ]);
8983
+ return ids.length || result.changes;
8984
+ }
8985
+ async purgeExpired() {
8986
+ const db = getDbClient();
8987
+ const expiredIds = await db.query("SELECT id FROM agent_memory WHERE expiresAt IS NOT NULL AND expiresAt <= datetime('now')");
8988
+ if (expiredIds.length === 0)
8989
+ return 0;
8990
+ const batchSize = 500;
8991
+ for (let i = 0;i < expiredIds.length; i += batchSize) {
8992
+ await this.purgeByIds(expiredIds.slice(i, i + batchSize).map((r) => r.id));
8993
+ }
8994
+ const result = await db.run("DELETE FROM agent_memory WHERE expiresAt IS NOT NULL AND expiresAt <= datetime('now')");
8995
+ console.log(`[memory] Purged ${result.changes} expired memory row(s) (vec cleanup: ${expiredIds.length} id(s))`);
8996
+ return result.changes;
8997
+ }
8998
+ async updateEmbedding(id, embedding, model) {
8999
+ const db = getDbClient();
9000
+ const buffer = serializeEmbedding(embedding);
9001
+ await db.run("UPDATE agent_memory SET embedding = ?, embeddingModel = ? WHERE id = ?", [
9002
+ buffer,
9003
+ model,
9004
+ id
9005
+ ]);
9006
+ if (this.vecInitialized && this.getVecTableSchema()) {
9007
+ const vecBuffer = this.toVecBuffer(embedding);
9008
+ if (!vecBuffer) {
9009
+ console.warn(`[memory-vec] update skipped memory_id=${id} reason=invalid_dimensions dimensions=${embedding.length} expected=${EMBEDDING_DIMENSIONS}`);
9010
+ return;
9011
+ }
9012
+ try {
9013
+ await db.run("DELETE FROM memory_vec WHERE memory_id = ?", [id]);
9014
+ await db.run("INSERT INTO memory_vec(memory_id, embedding) VALUES (?, ?)", [id, vecBuffer]);
9015
+ } catch (err) {
9016
+ console.error(`[memory-vec] update failed memory_id=${id}: ${err.message}`);
9017
+ }
9018
+ }
9019
+ }
9020
+ async getStats(agentId) {
9021
+ const db = getDbClient();
9022
+ const total = await db.get("SELECT COUNT(*) as count FROM agent_memory WHERE agentId = ?", [agentId]);
9023
+ const bySourceRows = await db.query("SELECT source, COUNT(*) as count FROM agent_memory WHERE agentId = ? GROUP BY source", [agentId]);
9024
+ const byScopeRows = await db.query("SELECT scope, COUNT(*) as count FROM agent_memory WHERE agentId = ? GROUP BY scope", [agentId]);
9025
+ const withEmbeddings = await db.get("SELECT COUNT(*) as count FROM agent_memory WHERE agentId = ? AND embedding IS NOT NULL", [agentId]);
9026
+ const expired = await db.get("SELECT COUNT(*) as count FROM agent_memory WHERE agentId = ? AND expiresAt IS NOT NULL AND expiresAt <= datetime('now')", [agentId]);
9027
+ const bySource = {};
9028
+ for (const row of bySourceRows)
9029
+ bySource[row.source] = row.count;
9030
+ const byScope = {};
9031
+ for (const row of byScopeRows)
9032
+ byScope[row.scope] = row.count;
9033
+ return {
9034
+ total: total?.count ?? 0,
9035
+ bySource,
9036
+ byScope,
9037
+ withEmbeddings: withEmbeddings?.count ?? 0,
9038
+ expired: expired?.count ?? 0
9039
+ };
9040
+ }
9041
+ getHealthCounts() {
9042
+ const db = getDb();
9043
+ const tableExists = this.getVecTableSchema() !== null;
9044
+ const tableUsable = tableExists && isSqliteVecAvailable();
9045
+ const count = (sql) => db.prepare(sql).get()?.count ?? 0;
9046
+ return {
9047
+ total: count("SELECT COUNT(*) as count FROM agent_memory"),
9048
+ withEmbedding: count("SELECT COUNT(*) as count FROM agent_memory WHERE embedding IS NOT NULL"),
9049
+ validEmbedding: count(`SELECT COUNT(*) as count FROM agent_memory WHERE embedding IS NOT NULL AND length(embedding) = ${VECTOR_BYTES}`),
9050
+ invalidEmbedding: count(`SELECT COUNT(*) as count FROM agent_memory WHERE embedding IS NOT NULL AND length(embedding) != ${VECTOR_BYTES}`),
9051
+ searchable: count(`SELECT COUNT(*) as count FROM agent_memory
9052
+ WHERE embedding IS NOT NULL
9053
+ AND length(embedding) = ${VECTOR_BYTES}
9054
+ AND (expiresAt IS NULL OR expiresAt > datetime('now'))`),
9055
+ memoryVec: tableUsable ? count("SELECT COUNT(*) as count FROM memory_vec") : 0,
9056
+ missingFromVec: tableUsable ? count(`SELECT COUNT(*) as count
9057
+ FROM agent_memory m
9058
+ LEFT JOIN memory_vec v ON v.memory_id = m.id
9059
+ WHERE m.embedding IS NOT NULL
9060
+ AND length(m.embedding) = ${VECTOR_BYTES}
9061
+ AND v.memory_id IS NULL`) : count(`SELECT COUNT(*) as count FROM agent_memory WHERE embedding IS NOT NULL AND length(embedding) = ${VECTOR_BYTES}`),
9062
+ extraInVec: tableUsable ? count(`SELECT COUNT(*) as count
9063
+ FROM memory_vec v
9064
+ LEFT JOIN agent_memory m ON m.id = v.memory_id
9065
+ WHERE m.id IS NULL`) : 0
9066
+ };
9067
+ }
9068
+ getHealth() {
9069
+ const schema = this.getVecTableSchema();
9070
+ const counts = this.getHealthCounts();
9071
+ const reasons = [];
9072
+ if (!isSqliteVecAvailable())
9073
+ reasons.push("sqlite_vec_extension_unavailable");
9074
+ if (!schema)
9075
+ reasons.push("memory_vec_table_missing");
9076
+ if (!this.vecInitialized)
9077
+ reasons.push("memory_vec_not_initialized");
9078
+ if (counts.memoryVec === 0)
9079
+ reasons.push("memory_vec_empty");
9080
+ if (counts.missingFromVec > 0)
9081
+ reasons.push("memory_vec_missing_embeddings");
9082
+ if (counts.extraInVec > 0)
9083
+ reasons.push("memory_vec_extra_rows");
9084
+ return {
9085
+ sqliteVec: {
9086
+ extensionLoaded: isSqliteVecAvailable(),
9087
+ tableExists: schema !== null,
9088
+ initialized: this.vecInitialized,
9089
+ vectorDimensions: EMBEDDING_DIMENSIONS,
9090
+ distanceMetric: "cosine",
9091
+ schema,
9092
+ lastPopulate: this.lastPopulate
9093
+ },
9094
+ counts,
9095
+ retrievalMode: reasons.length === 0 ? "vec" : "fallback",
9096
+ reasons
9097
+ };
9098
+ }
9099
+ }
9100
+ var VECTOR_BYTES, FTS_DELETE_EXTRA_SQL = `DELETE FROM memory_fts
9101
+ WHERE memory_id NOT IN (SELECT id FROM agent_memory)`, FTS_MISSING_IDS_SQL = `SELECT m.id FROM agent_memory m
9102
+ WHERE m.id NOT IN (SELECT memory_id FROM memory_fts WHERE memory_id IS NOT NULL)`, FTS_POPULATE_BATCH_SIZE = 500;
9103
+ var init_sqlite_store = __esm(() => {
9104
+ init_db();
9105
+ init_embedding();
9106
+ init_profile_sync();
9107
+ init_constants();
9108
+ init_reranker();
9109
+ VECTOR_BYTES = EMBEDDING_DIMENSIONS * Float32Array.BYTES_PER_ELEMENT;
9110
+ });
9111
+
9112
+ // src/be/memory/index.ts
9113
+ var embeddingProvider = null;
9114
+ var memoryStore = null;
9115
+ function getEmbeddingProvider() {
9116
+ if (!embeddingProvider) {
9117
+ const { OpenAIEmbeddingProvider: OpenAIEmbeddingProvider2 } = (init_openai_embedding(), __toCommonJS(exports_openai_embedding));
9118
+ embeddingProvider = new OpenAIEmbeddingProvider2;
9119
+ }
9120
+ return embeddingProvider;
9121
+ }
9122
+ function resetEmbeddingProvider() {
9123
+ embeddingProvider = null;
9124
+ }
9125
+ function getMemoryStore() {
9126
+ if (!memoryStore) {
9127
+ const { SqliteMemoryStore: SqliteMemoryStore2 } = (init_sqlite_store(), __toCommonJS(exports_sqlite_store));
9128
+ memoryStore = new SqliteMemoryStore2;
9129
+ }
9130
+ return memoryStore;
9131
+ }
9132
+
9133
+ export { cosineSimilarity, serializeEmbedding, deserializeEmbedding, init_embedding, OpenAI, init_openai, CANDIDATE_SET_MULTIPLIER, isGraphExpansionEnabled, EMBEDDING_DIMENSIONS, init_constants, computeScore, rerank, init_reranker, rowToCandidate, init_sqlite_store, getEmbeddingProvider, resetEmbeddingProvider, getMemoryStore };