@desplega.ai/agent-swarm 1.49.0 → 1.52.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 (547) hide show
  1. package/README.md +1 -1
  2. package/openapi.json +2070 -728
  3. package/package.json +10 -1
  4. package/src/agentmail/handlers.ts +65 -10
  5. package/src/agentmail/templates.ts +111 -0
  6. package/src/be/db.ts +1233 -7
  7. package/src/be/migrations/014_prompt_templates.sql +33 -0
  8. package/src/be/migrations/015_workflow_workspace.sql +3 -0
  9. package/src/be/migrations/016_active_session_runner_session.sql +4 -0
  10. package/src/be/migrations/017_channel_activity_cursors.sql +6 -0
  11. package/src/be/migrations/018_fix_seed_double_version.sql +30 -0
  12. package/src/be/migrations/019_skills.sql +65 -0
  13. package/src/be/migrations/020_approval_requests.sql +41 -0
  14. package/src/be/seed.ts +62 -0
  15. package/src/be/skill-parser.ts +70 -0
  16. package/src/be/skill-sync.ts +106 -0
  17. package/src/commands/runner.ts +320 -132
  18. package/src/commands/templates.ts +172 -0
  19. package/src/github/handlers.ts +292 -77
  20. package/src/github/mentions-aliases.test.ts +73 -0
  21. package/src/github/mentions.test.ts +3 -3
  22. package/src/github/mentions.ts +32 -6
  23. package/src/github/templates.ts +398 -0
  24. package/src/gitlab/handlers.ts +63 -22
  25. package/src/gitlab/templates.ts +140 -0
  26. package/src/heartbeat/heartbeat.ts +19 -10
  27. package/src/heartbeat/templates.ts +30 -0
  28. package/src/http/active-sessions.ts +27 -0
  29. package/src/http/approval-requests.ts +247 -0
  30. package/src/http/config.ts +3 -3
  31. package/src/http/index.ts +9 -2
  32. package/src/http/poll.ts +135 -14
  33. package/src/http/prompt-templates.ts +412 -0
  34. package/src/http/schedules.ts +35 -0
  35. package/src/http/skills.ts +479 -0
  36. package/src/http/workflows.ts +8 -0
  37. package/src/linear/sync.ts +28 -4
  38. package/src/linear/templates.ts +47 -0
  39. package/src/prompts/base-prompt.ts +41 -490
  40. package/src/prompts/registry.ts +57 -0
  41. package/src/prompts/resolver.ts +296 -0
  42. package/src/prompts/session-templates.ts +604 -0
  43. package/src/providers/claude-adapter.ts +15 -2
  44. package/src/providers/pi-mono-extension.ts +5 -1
  45. package/src/scheduler/scheduler.ts +125 -91
  46. package/src/server.ts +44 -0
  47. package/src/slack/assistant.ts +7 -4
  48. package/src/slack/channel-activity.ts +177 -0
  49. package/src/slack/handlers.ts +21 -6
  50. package/src/slack/templates.ts +55 -0
  51. package/src/tests/approval-requests.test.ts +735 -0
  52. package/src/tests/artifact-sdk.test.ts +12 -12
  53. package/src/tests/base-prompt.test.ts +49 -49
  54. package/src/tests/channel-activity.test.ts +363 -0
  55. package/src/tests/heartbeat.test.ts +1 -0
  56. package/src/tests/linear-webhook.test.ts +7 -3
  57. package/src/tests/pool-session-logs.test.ts +199 -0
  58. package/src/tests/prompt-template-github.test.ts +682 -0
  59. package/src/tests/prompt-template-remaining.test.ts +504 -0
  60. package/src/tests/prompt-template-resolver.test.ts +621 -0
  61. package/src/tests/prompt-template-session.test.ts +363 -0
  62. package/src/tests/prompt-templates-db.test.ts +616 -0
  63. package/src/tests/self-improvement.test.ts +8 -7
  64. package/src/tests/skill-parser.test.ts +178 -0
  65. package/src/tests/skill-sync.test.ts +171 -0
  66. package/src/tests/slack-metadata-inheritance.test.ts +1 -1
  67. package/src/tests/slack-thread-followups.test.ts +1 -1
  68. package/src/tests/structured-output.test.ts +0 -4
  69. package/src/tests/tool-annotations.test.ts +2 -1
  70. package/src/tests/update-profile-agentid.test.ts +248 -0
  71. package/src/tests/update-profile-auth.test.ts +195 -0
  72. package/src/tests/workflow-async-v2.test.ts +126 -4
  73. package/src/tests/workflow-definition-validation.test.ts +76 -0
  74. package/src/tests/workflow-executors.test.ts +4 -2
  75. package/src/tests/workflow-retry-v2.test.ts +1 -1
  76. package/src/tests/workflow-schedule-trigger.test.ts +104 -0
  77. package/src/tests/workflow-workspace.test.ts +272 -0
  78. package/src/tools/prompt-templates/delete.ts +86 -0
  79. package/src/tools/prompt-templates/get.ts +89 -0
  80. package/src/tools/prompt-templates/index.ts +5 -0
  81. package/src/tools/prompt-templates/list.ts +95 -0
  82. package/src/tools/prompt-templates/preview.ts +84 -0
  83. package/src/tools/prompt-templates/set.ts +117 -0
  84. package/src/tools/request-human-input.ts +106 -0
  85. package/src/tools/skills/index.ts +11 -0
  86. package/src/tools/skills/skill-create.ts +105 -0
  87. package/src/tools/skills/skill-delete.ts +67 -0
  88. package/src/tools/skills/skill-get.ts +75 -0
  89. package/src/tools/skills/skill-install-remote.ts +152 -0
  90. package/src/tools/skills/skill-install.ts +101 -0
  91. package/src/tools/skills/skill-list.ts +77 -0
  92. package/src/tools/skills/skill-publish.ts +123 -0
  93. package/src/tools/skills/skill-search.ts +43 -0
  94. package/src/tools/skills/skill-sync-remote.ts +128 -0
  95. package/src/tools/skills/skill-uninstall.ts +60 -0
  96. package/src/tools/skills/skill-update.ts +128 -0
  97. package/src/tools/store-progress.ts +22 -4
  98. package/src/tools/task-action.ts +20 -0
  99. package/src/tools/templates.ts +53 -0
  100. package/src/tools/tool-config.ts +23 -0
  101. package/src/tools/update-profile.ts +106 -34
  102. package/src/tools/workflows/create-workflow.ts +19 -1
  103. package/src/tools/workflows/update-workflow.ts +16 -1
  104. package/src/types.ts +109 -2
  105. package/src/workflows/definition.ts +30 -12
  106. package/src/workflows/engine.ts +40 -14
  107. package/src/workflows/executors/agent-task.ts +14 -3
  108. package/src/workflows/executors/human-in-the-loop.ts +160 -0
  109. package/src/workflows/executors/registry.ts +2 -0
  110. package/src/workflows/index.ts +1 -1
  111. package/src/workflows/recovery.ts +72 -0
  112. package/src/workflows/resume.ts +162 -12
  113. package/src/workflows/triggers.ts +31 -2
  114. package/src/workflows/version.ts +2 -0
  115. package/.claude/settings.json +0 -84
  116. package/.claude/settings.local.json +0 -117
  117. package/.dockerignore +0 -61
  118. package/.editorconfig +0 -15
  119. package/.entire/settings.json +0 -4
  120. package/.env.docker.example +0 -56
  121. package/.env.example +0 -78
  122. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -78
  123. package/.github/ISSUE_TEMPLATE/community-template.yml +0 -77
  124. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  125. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -60
  126. package/.github/PULL_REQUEST_TEMPLATE/community-template.md +0 -29
  127. package/.github/workflows/ci.yml +0 -52
  128. package/.github/workflows/docker-and-deploy.yml +0 -132
  129. package/.github/workflows/merge-gate.yml +0 -233
  130. package/.opencode/plugins/entire.ts +0 -133
  131. package/.superset/config.json +0 -6
  132. package/.wts-config.json +0 -4
  133. package/.wts-setup.ts +0 -171
  134. package/CHANGELOG.md +0 -447
  135. package/CLAUDE.md +0 -521
  136. package/CONTRIBUTING.md +0 -315
  137. package/DEPLOYMENT.md +0 -622
  138. package/Dockerfile +0 -65
  139. package/Dockerfile.worker +0 -189
  140. package/MCP.md +0 -841
  141. package/UI.md +0 -40
  142. package/api-entrypoint.sh +0 -56
  143. package/assets/agent-swarm-logo-orange.png +0 -0
  144. package/assets/agent-swarm-logo.png +0 -0
  145. package/assets/agent-swarm.mp4 +0 -0
  146. package/assets/agent-swarm.png +0 -0
  147. package/biome.json +0 -39
  148. package/deploy/DEPLOY.md +0 -60
  149. package/deploy/agent-swarm.service +0 -17
  150. package/deploy/docker-push.ts +0 -30
  151. package/deploy/install.ts +0 -85
  152. package/deploy/prod-db.ts +0 -42
  153. package/deploy/uninstall.ts +0 -12
  154. package/deploy/update.ts +0 -21
  155. package/depot.json +0 -1
  156. package/docker-compose.example.yml +0 -350
  157. package/docker-compose.local.yml +0 -119
  158. package/docker-entrypoint.sh +0 -632
  159. package/docs-site/app/api/search/route.ts +0 -4
  160. package/docs-site/app/docs/[[...slug]]/page.tsx +0 -87
  161. package/docs-site/app/docs/layout.tsx +0 -12
  162. package/docs-site/app/globals.css +0 -24
  163. package/docs-site/app/layout.config.tsx +0 -34
  164. package/docs-site/app/layout.tsx +0 -119
  165. package/docs-site/app/llms-full.txt/route.ts +0 -11
  166. package/docs-site/app/llms.mdx/docs/[[...slug]]/route.ts +0 -24
  167. package/docs-site/app/llms.txt/route.ts +0 -8
  168. package/docs-site/app/page.tsx +0 -5
  169. package/docs-site/app/robots.ts +0 -13
  170. package/docs-site/app/sitemap.ts +0 -37
  171. package/docs-site/components/api-page.client.tsx +0 -4
  172. package/docs-site/components/api-page.tsx +0 -7
  173. package/docs-site/components/mdx/mermaid.tsx +0 -55
  174. package/docs-site/content/docs/(documentation)/architecture/agents.mdx +0 -117
  175. package/docs-site/content/docs/(documentation)/architecture/hooks.mdx +0 -77
  176. package/docs-site/content/docs/(documentation)/architecture/memory.mdx +0 -96
  177. package/docs-site/content/docs/(documentation)/architecture/meta.json +0 -4
  178. package/docs-site/content/docs/(documentation)/architecture/overview.mdx +0 -172
  179. package/docs-site/content/docs/(documentation)/concepts/epics.mdx +0 -98
  180. package/docs-site/content/docs/(documentation)/concepts/meta.json +0 -4
  181. package/docs-site/content/docs/(documentation)/concepts/scheduling.mdx +0 -136
  182. package/docs-site/content/docs/(documentation)/concepts/services.mdx +0 -104
  183. package/docs-site/content/docs/(documentation)/concepts/task-lifecycle.mdx +0 -148
  184. package/docs-site/content/docs/(documentation)/concepts/workflows.mdx +0 -209
  185. package/docs-site/content/docs/(documentation)/contributing.mdx +0 -158
  186. package/docs-site/content/docs/(documentation)/getting-started.mdx +0 -157
  187. package/docs-site/content/docs/(documentation)/guides/agentmail-integration.mdx +0 -79
  188. package/docs-site/content/docs/(documentation)/guides/deployment.mdx +0 -171
  189. package/docs-site/content/docs/(documentation)/guides/github-integration.mdx +0 -81
  190. package/docs-site/content/docs/(documentation)/guides/gitlab-integration.mdx +0 -93
  191. package/docs-site/content/docs/(documentation)/guides/linear-integration.mdx +0 -98
  192. package/docs-site/content/docs/(documentation)/guides/meta.json +0 -13
  193. package/docs-site/content/docs/(documentation)/guides/sentry-integration.mdx +0 -52
  194. package/docs-site/content/docs/(documentation)/guides/slack-integration.mdx +0 -179
  195. package/docs-site/content/docs/(documentation)/guides/x402-payments.mdx +0 -154
  196. package/docs-site/content/docs/(documentation)/index.mdx +0 -65
  197. package/docs-site/content/docs/(documentation)/meta.json +0 -19
  198. package/docs-site/content/docs/(documentation)/reference/cli.mdx +0 -241
  199. package/docs-site/content/docs/(documentation)/reference/environment-variables.mdx +0 -205
  200. package/docs-site/content/docs/(documentation)/reference/mcp-tools.mdx +0 -449
  201. package/docs-site/content/docs/(documentation)/reference/meta.json +0 -4
  202. package/docs-site/content/docs/api-reference/active-sessions.mdx +0 -9
  203. package/docs-site/content/docs/api-reference/agents.mdx +0 -9
  204. package/docs-site/content/docs/api-reference/channels.mdx +0 -9
  205. package/docs-site/content/docs/api-reference/config.mdx +0 -9
  206. package/docs-site/content/docs/api-reference/debug.mdx +0 -9
  207. package/docs-site/content/docs/api-reference/ecosystem.mdx +0 -9
  208. package/docs-site/content/docs/api-reference/epics.mdx +0 -9
  209. package/docs-site/content/docs/api-reference/index.mdx +0 -32
  210. package/docs-site/content/docs/api-reference/memory.mdx +0 -9
  211. package/docs-site/content/docs/api-reference/meta.json +0 -25
  212. package/docs-site/content/docs/api-reference/poll.mdx +0 -9
  213. package/docs-site/content/docs/api-reference/repos.mdx +0 -9
  214. package/docs-site/content/docs/api-reference/schedules.mdx +0 -9
  215. package/docs-site/content/docs/api-reference/session-data.mdx +0 -9
  216. package/docs-site/content/docs/api-reference/stats.mdx +0 -9
  217. package/docs-site/content/docs/api-reference/tasks.mdx +0 -9
  218. package/docs-site/content/docs/api-reference/trackers.mdx +0 -9
  219. package/docs-site/content/docs/api-reference/webhooks.mdx +0 -9
  220. package/docs-site/content/docs/api-reference/workflows.mdx +0 -9
  221. package/docs-site/content/docs/meta.json +0 -3
  222. package/docs-site/lib/get-llm-text.ts +0 -10
  223. package/docs-site/lib/openapi.ts +0 -23
  224. package/docs-site/lib/source.ts +0 -8
  225. package/docs-site/mdx-components.tsx +0 -13
  226. package/docs-site/next.config.mjs +0 -29
  227. package/docs-site/package.json +0 -35
  228. package/docs-site/pnpm-lock.yaml +0 -5407
  229. package/docs-site/postcss.config.mjs +0 -8
  230. package/docs-site/public/logo.png +0 -0
  231. package/docs-site/scripts/generate-docs.ts +0 -171
  232. package/docs-site/source.config.ts +0 -17
  233. package/docs-site/tsconfig.json +0 -46
  234. package/ecosystem.config.cjs +0 -66
  235. package/landing/next.config.ts +0 -14
  236. package/landing/package.json +0 -31
  237. package/landing/pnpm-lock.yaml +0 -1091
  238. package/landing/postcss.config.mjs +0 -8
  239. package/landing/public/apple-touch-icon.png +0 -0
  240. package/landing/public/favicon.ico +0 -0
  241. package/landing/public/logo.png +0 -0
  242. package/landing/public/og-image.png +0 -0
  243. package/landing/public/omghost-desplega.svg +0 -30
  244. package/landing/public/omghost-openfort.svg +0 -9
  245. package/landing/src/app/actions/waitlist.ts +0 -25
  246. package/landing/src/app/blog/openfort-hackathon/page.tsx +0 -863
  247. package/landing/src/app/blog/page.tsx +0 -162
  248. package/landing/src/app/blog/swarm-metrics/page.tsx +0 -685
  249. package/landing/src/app/examples/page.tsx +0 -174
  250. package/landing/src/app/examples/x402/page.tsx +0 -456
  251. package/landing/src/app/globals.css +0 -122
  252. package/landing/src/app/layout.tsx +0 -134
  253. package/landing/src/app/page.tsx +0 -27
  254. package/landing/src/app/robots.ts +0 -13
  255. package/landing/src/app/sitemap.ts +0 -44
  256. package/landing/src/components/architecture.tsx +0 -163
  257. package/landing/src/components/cta.tsx +0 -52
  258. package/landing/src/components/features.tsx +0 -160
  259. package/landing/src/components/footer.tsx +0 -100
  260. package/landing/src/components/hero.tsx +0 -217
  261. package/landing/src/components/how-it-works.tsx +0 -165
  262. package/landing/src/components/navbar.tsx +0 -147
  263. package/landing/src/components/waitlist.tsx +0 -110
  264. package/landing/src/components/why-choose.tsx +0 -149
  265. package/landing/src/components/workshops.tsx +0 -328
  266. package/landing/src/lib/utils.ts +0 -6
  267. package/landing/tsconfig.json +0 -41
  268. package/misc/transcripts/2026-03-09-pi-mono-e2e-verification.md +0 -154
  269. package/new-ui/CLAUDE.md +0 -92
  270. package/new-ui/README.md +0 -73
  271. package/new-ui/biome.json +0 -42
  272. package/new-ui/components.json +0 -21
  273. package/new-ui/index.html +0 -25
  274. package/new-ui/package.json +0 -49
  275. package/new-ui/pnpm-lock.yaml +0 -4845
  276. package/new-ui/public/logo.png +0 -0
  277. package/new-ui/src/api/client.ts +0 -814
  278. package/new-ui/src/api/hooks/index.ts +0 -64
  279. package/new-ui/src/api/hooks/use-agents.ts +0 -58
  280. package/new-ui/src/api/hooks/use-channels.ts +0 -115
  281. package/new-ui/src/api/hooks/use-config-api.ts +0 -46
  282. package/new-ui/src/api/hooks/use-costs.ts +0 -122
  283. package/new-ui/src/api/hooks/use-db-query.ts +0 -29
  284. package/new-ui/src/api/hooks/use-epics.ts +0 -75
  285. package/new-ui/src/api/hooks/use-repos.ts +0 -61
  286. package/new-ui/src/api/hooks/use-schedules.ts +0 -81
  287. package/new-ui/src/api/hooks/use-services.ts +0 -16
  288. package/new-ui/src/api/hooks/use-stats.ts +0 -27
  289. package/new-ui/src/api/hooks/use-tasks.ts +0 -89
  290. package/new-ui/src/api/hooks/use-workflows.ts +0 -109
  291. package/new-ui/src/api/types.ts +0 -549
  292. package/new-ui/src/app/App.tsx +0 -13
  293. package/new-ui/src/app/providers.tsx +0 -32
  294. package/new-ui/src/app/router.tsx +0 -52
  295. package/new-ui/src/components/layout/app-header.tsx +0 -47
  296. package/new-ui/src/components/layout/app-sidebar.tsx +0 -128
  297. package/new-ui/src/components/layout/breadcrumbs.tsx +0 -57
  298. package/new-ui/src/components/layout/config-guard.tsx +0 -22
  299. package/new-ui/src/components/layout/root-layout.tsx +0 -40
  300. package/new-ui/src/components/layout/swarm-switcher.tsx +0 -85
  301. package/new-ui/src/components/shared/command-menu.tsx +0 -131
  302. package/new-ui/src/components/shared/data-grid.tsx +0 -141
  303. package/new-ui/src/components/shared/empty-state.tsx +0 -24
  304. package/new-ui/src/components/shared/error-boundary.tsx +0 -72
  305. package/new-ui/src/components/shared/json-viewer.tsx +0 -47
  306. package/new-ui/src/components/shared/name-connection-modal.tsx +0 -99
  307. package/new-ui/src/components/shared/page-skeleton.tsx +0 -16
  308. package/new-ui/src/components/shared/session-log-viewer.tsx +0 -364
  309. package/new-ui/src/components/shared/stats-bar.tsx +0 -132
  310. package/new-ui/src/components/shared/status-badge.tsx +0 -131
  311. package/new-ui/src/components/shared/usage-summary.tsx +0 -179
  312. package/new-ui/src/components/ui/alert-dialog.tsx +0 -176
  313. package/new-ui/src/components/ui/alert.tsx +0 -60
  314. package/new-ui/src/components/ui/avatar.tsx +0 -96
  315. package/new-ui/src/components/ui/badge.tsx +0 -46
  316. package/new-ui/src/components/ui/button.tsx +0 -62
  317. package/new-ui/src/components/ui/card.tsx +0 -75
  318. package/new-ui/src/components/ui/command.tsx +0 -160
  319. package/new-ui/src/components/ui/dialog.tsx +0 -143
  320. package/new-ui/src/components/ui/dropdown-menu.tsx +0 -226
  321. package/new-ui/src/components/ui/input.tsx +0 -21
  322. package/new-ui/src/components/ui/label.tsx +0 -19
  323. package/new-ui/src/components/ui/progress.tsx +0 -26
  324. package/new-ui/src/components/ui/scroll-area.tsx +0 -54
  325. package/new-ui/src/components/ui/select.tsx +0 -175
  326. package/new-ui/src/components/ui/separator.tsx +0 -28
  327. package/new-ui/src/components/ui/sheet.tsx +0 -132
  328. package/new-ui/src/components/ui/sidebar.tsx +0 -691
  329. package/new-ui/src/components/ui/skeleton.tsx +0 -13
  330. package/new-ui/src/components/ui/sonner.tsx +0 -35
  331. package/new-ui/src/components/ui/switch.tsx +0 -33
  332. package/new-ui/src/components/ui/table.tsx +0 -92
  333. package/new-ui/src/components/ui/tabs.tsx +0 -79
  334. package/new-ui/src/components/ui/textarea.tsx +0 -18
  335. package/new-ui/src/components/ui/tooltip.tsx +0 -51
  336. package/new-ui/src/components/workflows/action-node.tsx +0 -53
  337. package/new-ui/src/components/workflows/condition-node.tsx +0 -50
  338. package/new-ui/src/components/workflows/graph-utils.ts +0 -124
  339. package/new-ui/src/components/workflows/json-tree.tsx +0 -189
  340. package/new-ui/src/components/workflows/node-styles.ts +0 -10
  341. package/new-ui/src/components/workflows/step-detail-sheet.tsx +0 -87
  342. package/new-ui/src/components/workflows/trigger-node.tsx +0 -41
  343. package/new-ui/src/components/workflows/workflow-graph.tsx +0 -65
  344. package/new-ui/src/hooks/use-auto-scroll.ts +0 -82
  345. package/new-ui/src/hooks/use-config.ts +0 -203
  346. package/new-ui/src/hooks/use-keyboard-shortcuts.ts +0 -41
  347. package/new-ui/src/hooks/use-mobile.ts +0 -19
  348. package/new-ui/src/hooks/use-theme.ts +0 -60
  349. package/new-ui/src/lib/config.ts +0 -188
  350. package/new-ui/src/lib/slugs.ts +0 -71
  351. package/new-ui/src/lib/utils.ts +0 -120
  352. package/new-ui/src/main.tsx +0 -11
  353. package/new-ui/src/pages/agents/[id]/page.tsx +0 -492
  354. package/new-ui/src/pages/agents/page.tsx +0 -134
  355. package/new-ui/src/pages/chat/page.tsx +0 -674
  356. package/new-ui/src/pages/config/page.tsx +0 -1109
  357. package/new-ui/src/pages/dashboard/page.tsx +0 -454
  358. package/new-ui/src/pages/debug/page.tsx +0 -275
  359. package/new-ui/src/pages/epics/[id]/page.tsx +0 -809
  360. package/new-ui/src/pages/epics/page.tsx +0 -321
  361. package/new-ui/src/pages/not-found/page.tsx +0 -18
  362. package/new-ui/src/pages/repos/page.tsx +0 -369
  363. package/new-ui/src/pages/schedules/[id]/page.tsx +0 -664
  364. package/new-ui/src/pages/schedules/page.tsx +0 -477
  365. package/new-ui/src/pages/services/page.tsx +0 -128
  366. package/new-ui/src/pages/tasks/[id]/page.tsx +0 -670
  367. package/new-ui/src/pages/tasks/page.tsx +0 -592
  368. package/new-ui/src/pages/usage/page.tsx +0 -195
  369. package/new-ui/src/pages/workflow-runs/[id]/page.tsx +0 -363
  370. package/new-ui/src/pages/workflows/[id]/page.tsx +0 -417
  371. package/new-ui/src/pages/workflows/page.tsx +0 -266
  372. package/new-ui/src/styles/ag-grid.css +0 -36
  373. package/new-ui/src/styles/globals.css +0 -213
  374. package/new-ui/test-results/.last-run.json +0 -4
  375. package/new-ui/tsconfig.app.json +0 -34
  376. package/new-ui/tsconfig.json +0 -4
  377. package/new-ui/tsconfig.node.json +0 -26
  378. package/new-ui/vercel.json +0 -4
  379. package/new-ui/vite.config.ts +0 -28
  380. package/plugin/README.md +0 -1
  381. package/plugin/build-pi-skills.ts +0 -233
  382. package/plugin/hooks/hooks.json +0 -71
  383. package/prek.toml +0 -75
  384. package/pyproject.toml +0 -9
  385. package/scripts/check-db-boundary.sh +0 -60
  386. package/scripts/e2e-docker-provider.ts +0 -820
  387. package/scripts/e2e-io-schemas-test.ts +0 -807
  388. package/scripts/e2e-provider-test.ts +0 -220
  389. package/scripts/e2e-workflow-redesign.sh +0 -229
  390. package/scripts/e2e-workflow-test.sh +0 -285
  391. package/scripts/e2e-workflow-test.ts +0 -857
  392. package/scripts/generate-mcp-docs.ts +0 -415
  393. package/scripts/generate-openapi.ts +0 -26
  394. package/scripts/measure-tool-tokens.ts +0 -118
  395. package/scripts/x402-e2e-test.ts +0 -195
  396. package/scripts/x402-test-server.ts +0 -236
  397. package/scripts/x402-testnet-e2e.ts +0 -668
  398. package/slack-manifest.json +0 -88
  399. package/templates-ui/README.md +0 -46
  400. package/templates-ui/components.json +0 -17
  401. package/templates-ui/eslint.config.mjs +0 -18
  402. package/templates-ui/next.config.ts +0 -7
  403. package/templates-ui/package.json +0 -35
  404. package/templates-ui/pnpm-lock.yaml +0 -4571
  405. package/templates-ui/postcss.config.mjs +0 -7
  406. package/templates-ui/public/file.svg +0 -1
  407. package/templates-ui/public/globe.svg +0 -1
  408. package/templates-ui/public/logo.png +0 -0
  409. package/templates-ui/public/next.svg +0 -1
  410. package/templates-ui/public/vercel.svg +0 -1
  411. package/templates-ui/public/window.svg +0 -1
  412. package/templates-ui/src/app/[category]/[name]/page.tsx +0 -89
  413. package/templates-ui/src/app/api/templates/[...slug]/route.ts +0 -52
  414. package/templates-ui/src/app/api/templates/route.ts +0 -18
  415. package/templates-ui/src/app/builder/page.tsx +0 -37
  416. package/templates-ui/src/app/globals.css +0 -94
  417. package/templates-ui/src/app/layout.tsx +0 -79
  418. package/templates-ui/src/app/page.tsx +0 -38
  419. package/templates-ui/src/app/robots.ts +0 -11
  420. package/templates-ui/src/app/sitemap.ts +0 -31
  421. package/templates-ui/src/components/compose-builder.tsx +0 -442
  422. package/templates-ui/src/components/compose-preview.tsx +0 -117
  423. package/templates-ui/src/components/file-preview.tsx +0 -77
  424. package/templates-ui/src/components/footer.tsx +0 -40
  425. package/templates-ui/src/components/header.tsx +0 -41
  426. package/templates-ui/src/components/template-card.tsx +0 -87
  427. package/templates-ui/src/components/template-detail.tsx +0 -125
  428. package/templates-ui/src/components/template-gallery.tsx +0 -263
  429. package/templates-ui/src/components/ui/badge.tsx +0 -36
  430. package/templates-ui/src/components/ui/button.tsx +0 -57
  431. package/templates-ui/src/components/ui/card.tsx +0 -76
  432. package/templates-ui/src/components/ui/separator.tsx +0 -31
  433. package/templates-ui/src/components/ui/tooltip.tsx +0 -32
  434. package/templates-ui/src/lib/compose-generator.ts +0 -241
  435. package/templates-ui/src/lib/templates.ts +0 -137
  436. package/templates-ui/src/lib/utils.ts +0 -6
  437. package/templates-ui/tsconfig.json +0 -34
  438. package/thoughts/research/2026-02-28-openfort-viem-x402-research.md +0 -679
  439. package/thoughts/research/2026-02-28-x402-payments-research.md +0 -686
  440. package/thoughts/researcher/plans/2026-02-20-agent-self-improvement-plan.md +0 -282
  441. package/thoughts/researcher/research/2026-02-20-agent-self-improvement.md +0 -492
  442. package/thoughts/shared/plans/.gitkeep +0 -0
  443. package/thoughts/shared/plans/2025-12-18-slack-integration.md +0 -1195
  444. package/thoughts/shared/plans/2025-12-19-agent-log-streaming.md +0 -732
  445. package/thoughts/shared/plans/2025-12-19-role-based-swarm-plugin.md +0 -361
  446. package/thoughts/shared/plans/2025-12-20-mobile-responsive-ui.md +0 -501
  447. package/thoughts/shared/plans/2025-12-20-startup-team-swarm.md +0 -560
  448. package/thoughts/shared/plans/2025-12-23-runner-level-polling.md +0 -934
  449. package/thoughts/shared/plans/2025-12-23-runner-session-logs.md +0 -1000
  450. package/thoughts/shared/plans/2025-12-23-worker-lead-spawn-triggers.md +0 -568
  451. package/thoughts/shared/plans/2026-01-09-inverse-teleport.md +0 -1516
  452. package/thoughts/shared/plans/2026-01-12-agent-rename-pm2-control.md +0 -1133
  453. package/thoughts/shared/plans/2026-01-12-github-app-integration.md +0 -380
  454. package/thoughts/shared/plans/2026-01-12-lead-inbox-model.md +0 -876
  455. package/thoughts/shared/plans/2026-01-12-ralph-wiggum-integration.md +0 -463
  456. package/thoughts/shared/plans/2026-01-13-agent-concurrency.md +0 -691
  457. package/thoughts/shared/plans/2026-01-13-github-assignment-handling.md +0 -690
  458. package/thoughts/shared/plans/2026-01-13-prevent-duplicate-trigger-processing.md +0 -1071
  459. package/thoughts/shared/plans/2026-01-14-fix-slack-thread-context.md +0 -507
  460. package/thoughts/shared/plans/2026-01-15-scheduled-tasks-implementation.md +0 -565
  461. package/thoughts/shared/plans/2026-01-15-usage-cost-tracking-ui.md +0 -1479
  462. package/thoughts/shared/plans/2026-01-16-epics-feature-implementation.md +0 -1230
  463. package/thoughts/shared/plans/2026-02-26-mcp-tool-context-reduction.md +0 -282
  464. package/thoughts/shared/plans/2026-03-02-claude-context-mode-integration.md +0 -328
  465. package/thoughts/shared/plans/2026-03-02-code-level-heartbeat.md +0 -224
  466. package/thoughts/shared/research/.gitkeep +0 -0
  467. package/thoughts/shared/research/2025-01-09-inverse-teleport-plan-review.md +0 -420
  468. package/thoughts/shared/research/2025-12-18-slack-integration.md +0 -442
  469. package/thoughts/shared/research/2025-12-19-agent-log-streaming.md +0 -339
  470. package/thoughts/shared/research/2025-12-19-agent-secrets-cli-research.md +0 -390
  471. package/thoughts/shared/research/2025-12-21-gemini-cli-integration.md +0 -376
  472. package/thoughts/shared/research/2025-12-22-runner-loop-architecture.md +0 -582
  473. package/thoughts/shared/research/2025-12-22-setup-experience-improvements.md +0 -264
  474. package/thoughts/shared/research/2026-01-13-lead-duplicate-trigger-processing.md +0 -223
  475. package/thoughts/shared/research/2026-01-14-lead-slack-thread-context.md +0 -277
  476. package/thoughts/shared/research/2026-01-15-ai-tracker-agent-swarm-integration.md +0 -376
  477. package/thoughts/shared/research/2026-01-15-auto-starting-processes-in-worker-containers.md +0 -787
  478. package/thoughts/shared/research/2026-01-15-scheduled-tasks.md +0 -390
  479. package/thoughts/shared/research/2026-01-16-epics-feature-research.md +0 -437
  480. package/thoughts/shared/research/2026-02-26-cliffy-mcp-tools.md +0 -159
  481. package/thoughts/shared/research/2026-03-03-database-migration-system-refactor.md +0 -337
  482. package/thoughts/swarm-researcher/plans/2026-02-23-openclaw-improvements-plan.md +0 -778
  483. package/thoughts/swarm-researcher/plans/2026-02-26-artifacts-localtunnel-plan.md +0 -1269
  484. package/thoughts/swarm-researcher/research/2026-02-23-openclaw-vs-agent-swarm-comparison.md +0 -411
  485. package/thoughts/swarm-researcher/research/2026-02-26-artifacts-localtunnel.md +0 -724
  486. package/thoughts/taras/brainstorms/2026-03-20-prompt-template-registry.md +0 -443
  487. package/thoughts/taras/brainstorms/2026-03-20-setup-cli-onboarding.md +0 -307
  488. package/thoughts/taras/plans/2026-01-22-agent-swarm-schemas.md +0 -98
  489. package/thoughts/taras/plans/2026-01-28-per-worker-claude-md.md +0 -617
  490. package/thoughts/taras/plans/2026-01-28-sentry-cli-integration.md +0 -214
  491. package/thoughts/taras/plans/2026-02-20-auto-improvement.md +0 -803
  492. package/thoughts/taras/plans/2026-02-20-env-management.md +0 -538
  493. package/thoughts/taras/plans/2026-02-20-memory-system.md +0 -882
  494. package/thoughts/taras/plans/2026-02-20-repos-knowledge.md +0 -806
  495. package/thoughts/taras/plans/2026-02-20-session-attach.md +0 -647
  496. package/thoughts/taras/plans/2026-02-20-worker-identity.md +0 -820
  497. package/thoughts/taras/plans/2026-02-25-feat-new-ui-visual-redesign-plan.md +0 -768
  498. package/thoughts/taras/plans/2026-03-04-fix-buildSystemPrompt-missing-fields.md +0 -77
  499. package/thoughts/taras/plans/2026-03-04-new-ui-missing-actions.md +0 -543
  500. package/thoughts/taras/plans/2026-03-06-one-time-scheduled-tasks.md +0 -373
  501. package/thoughts/taras/plans/2026-03-08-memory-self-improvement-enhancements.md +0 -512
  502. package/thoughts/taras/plans/2026-03-08-pi-mono-provider-implementation.md +0 -919
  503. package/thoughts/taras/plans/2026-03-09-templates-registry.md +0 -723
  504. package/thoughts/taras/plans/2026-03-10-task-working-directory.md +0 -371
  505. package/thoughts/taras/plans/2026-03-11-archil-per-agent-write-strategy.md +0 -621
  506. package/thoughts/taras/plans/2026-03-12-eliminate-inbox-route-to-tasks.md +0 -61
  507. package/thoughts/taras/plans/2026-03-12-slack-thread-followup-additive.md +0 -488
  508. package/thoughts/taras/plans/2026-03-13-slack-ai-improvements.md +0 -644
  509. package/thoughts/taras/plans/2026-03-16-route-wrapper-openapi.md +0 -636
  510. package/thoughts/taras/plans/2026-03-17-multi-api-config.md +0 -444
  511. package/thoughts/taras/plans/2026-03-18-agent-fs-integration.md +0 -591
  512. package/thoughts/taras/plans/2026-03-18-debug-db-explorer.md +0 -446
  513. package/thoughts/taras/plans/2026-03-18-workflow-redesign.md +0 -987
  514. package/thoughts/taras/plans/2026-03-19-compound-learnings.md +0 -403
  515. package/thoughts/taras/plans/2026-03-19-ticket-tracker-linear-integration.md +0 -860
  516. package/thoughts/taras/plans/2026-03-19-workflow-io-schemas-and-bugs.md +0 -899
  517. package/thoughts/taras/plans/2026-03-20-setup-cli-onboarding.md +0 -874
  518. package/thoughts/taras/plans/2026-03-20-workflow-structured-output-validation-workspace.md +0 -723
  519. package/thoughts/taras/research/2026-01-22-vercel-cli-integration.md +0 -287
  520. package/thoughts/taras/research/2026-01-27-excessive-polling-issue.md +0 -311
  521. package/thoughts/taras/research/2026-01-28-per-worker-claude-md.md +0 -383
  522. package/thoughts/taras/research/2026-01-28-sentry-cli-integration.md +0 -240
  523. package/thoughts/taras/research/2026-02-19-agent-native-swarm-architecture.md +0 -390
  524. package/thoughts/taras/research/2026-02-19-swarm-gaps-implementation.md +0 -594
  525. package/thoughts/taras/research/2026-02-25-dashboard-ui-design-best-practices.md +0 -825
  526. package/thoughts/taras/research/2026-02-26-task-detail-page-redesign.md +0 -393
  527. package/thoughts/taras/research/2026-03-03-new-ui-missing-actions.md +0 -168
  528. package/thoughts/taras/research/2026-03-05-pi-mono-provider-research.md +0 -230
  529. package/thoughts/taras/research/2026-03-06-workflow-engine-design.md +0 -445
  530. package/thoughts/taras/research/2026-03-08-drive-loop-concept.md +0 -375
  531. package/thoughts/taras/research/2026-03-08-pi-mono-deep-dive.md +0 -869
  532. package/thoughts/taras/research/2026-03-09-templates-registry.md +0 -373
  533. package/thoughts/taras/research/2026-03-10-agent-working-directory.md +0 -223
  534. package/thoughts/taras/research/2026-03-10-configurable-event-prompts.md +0 -339
  535. package/thoughts/taras/research/2026-03-11-archil-production-setup.md +0 -181
  536. package/thoughts/taras/research/2026-03-11-archil-shared-disk-write-strategies.md +0 -437
  537. package/thoughts/taras/research/2026-03-13-slack-ai-features.md +0 -258
  538. package/thoughts/taras/research/2026-03-16-openapi-docs-generation.md +0 -335
  539. package/thoughts/taras/research/2026-03-16-route-wrapper-openapi.md +0 -670
  540. package/thoughts/taras/research/2026-03-16-slack-thread-followups-e2e.md +0 -54
  541. package/thoughts/taras/research/2026-03-18-agent-fs-integration.md +0 -558
  542. package/thoughts/taras/research/2026-03-18-linear-integration-finalization.md +0 -526
  543. package/thoughts/taras/research/2026-03-18-workflow-redesign.md +0 -797
  544. package/thoughts/taras/research/2026-03-19-workflow-node-io-schemas-and-bugs.md +0 -563
  545. package/thoughts/taras/research/2026-03-19-workflow-structured-output-validation-workspace.md +0 -486
  546. package/thoughts/taras/research/2026-03-20-prompt-template-registry.md +0 -469
  547. package/tsconfig.json +0 -37
@@ -1,882 +0,0 @@
1
- ---
2
- date: 2026-02-20
3
- planner: Claude
4
- branch: claw-memory
5
- repository: agent-swarm
6
- topic: "Memory System Implementation (Gap 2)"
7
- tags: [plan, memory, embeddings, vector-search, hooks, mcp-tools]
8
- status: complete
9
- autonomy: autopilot
10
- related_research: thoughts/taras/research/2026-02-19-swarm-gaps-implementation.md
11
- last_updated: 2026-02-20
12
- last_updated_by: Claude
13
- ---
14
-
15
- # Memory System Implementation Plan (Gap 2)
16
-
17
- ## Overview
18
-
19
- Implement a persistent memory system for agent-swarm that allows agents to accumulate knowledge across sessions. Today, agent data is scattered across 7 storage subsystems (see [research](../research/2026-02-19-swarm-gaps-implementation.md#gap-2-memory-system-fs--sqlite-vec--openai-embeddings)) with zero cross-system search. This plan adds:
20
-
21
- 1. An `agent_memory` table with embedding-based vector search
22
- 2. `memory-search` and `memory-get` MCP tools for agents to query their memories
23
- 3. File-based auto-indexing via PostToolUse hook (writes to `{personal|shared}/memory/` get indexed)
24
- 4. Session summarization at Stop hook (task output/progress → memory)
25
- 5. Task completion memory (completed tasks auto-indexed)
26
-
27
- ## Current State Analysis
28
-
29
- **What exists:**
30
- - Agent data scattered across `agents.claudeMd`, `agent_tasks.progress/output`, `agent_log`, `session_logs`, `session_costs`, `/workspace/personal/`, `/workspace/shared/thoughts/` — none searchable cross-system
31
- - Base prompt (`src/prompts/base-prompt.ts:214-219`) tells agents to create `memory.txt` or `memory.db` locally — no server-side automation
32
- - No `openai` package in dependencies — embedding API not available
33
- - No sqlite-vec or FTS5 extensions loaded
34
- - PostToolUse hook (`src/hooks/hook.ts:620-653`) already intercepts Write/Edit for identity file sync — pattern exists to extend
35
-
36
- **Key patterns to follow:**
37
- - DB table creation: `CREATE TABLE IF NOT EXISTS` inside `initSchema` transaction (`src/be/db.ts:329-349` for `swarm_config`)
38
- - DB migrations: `try { ALTER TABLE ADD COLUMN } catch { /* exists */ }` (`src/be/db.ts:381-539`)
39
- - Tool registration: `createToolRegistrar(server)` pattern with `inputSchema`/`outputSchema` zod schemas (`src/tools/utils.ts:86-114`)
40
- - Tool return format: `{ content: [{type: "text", text}], structuredContent: {yourAgentId, success, message, ...} }`
41
- - Capability gating: `hasCapability("memory")` check in `src/server.ts:62-64`
42
- - Hook HTTP calls: fire-and-forget to API server (`src/hooks/hook.ts:632-636`)
43
- - Test pattern: isolated SQLite DB per test file, `node:http` handler, `beforeAll`/`afterAll` cleanup (`src/tests/session-attach.test.ts:1-15`)
44
-
45
- ### Key Discoveries:
46
- - `src/be/db.ts:329-349` — `swarm_config` table uses `CREATE TABLE IF NOT EXISTS` inside init transaction with separate index statements. Memory table should follow same pattern.
47
- - `src/hooks/hook.ts:627-637` — PostToolUse already checks `toolName === "Write" || "Edit"` and `editedPath` for identity sync. Memory indexing extends this exact pattern.
48
- - `src/hooks/hook.ts:666-695` — Stop hook syncs CLAUDE.md and identity files. Session summarization adds a new step here.
49
- - `src/tools/store-progress.ts:104-112` — Task completion (`status === "completed"`) updates agent status. Memory indexing hooks into this point.
50
- - `src/server.ts:55-64` — Capability flags system. Adding `"memory"` to `DEFAULT_CAPABILITIES` string at line 57.
51
- - `src/types.ts:372-386` — `SwarmConfigSchema` is the newest Zod schema. `AgentMemorySchema` follows the same pattern.
52
- - No OpenAI SDK in `package.json` — needs `bun add openai`.
53
-
54
- ## Desired End State
55
-
56
- Agents can:
57
- 1. Call `memory-search` with a natural language query and get semantically similar past memories
58
- 2. Call `memory-get` to retrieve full details of a specific memory
59
- 3. Write files to `/workspace/personal/memory/` or `/workspace/shared/memory/` and have them automatically indexed with embeddings
60
- 4. Have their completed task outputs automatically indexed as memories
61
- 5. Have session summaries automatically captured at session end
62
-
63
- Verified by:
64
- - Unit tests for DB functions, embedding, cosine similarity
65
- - Unit tests for MCP tools against isolated DB
66
- - E2E test: write a file to memory directory → search for it → find it
67
-
68
- ## Quick Verification Reference
69
-
70
- ```bash
71
- bun run tsc:check # Type check
72
- bun run lint:fix # Lint & format
73
- bun test src/tests/memory.test.ts # Memory unit tests
74
- ```
75
-
76
- Key files to check:
77
- - `src/be/db.ts` — `agent_memory` table, CRUD functions, dedup
78
- - `src/be/embedding.ts` — Embedding utility, cosine similarity
79
- - `src/be/chunking.ts` — Two-stage markdown-aware text chunker
80
- - `src/tools/memory-search.ts` — MCP search tool (lead-aware)
81
- - `src/tools/memory-get.ts` — MCP get tool
82
- - `src/hooks/hook.ts` — PostToolUse auto-indexing, Stop session summary
83
- - `src/http.ts` — `POST /api/memory/index` ingestion endpoint (chunking + dedup)
84
- - `src/server.ts` — Tool registration with "memory" capability
85
- - `src/types.ts` — `AgentMemorySchema`
86
- - `src/tests/memory.test.ts` — Unit tests
87
-
88
- ## What We're NOT Doing
89
-
90
- - **NOT using sqlite-vec**: Using BLOB storage + JS cosine similarity for simplicity. Works identically on macOS and Linux. Good for <10K vectors. sqlite-vec can be added later as optimization.
91
- - **NOT implementing BM25/hybrid search**: Pure vector search only. Keyword fallback can be added later.
92
- - **NOT implementing memory garbage collection**: Just `createdAt` index for future cleanup.
93
- - **NOT implementing cross-agent automatic propagation**: Agents explicitly choose scope (`agent` vs `swarm`) when writing to personal vs shared memory directories.
94
- - **NOT implementing a `memory-save` MCP tool**: Memory creation happens through file writes (auto-indexed by hook) and automatic task completion indexing. Keeps the agent's workflow natural — write files, not call tools.
95
- - **NOT implementing memory maintenance/curation**: OpenClaw has agents periodically review and curate their memories. We skip this for now — memories accumulate, agents search what they need.
96
-
97
- ## Implementation Approach
98
-
99
- **Embedding strategy**: BLOB storage in regular SQLite table + brute-force cosine similarity in JS. At 512 dimensions (Float32Array), each embedding is 2KB. For 10K memories, that's 20MB of embeddings — fits easily in memory for O(n) search.
100
-
101
- **Async indexing**: Hook calls API endpoint (`POST /api/memory/index`) which returns 202 immediately and processes embedding in background. Hooks stay fast, agent is never blocked.
102
-
103
- **Scope model**: Memories have `scope: 'agent' | 'swarm'`. Files in `/workspace/personal/memory/` → agent scope. Files in `/workspace/shared/memory/` → swarm scope. **Lead agents see ALL memories (agent + swarm, across all agents)**. Workers see their own agent-scoped + all swarm-scoped memories.
104
-
105
- **Embedding provider**: OpenAI `text-embedding-3-small` at 512 dimensions ($0.02/1M tokens). Simple, cheap, well-documented.
106
-
107
- **Chunking strategy**: Two-stage markdown-aware splitter. Stage 1: split by markdown headers (`#`, `##`, `###`) to preserve document structure. Stage 2: if any section exceeds 2,000 chars (~500 tokens), apply recursive character splitting with separators `["\n\n", "\n", ". ", " "]`. Overlap of 100 chars between chunks. Files under 2,000 chars are embedded as a single chunk. Min chunk size 50 chars (skip trivially small chunks).
108
-
109
- **Deduplication strategy**: When re-indexing a file (same `sourcePath`), use transaction-wrapped delete + re-insert: `DELETE FROM agent_memory WHERE sourcePath = ? AND agentId = ?` followed by batch INSERT of new chunks — all inside `getDb().transaction()`. This follows existing codebase patterns (`deleteServicesByAgentId` + `createSessionLogs`).
110
-
111
- **OPENAI_API_KEY placement**: Only needed on the **API server** (`.env` on host). Workers never call OpenAI directly — they POST to the API server which handles embedding server-side. Session summarization uses `claude -p` with `CLAUDE_CODE_OAUTH_TOKEN` (already in worker containers).
112
-
113
- ---
114
-
115
- ## Phase 1: Database Schema & Embedding Infrastructure
116
-
117
- ### Overview
118
- Create the `agent_memory` table, add the `openai` package, implement embedding generation and cosine similarity functions, and DB CRUD operations. This phase is pure infrastructure with no user-facing features.
119
-
120
- ### Changes Required:
121
-
122
- #### 1. Add OpenAI dependency
123
- **Command**: `bun add openai`
124
-
125
- #### 2. Create embedding utility
126
- **File**: `src/be/embedding.ts` (new file)
127
- **Changes**: Implement `getEmbedding(text: string): Promise<Float32Array>` using OpenAI `text-embedding-3-small` at 512 dimensions. Implement `cosineSimilarity(a: Float32Array, b: Float32Array): number` for vector comparison. Implement `serializeEmbedding(embedding: Float32Array): Buffer` and `deserializeEmbedding(buffer: Buffer): Float32Array` for BLOB storage.
128
-
129
- Key implementation details:
130
- - Strip newlines from input text before embedding (`text.replace(/[\n\r]/g, " ")`)
131
- - Handle API errors gracefully — return null on failure, let caller decide
132
- - `OPENAI_API_KEY` env var required (skip embedding if not set — graceful degradation)
133
-
134
- ```typescript
135
- // Pseudo-code structure
136
- import OpenAI from "openai";
137
-
138
- let openai: OpenAI | null = null;
139
-
140
- function getClient(): OpenAI | null {
141
- if (!process.env.OPENAI_API_KEY) return null;
142
- if (!openai) openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
143
- return openai;
144
- }
145
-
146
- export async function getEmbedding(text: string): Promise<Float32Array | null> {
147
- const client = getClient();
148
- if (!client) return null;
149
- // Call API, return Float32Array
150
- }
151
-
152
- export function cosineSimilarity(a: Float32Array, b: Float32Array): number { ... }
153
- export function serializeEmbedding(e: Float32Array): Buffer { ... }
154
- export function deserializeEmbedding(b: Buffer): Float32Array { ... }
155
- ```
156
-
157
- #### 3. Add `agent_memory` table to database
158
- **File**: `src/be/db.ts`
159
- **Changes**: Add `CREATE TABLE IF NOT EXISTS agent_memory` inside the `initSchema` transaction (after `swarm_config` table at line ~349). Add indexes.
160
-
161
- ```sql
162
- CREATE TABLE IF NOT EXISTS agent_memory (
163
- id TEXT PRIMARY KEY,
164
- agentId TEXT,
165
- scope TEXT NOT NULL CHECK(scope IN ('agent', 'swarm')),
166
- name TEXT NOT NULL,
167
- content TEXT NOT NULL,
168
- summary TEXT,
169
- embedding BLOB,
170
- source TEXT NOT NULL CHECK(source IN ('manual', 'file_index', 'session_summary', 'task_completion')),
171
- sourceTaskId TEXT,
172
- sourcePath TEXT,
173
- chunkIndex INTEGER DEFAULT 0,
174
- totalChunks INTEGER DEFAULT 1,
175
- tags TEXT DEFAULT '[]',
176
- createdAt TEXT NOT NULL,
177
- accessedAt TEXT NOT NULL
178
- )
179
- ```
180
-
181
- Indexes:
182
- - `idx_agent_memory_agent ON agent_memory(agentId)`
183
- - `idx_agent_memory_scope ON agent_memory(scope)`
184
- - `idx_agent_memory_source ON agent_memory(source)`
185
- - `idx_agent_memory_created ON agent_memory(createdAt)`
186
- - `idx_agent_memory_source_path ON agent_memory(sourcePath)` — needed for deduplication on re-index
187
-
188
- #### 4. Add DB CRUD functions
189
- **File**: `src/be/db.ts`
190
- **Changes**: Add functions following existing patterns (e.g., `createSwarmConfig` at line ~4468):
191
-
192
- - `createMemory(data: CreateMemoryOptions): AgentMemory` — INSERT with UUID generation
193
- - `getMemoryById(id: string): AgentMemory | null` — SELECT by ID, update `accessedAt`
194
- - `searchMemoriesByVector(queryEmbedding: Float32Array, agentId: string, options?: { scope?, limit?, source?, isLead? }): AgentMemory[]` — Load all matching embeddings, compute cosine similarity in JS, return top-K. When `isLead: true`, return ALL memories across all agents (not just own + swarm).
195
- - `listMemoriesByAgent(agentId: string, options?: { scope?, limit?, offset?, isLead? }): AgentMemory[]` — Paginated list. Lead sees all agents' memories.
196
- - `deleteMemoriesBySourcePath(sourcePath: string, agentId: string): number` — Delete all chunks for a given source path (used for re-indexing)
197
- - `deleteMemory(id: string): boolean` — DELETE by ID
198
- - `getMemoryStats(agentId: string): { total: number, bySource: Record<string, number>, byScope: Record<string, number> }` — Aggregate stats
199
-
200
- Internal helpers:
201
- - `rowToAgentMemory(row: AgentMemoryRow): AgentMemory` — Convert DB row to typed object (following `rowToAgent` pattern at `db.ts:731-748`)
202
- - `AgentMemoryRow` type for the raw DB row
203
-
204
- #### 5. Add Zod types
205
- **File**: `src/types.ts`
206
- **Changes**: Add `AgentMemorySchema` and derived types after `SwarmConfigSchema` (line ~386):
207
-
208
- ```typescript
209
- export const AgentMemoryScopeSchema = z.enum(["agent", "swarm"]);
210
- export const AgentMemorySourceSchema = z.enum(["manual", "file_index", "session_summary", "task_completion"]);
211
-
212
- export const AgentMemorySchema = z.object({
213
- id: z.string().uuid(),
214
- agentId: z.string().uuid().nullable(),
215
- scope: AgentMemoryScopeSchema,
216
- name: z.string().min(1).max(500),
217
- content: z.string(),
218
- summary: z.string().nullable(),
219
- source: AgentMemorySourceSchema,
220
- sourceTaskId: z.string().uuid().nullable(),
221
- sourcePath: z.string().nullable(),
222
- chunkIndex: z.number().int().min(0).default(0),
223
- totalChunks: z.number().int().min(1).default(1),
224
- tags: z.array(z.string()),
225
- createdAt: z.string(),
226
- accessedAt: z.string(),
227
- });
228
-
229
- export type AgentMemoryScope = z.infer<typeof AgentMemoryScopeSchema>;
230
- export type AgentMemorySource = z.infer<typeof AgentMemorySourceSchema>;
231
- export type AgentMemory = z.infer<typeof AgentMemorySchema>;
232
- ```
233
-
234
- Note: `embedding` is NOT in the Zod schema — it's a BLOB that stays server-side, never serialized to JSON.
235
-
236
- #### 6. Create chunking utility
237
- **File**: `src/be/chunking.ts` (new file)
238
- **Changes**: Implement a two-stage markdown-aware chunker.
239
-
240
- ```typescript
241
- export interface MemoryChunk {
242
- content: string;
243
- chunkIndex: number;
244
- totalChunks: number;
245
- headings: string[]; // heading hierarchy for context
246
- }
247
-
248
- const MAX_CHUNK_SIZE = 2000; // ~500 tokens
249
- const CHUNK_OVERLAP = 100; // chars
250
- const MIN_CHUNK_SIZE = 50; // skip trivially small chunks
251
-
252
- export function chunkContent(text: string): MemoryChunk[] { ... }
253
- ```
254
-
255
- **Stage 1**: Split by markdown headers (`#`, `##`, `###`). Each section under a heading becomes a candidate chunk, preserving heading hierarchy as metadata.
256
-
257
- **Stage 2**: If any section exceeds `MAX_CHUNK_SIZE`, apply recursive character splitting with separators `["\n\n", "\n", ". ", " "]` and `CHUNK_OVERLAP` overlap.
258
-
259
- **Small files**: If the entire text is under `MAX_CHUNK_SIZE`, return it as a single chunk (no splitting).
260
-
261
- Key rules:
262
- - Strip leading/trailing whitespace from chunks
263
- - Skip chunks under `MIN_CHUNK_SIZE` (50 chars)
264
- - Include heading hierarchy in the chunk content as a prefix (e.g., `"## Setup > Prerequisites\n\n..."`) so the embedding captures the section context
265
-
266
- #### 7. Unit tests
267
- **File**: `src/tests/memory.test.ts` (new file)
268
- **Changes**: Test DB CRUD operations, cosine similarity, and chunking:
269
-
270
- - Test `createMemory` with all fields (including `chunkIndex`, `totalChunks`)
271
- - Test `getMemoryById` returns correct data
272
- - Test `searchMemoriesByVector` with mock embeddings (known similarity values)
273
- - Test `searchMemoriesByVector` with `isLead: true` returns ALL memories across agents
274
- - Test `searchMemoriesByVector` with `isLead: false` returns only own + swarm
275
- - Test `listMemoriesByAgent` pagination
276
- - Test `deleteMemory`
277
- - Test `deleteMemoriesBySourcePath` deletes all chunks for a path
278
- - Test `getMemoryStats`
279
- - Test `cosineSimilarity` with known vectors (orthogonal → 0, identical → 1, opposite → -1)
280
- - Test `serializeEmbedding` / `deserializeEmbedding` roundtrip
281
- - Test scope filtering: agent memories not visible to other agents, swarm memories visible to all
282
- - Test `chunkContent` with small text (no split)
283
- - Test `chunkContent` with markdown headers (splits on headers)
284
- - Test `chunkContent` with oversized section (recursive split)
285
- - Test `chunkContent` skips chunks under 50 chars
286
- - Test `chunkContent` includes heading hierarchy as prefix
287
-
288
- Test setup: isolated SQLite DB (`./test-memory.sqlite`), `initDb`/`closeDb` in `beforeAll`/`afterAll`.
289
-
290
- ### Success Criteria:
291
-
292
- #### Automated Verification:
293
- - [x] Type check passes: `bun run tsc:check`
294
- - [x] Lint passes: `bun run lint:fix`
295
- - [x] Memory tests pass: `bun test src/tests/memory.test.ts`
296
- - [x] All existing tests still pass: `bun test`
297
-
298
- #### Manual Verification:
299
- - [x] `agent_memory` table created when starting server: `bun run start:http` then `sqlite3 agent-swarm-db.sqlite ".tables"` shows `agent_memory`
300
- - [x] Embedding function works with valid `OPENAI_API_KEY`: confirmed via POST /api/memory/index — embeddings are 2048 bytes (512 float32s)
301
- - [x] Embedding function returns null when `OPENAI_API_KEY` is not set (graceful degradation) — code path verified via code review (getClient returns null)
302
-
303
- **Implementation Note**: After completing this phase, pause for manual confirmation.
304
-
305
- ---
306
-
307
- ## Phase 2: MCP Tools (memory-search, memory-get)
308
-
309
- ### Overview
310
- Create two MCP tools that agents can call to search and retrieve their memories. Register them behind a "memory" capability flag.
311
-
312
- ### Changes Required:
313
-
314
- #### 1. Create memory-search tool
315
- **File**: `src/tools/memory-search.ts` (new file)
316
- **Changes**: Following the tool pattern from `src/tools/get-task-details.ts`:
317
-
318
- ```typescript
319
- // Input schema:
320
- z.object({
321
- query: z.string().min(1).describe("Natural language search query."),
322
- scope: z.enum(["all", "agent", "swarm"]).default("all")
323
- .describe("Search scope: 'all' (own + swarm), 'agent' (own only), 'swarm' (shared only)."),
324
- limit: z.number().int().min(1).max(50).default(10)
325
- .describe("Max results to return."),
326
- source: z.enum(["file_index", "session_summary", "task_completion", "manual"]).optional()
327
- .describe("Filter by memory source type."),
328
- })
329
-
330
- // Output schema:
331
- z.object({
332
- yourAgentId: z.string().uuid().optional(),
333
- success: z.boolean(),
334
- message: z.string(),
335
- results: z.array(z.object({
336
- id: z.string().uuid(),
337
- name: z.string(),
338
- summary: z.string().nullable(),
339
- source: AgentMemorySourceSchema,
340
- scope: AgentMemoryScopeSchema,
341
- similarity: z.number(),
342
- createdAt: z.string(),
343
- })).optional(),
344
- })
345
- ```
346
-
347
- Implementation:
348
- 1. Validate `requestInfo.agentId` exists
349
- 2. Look up agent to determine `isLead` status
350
- 3. Call `getEmbedding(query)` for the query
351
- 4. If embedding is null (no API key), fall back to listing recent memories
352
- 5. Call `searchMemoriesByVector(queryEmbedding, agentId, { scope, limit, source, isLead })`
353
- - Lead agents see ALL memories (agent-scoped from all agents + swarm)
354
- - Workers see own agent-scoped + all swarm-scoped
355
- 6. Return results with similarity scores, names, summaries (NOT full content — use `memory-get` for that)
356
-
357
- #### 2. Create memory-get tool
358
- **File**: `src/tools/memory-get.ts` (new file)
359
- **Changes**: Simple retrieval tool:
360
-
361
- ```typescript
362
- // Input schema:
363
- z.object({
364
- memoryId: z.uuid().describe("The ID of the memory to retrieve."),
365
- })
366
-
367
- // Output schema:
368
- z.object({
369
- yourAgentId: z.string().uuid().optional(),
370
- success: z.boolean(),
371
- message: z.string(),
372
- memory: AgentMemorySchema.optional(),
373
- })
374
- ```
375
-
376
- Implementation:
377
- 1. Call `getMemoryById(memoryId)` — this also updates `accessedAt`
378
- 2. Return full memory details including content
379
-
380
- #### 3. Register tools in server.ts
381
- **File**: `src/server.ts`
382
- **Changes**:
383
- - Add imports for `registerMemorySearchTool` and `registerMemoryGetTool`
384
- - Add `"memory"` to `DEFAULT_CAPABILITIES` string (line 57): `"core,task-pool,messaging,profiles,services,scheduling,epics,memory"`
385
- - Add capability-gated registration block:
386
- ```typescript
387
- if (hasCapability("memory")) {
388
- registerMemorySearchTool(server);
389
- registerMemoryGetTool(server);
390
- }
391
- ```
392
-
393
- #### 4. Unit tests
394
- **File**: `src/tests/memory.test.ts` (extend)
395
- **Changes**: Add tests for MCP tool handlers via the HTTP test pattern (following `session-attach.test.ts`):
396
-
397
- - Test `memory-search` returns results sorted by similarity
398
- - Test `memory-search` with scope filter (agent-only, swarm-only, all)
399
- - Test `memory-search` fallback when no OPENAI_API_KEY (returns recent memories)
400
- - Test `memory-get` returns full content
401
- - Test `memory-get` with invalid ID returns error
402
- - Test `memory-search` without agentId returns error
403
-
404
- ### Success Criteria:
405
-
406
- #### Automated Verification:
407
- - [x] Type check passes: `bun run tsc:check`
408
- - [x] Lint passes: `bun run lint:fix`
409
- - [x] Memory tests pass: `bun test src/tests/memory.test.ts`
410
- - [x] All existing tests still pass: `bun test`
411
-
412
- #### Manual Verification:
413
- - [x] Start server, call `memory-search` via MCP curl session — returns results with similarity scores (0.626 for exact match, 0.280 for related, 0.195 for unrelated)
414
- - [x] Call `memory-get` with returned ID — returns full content, agentId, scope, source, timestamps
415
- - [x] Verify "memory" appears in capabilities list — `tools/list` shows `memory-search` and `memory-get`
416
-
417
- **Implementation Note**: After completing this phase, pause for manual confirmation.
418
-
419
- ---
420
-
421
- ## Phase 3: Memory Ingestion API & Hook Auto-Indexing
422
-
423
- ### Overview
424
- Add a server-side API endpoint for memory ingestion (async embedding + storage), then extend the PostToolUse hook to detect file writes to memory directories and trigger indexing.
425
-
426
- ### Changes Required:
427
-
428
- #### 1. Add memory ingestion API endpoint
429
- **File**: `src/http.ts`
430
- **Changes**: Add `POST /api/memory/index` endpoint (following the REST pattern used by existing endpoints):
431
-
432
- Request body:
433
- ```json
434
- {
435
- "agentId": "uuid",
436
- "content": "file content or text to index",
437
- "name": "human-readable label",
438
- "scope": "agent" | "swarm",
439
- "source": "file_index" | "session_summary" | "task_completion" | "manual",
440
- "sourceTaskId": "uuid (optional)",
441
- "sourcePath": "/workspace/personal/memory/something.md (optional)",
442
- "tags": ["optional", "tags"]
443
- }
444
- ```
445
-
446
- Response: `202 Accepted` with `{ queued: true, memoryIds: ["uuid1", "uuid2", ...] }`
447
-
448
- Implementation:
449
- 1. Validate required fields
450
- 2. **Dedup**: If `sourcePath` is provided, delete all existing chunks for `(sourcePath, agentId)` inside a transaction
451
- 3. **Chunk**: Call `chunkContent(content)` to split into chunks (most files will be 1 chunk)
452
- 4. Create memory records in DB for each chunk (without embedding), inside same transaction
453
- 5. Kick off async embedding for each chunk: `processChunkEmbeddings(memoryIds, chunks)` — no `await`
454
- 6. Return 202 with the memory IDs
455
-
456
- The dedup + insert transaction:
457
- ```typescript
458
- const memoryIds = getDb().transaction(() => {
459
- // Delete old chunks if re-indexing same file
460
- if (sourcePath && agentId) {
461
- deleteMemoriesBySourcePath(sourcePath, agentId);
462
- }
463
-
464
- const chunks = chunkContent(content);
465
- const ids: string[] = [];
466
- for (const chunk of chunks) {
467
- const memory = createMemory({
468
- agentId, content: chunk.content, name,
469
- scope, source, sourcePath,
470
- chunkIndex: chunk.chunkIndex,
471
- totalChunks: chunk.totalChunks,
472
- tags,
473
- });
474
- ids.push(memory.id);
475
- }
476
- return ids;
477
- })();
478
- ```
479
-
480
- The async embedding function:
481
- ```typescript
482
- async function processChunkEmbeddings(memoryIds: string[], chunks: MemoryChunk[]): Promise<void> {
483
- for (let i = 0; i < chunks.length; i++) {
484
- try {
485
- const embedding = await getEmbedding(chunks[i].content);
486
- if (embedding) {
487
- updateMemoryEmbedding(memoryIds[i], serializeEmbedding(embedding));
488
- }
489
- } catch (err) {
490
- console.error(`[memory] Failed to embed chunk ${memoryIds[i]}:`, (err as Error).message);
491
- }
492
- }
493
- }
494
- ```
495
-
496
- #### 2. Add `updateMemoryEmbedding` DB function
497
- **File**: `src/be/db.ts`
498
- **Changes**: Simple UPDATE for the embedding BLOB:
499
- ```typescript
500
- export function updateMemoryEmbedding(id: string, embedding: Buffer): void {
501
- getDb().prepare("UPDATE agent_memory SET embedding = ? WHERE id = ?").run(embedding, id);
502
- }
503
- ```
504
-
505
- #### 3. Extend PostToolUse hook for memory auto-indexing
506
- **File**: `src/hooks/hook.ts`
507
- **Changes**: After the existing identity file sync block (line 637), add memory directory detection:
508
-
509
- ```typescript
510
- // Auto-index files written to memory directories
511
- if (
512
- (toolName === "Write" || toolName === "Edit") &&
513
- editedPath &&
514
- (editedPath.startsWith("/workspace/personal/memory/") ||
515
- editedPath.startsWith("/workspace/shared/memory/"))
516
- ) {
517
- try {
518
- const fileContent = await Bun.file(editedPath).text();
519
- const isShared = editedPath.startsWith("/workspace/shared/");
520
- const fileName = editedPath.split("/").pop() ?? "unnamed";
521
-
522
- await fetch(`${apiUrl}/api/memory/index`, {
523
- method: "POST",
524
- headers: {
525
- "Content-Type": "application/json",
526
- Authorization: `Bearer ${apiKey}`,
527
- "X-Agent-ID": agentInfo.id,
528
- },
529
- body: JSON.stringify({
530
- agentId: agentInfo.id,
531
- content: fileContent,
532
- name: fileName.replace(/\.\w+$/, ""), // strip extension
533
- scope: isShared ? "swarm" : "agent",
534
- source: "file_index",
535
- sourcePath: editedPath,
536
- }),
537
- });
538
- } catch {
539
- // Non-blocking — don't interrupt the agent's workflow
540
- }
541
- }
542
- ```
543
-
544
- This means when an agent does `Write("/workspace/personal/memory/auth-fix.md", "...")`, the hook:
545
- 1. Reads the file content
546
- 2. POSTs to the API for async embedding + indexing
547
- 3. The agent is never blocked
548
-
549
- #### 4. Ensure memory directories exist
550
- **File**: `docker-entrypoint.sh`
551
- **Changes**: Add `mkdir -p /workspace/personal/memory /workspace/shared/memory` in the workspace directory creation section (around line ~303-347).
552
-
553
- #### 5. Unit tests
554
- **File**: `src/tests/memory.test.ts` (extend)
555
- **Changes**:
556
- - Test `POST /api/memory/index` endpoint creates memory records (possibly multiple chunks)
557
- - Test that memory is created even without OPENAI_API_KEY (just no embedding)
558
- - Test `updateMemoryEmbedding` correctly stores and retrieves embedding BLOB
559
- - Test dedup: POST same `sourcePath` twice → old chunks deleted, new chunks created
560
- - Test chunking: POST large content → creates multiple chunk records with correct `chunkIndex`/`totalChunks`
561
- - Test that small content (<2000 chars) creates a single chunk
562
-
563
- ### Success Criteria:
564
-
565
- #### Automated Verification:
566
- - [x] Type check passes: `bun run tsc:check`
567
- - [x] Lint passes: `bun run lint:fix`
568
- - [x] Memory tests pass: `bun test src/tests/memory.test.ts`
569
- - [x] All existing tests still pass: `bun test`
570
-
571
- #### Manual Verification:
572
- - [x] Start server with `OPENAI_API_KEY` set, POST to `/api/memory/index` via curl — returns 202 with memoryIds
573
- - [x] Verify embedding column is populated after async processing — all 8 test memories have 2048-byte embeddings
574
- - [x] Dedup verified: re-POST same sourcePath replaces old record (count stays 1, content updated)
575
- - [x] Large content chunking verified: 5-section markdown → 5 chunks with correct chunkIndex/totalChunks
576
- - [x] In Docker: write a file to `/workspace/personal/memory/api-patterns.md` — auto-indexed as `file_index` memory with embedding (2048 bytes)
577
-
578
- **Implementation Note**: After completing this phase, pause for manual confirmation.
579
-
580
- ---
581
-
582
- ## Phase 4: Task Completion & Session Summarization
583
-
584
- ### Overview
585
- Automatically index completed task outputs as memories and capture session summaries at Stop hook.
586
-
587
- ### Changes Required:
588
-
589
- #### 1. Extend store-progress for task completion memory
590
- **File**: `src/tools/store-progress.ts`
591
- **Changes**: After the task completion block (line 104-112), add async memory indexing:
592
-
593
- ```typescript
594
- if (status === "completed") {
595
- const result = completeTask(taskId, output);
596
- if (result) {
597
- updatedTask = result;
598
- if (existingTask.agentId) {
599
- updateAgentStatusFromCapacity(existingTask.agentId);
600
- }
601
- // Index completed task as memory (async, non-blocking)
602
- indexTaskCompletionMemory(existingTask, output).catch(() => {});
603
- }
604
- }
605
- ```
606
-
607
- The `indexTaskCompletionMemory` function (can be in `src/be/memory.ts` or inline):
608
- 1. Compose content from task description + output
609
- 2. Create memory with `source: 'task_completion'`, `sourceTaskId: task.id`
610
- 3. Generate embedding async
611
-
612
- Note: This can also be done as an HTTP call to `/api/memory/index` (keeping the embedding logic centralized), or directly via DB functions since store-progress runs server-side.
613
-
614
- #### 2. Extend Stop hook for session summarization (via Claude Haiku)
615
- **File**: `src/hooks/hook.ts`
616
- **Changes**: In the Stop handler (line 674-683), after syncing CLAUDE.md and identity files, add real session summarization using `claude -p --model haiku`.
617
-
618
- The hook has access to `msg.transcript_path` (the full session transcript) and optionally `process.env.TASK_FILE` (the current task). This should work in ALL cases — even when there's no task file (e.g., lead agent sessions, ad-hoc sessions).
619
-
620
- **Flow:**
621
- 1. Read the transcript from `msg.transcript_path` (truncate to last ~20K chars if too large)
622
- 2. Optionally read task context from `TASK_FILE` (if available)
623
- 3. Call `claude -p --model haiku` to generate a structured summary
624
- 4. POST the summary to `/api/memory/index` with `sourceTaskId` as optional
625
-
626
- ```typescript
627
- // Session summarization via Claude Haiku
628
- if (agentInfo?.id && msg.transcript_path) {
629
- try {
630
- // 1. Read transcript (truncated to last ~20K chars)
631
- let transcript = "";
632
- try {
633
- const fullTranscript = await Bun.file(msg.transcript_path).text();
634
- transcript = fullTranscript.length > 20000
635
- ? fullTranscript.slice(-20000)
636
- : fullTranscript;
637
- } catch { /* no transcript */ }
638
-
639
- if (transcript.length > 100) { // Skip trivial sessions
640
- // 2. Optionally read task context
641
- let taskContext = "";
642
- let taskId: string | undefined;
643
- const taskFile = process.env.TASK_FILE;
644
- if (taskFile) {
645
- try {
646
- const taskData = JSON.parse(await Bun.file(taskFile).text());
647
- taskContext = `Task: ${taskData.task || "Unknown"}`;
648
- taskId = taskData.id;
649
- } catch { /* no task file — that's fine */ }
650
- }
651
-
652
- // 3. Summarize with Claude Haiku (pipe transcript via stdin)
653
- const summarizePrompt = [
654
- "Summarize this agent session transcript concisely. Output ONLY the summary, no preamble.",
655
- "Format as 3-7 bullet points covering:",
656
- "- What was accomplished",
657
- "- Key decisions made",
658
- "- Problems encountered and solutions found",
659
- "- Learnings useful for future sessions",
660
- taskContext ? `\nTask context: ${taskContext}` : "",
661
- `\nTranscript:\n${transcript}`,
662
- ].filter(Boolean).join("\n");
663
-
664
- // Write prompt to temp file and pipe to claude (avoids shell arg length issues)
665
- const tmpFile = `/tmp/session-summary-${Date.now()}.txt`;
666
- await Bun.write(tmpFile, summarizePrompt);
667
- const result = await Bun.$`cat ${tmpFile} | claude -p --model haiku --output-format json`
668
- .quiet()
669
- .timeout(30000); // 30s timeout
670
- await Bun.$`rm -f ${tmpFile}`.quiet();
671
-
672
- const summaryOutput = JSON.parse(result.stdout.toString());
673
- const summary = summaryOutput.result ?? result.stdout.toString();
674
-
675
- if (summary && summary.length > 20) {
676
- // 4. Index as memory (async, non-blocking)
677
- await fetch(`${apiUrl}/api/memory/index`, {
678
- method: "POST",
679
- headers: {
680
- "Content-Type": "application/json",
681
- Authorization: `Bearer ${apiKey}`,
682
- "X-Agent-ID": agentInfo.id,
683
- },
684
- body: JSON.stringify({
685
- agentId: agentInfo.id,
686
- content: summary,
687
- name: taskContext
688
- ? `Session: ${taskContext.slice(0, 80)}`
689
- : `Session: ${new Date().toISOString().slice(0, 16)}`,
690
- scope: "agent",
691
- source: "session_summary",
692
- ...(taskId ? { sourceTaskId: taskId } : {}),
693
- }),
694
- });
695
- }
696
- }
697
- } catch {
698
- // Non-blocking — session summarization failure should never block shutdown
699
- }
700
- }
701
- ```
702
-
703
- **Key design decisions:**
704
- - Uses `claude -p --model haiku` — fast (~2-5s), cheap, runs inside the container where Claude CLI is installed
705
- - Prompt written to temp file and piped via stdin (avoids shell argument length limits with large transcripts)
706
- - 30s timeout to avoid blocking shutdown indefinitely
707
- - Works without a task file (for lead sessions, ad-hoc work, etc.)
708
- - `sourceTaskId` is optional — null for sessions without a task
709
- - Session memories are **always `scope: 'agent'`** and linked to the specific agent's ID. Lead agents can see all session memories from all agents via the `isLead` search path.
710
- - Transcript truncated to last 20K chars to stay within haiku's context and keep cost minimal
711
- - Output format is JSON to reliably extract the result
712
- - Uses `CLAUDE_CODE_OAUTH_TOKEN` (already in container) — does NOT need `OPENAI_API_KEY` (that's on the API server side for embedding)
713
-
714
- #### 3. Unit tests
715
- **File**: `src/tests/memory.test.ts` (extend)
716
- **Changes**:
717
- - Test that completing a task via `store-progress` creates a memory with `source: 'task_completion'`
718
- - Test that trivial task outputs (short content) are not indexed
719
- - Test the memory ingestion API with optional `sourceTaskId` (null allowed)
720
- - Test that the session summary content structure is correct (mock the claude call in tests)
721
-
722
- ### Success Criteria:
723
-
724
- #### Automated Verification:
725
- - [x] Type check passes: `bun run tsc:check`
726
- - [x] Lint passes: `bun run lint:fix`
727
- - [x] Memory tests pass: `bun test src/tests/memory.test.ts`
728
- - [x] All existing tests still pass: `bun test`
729
-
730
- #### Manual Verification:
731
- - [x] Complete a task via `store-progress` MCP tool — `task_completion` memory created with embedding (2048 bytes)
732
- - [x] Stop a Docker session, verify `session_summary` memory — Haiku generates bullet-point summaries (accomplishments, workflow, blockers)
733
- - [x] Stop a session without a task file (lead agent) — summarization works, uses date-based name (`Session: 2026-02-20T11:39`), no sourceTaskId
734
- - [x] Search for session content via `memory-search` — "Redis caching TTL" query returns task completion memory at 0.626 similarity
735
- - [x] Summarization doesn't significantly delay shutdown — Haiku responds in ~5-10s, 30s timeout as safety net
736
- - [x] **Bug found & fixed**: Stop hook spawning `claude -p --model haiku` triggered recursive hook invocation (fork bomb). Fixed with `SKIP_SESSION_SUMMARY` env var guard.
737
-
738
- **Implementation Note**: After completing this phase, pause for manual confirmation.
739
-
740
- ---
741
-
742
- ## Phase 5: Prompt & Template Updates
743
-
744
- ### Overview
745
- Update the agent prompts and templates to inform agents about the memory system and how to use it.
746
-
747
- ### Changes Required:
748
-
749
- #### 1. Update base prompt memory section
750
- **File**: `src/prompts/base-prompt.ts`
751
- **Changes**: Replace the existing `#### Memory` section (lines 214-219) with updated instructions inspired by [OpenClaw's AGENTS.md](https://github.com/openclaw/openclaw/blob/main/docs/reference/templates/AGENTS.md) "Write It Down" philosophy:
752
-
753
- ```markdown
754
- #### Memory
755
-
756
- **Your memory is limited — if you want to remember something, WRITE IT TO A FILE.**
757
- Mental notes don't survive session restarts. Files do. Text > Brain.
758
-
759
- **Session boot:** At the start of each session, use `memory-search` to recall relevant context for your current task. Your past learnings are searchable.
760
-
761
- **Saving memories:** Write important learnings, patterns, decisions, and solutions to files in your memory directories. They are automatically indexed and become searchable via `memory-search`:
762
- - `/workspace/personal/memory/` — Private to you, searchable only by you
763
- - `/workspace/shared/memory/` — Shared with all agents, searchable by everyone
764
-
765
- When you solve a hard problem, fix a tricky bug, or learn something about the codebase — write it down immediately. Don't wait until the end of the session.
766
-
767
- Example: `Write("/workspace/personal/memory/auth-header-fix.md", "The API requires Bearer prefix on all auth headers. Without it, you get a misleading 403 instead of 401.")`
768
-
769
- **Memory tools:**
770
- - `memory-search` — Search your memories with natural language queries. Returns summaries with IDs.
771
- - `memory-get` — Retrieve full details of a specific memory by ID.
772
-
773
- **What gets auto-indexed (no action needed from you):**
774
- - Files written to the memory directories above (via PostToolUse hook)
775
- - Completed task outputs (when you call store-progress with status: completed)
776
- - Session summaries (captured automatically when your session ends)
777
-
778
- **When to write memories:**
779
- - You solved a problem → write the solution
780
- - You learned a codebase pattern → write the pattern
781
- - You made a mistake → write what went wrong and how to avoid it
782
- - Someone says "remember this" → write it down
783
- - You discovered an important configuration → write it
784
-
785
- You also still have `/workspace/personal/` for general file persistence and `sqlite3` for local structured data.
786
- ```
787
-
788
- #### 2. Update default CLAUDE.md template
789
- **File**: `src/be/db.ts`
790
- **Changes**: In `generateDefaultClaudeMd()` (line ~2200), add a memory section to the template. Inspired by OpenClaw's two-tier approach (daily logs + curated memory):
791
-
792
- ```markdown
793
- ### Memory
794
- - Use `memory-search` to recall past experience before starting new tasks
795
- - Write important learnings to `/workspace/personal/memory/` files
796
- - Share useful knowledge to `/workspace/shared/memory/` for the swarm
797
- ```
798
-
799
- #### 3. Add OPENAI_API_KEY to env documentation
800
- **File**: `.env.example` (or `.env` if no `.env.example` exists)
801
- **Changes**: Add `OPENAI_API_KEY=` with a comment:
802
- ```bash
803
- # Memory system - OpenAI embeddings (API server only, NOT needed in workers)
804
- # Optional: system works without it but memory search degrades to recency-based
805
- OPENAI_API_KEY=
806
- ```
807
-
808
- **Important**: This goes in the **API server's** `.env` only. Do NOT add to `.env.docker` or `.env.docker-lead` — workers don't call OpenAI directly. Workers POST to the API server which handles embedding server-side. Session summarization in workers uses `claude -p` with the existing `CLAUDE_CODE_OAUTH_TOKEN`.
809
-
810
- ### Success Criteria:
811
-
812
- #### Automated Verification:
813
- - [x] Type check passes: `bun run tsc:check`
814
- - [x] Lint passes: `bun run lint:fix`
815
- - [x] All tests pass: `bun test`
816
-
817
- #### Manual Verification:
818
- - [x] Start a fresh agent (join-swarm), verify the default CLAUDE.md includes memory instructions — confirmed: "Memory" section with `memory-search` guidance
819
- - [x] Check the system prompt includes updated memory tool documentation — confirmed: base-prompt.ts has memory-search, memory-get, auto-indexed docs
820
- - [x] Verify `.env.example` documents `OPENAI_API_KEY` — confirmed at line 44
821
-
822
- **Implementation Note**: After completing this phase, pause for manual confirmation.
823
-
824
- ---
825
-
826
- ## Testing Strategy
827
-
828
- ### Unit Tests (`src/tests/memory.test.ts`)
829
- - Isolated SQLite DB (`./test-memory.sqlite`)
830
- - Test all DB CRUD functions with known data
831
- - Test cosine similarity with mathematically verifiable vectors
832
- - Test embedding serialization/deserialization roundtrip
833
- - Mock OpenAI API calls for tool tests (or use known pre-computed embeddings)
834
- - Test scope filtering (agent vs swarm visibility)
835
- - Test memory ingestion endpoint
836
- - Test store-progress memory creation
837
-
838
- ### Integration Tests
839
- - MCP tool tests via HTTP handler (following `session-attach.test.ts` pattern)
840
- - Memory search with pre-seeded embeddings
841
- - Memory get with valid/invalid IDs
842
-
843
- ### Manual E2E
844
- ```bash
845
- # 1. Start API server
846
- OPENAI_API_KEY=sk-... bun run start:http
847
-
848
- # 2. Create a memory via API
849
- curl -X POST http://localhost:3013/api/memory/index \
850
- -H "Authorization: Bearer 123123" \
851
- -H "Content-Type: application/json" \
852
- -H "X-Agent-ID: $(uuidgen)" \
853
- -d '{"agentId":"<agent-uuid>","content":"The auth header needs Bearer prefix","name":"auth-fix","scope":"agent","source":"manual"}'
854
-
855
- # 3. Wait 2s for async embedding
856
- sleep 2
857
-
858
- # 4. Verify memory exists
859
- sqlite3 agent-swarm-db.sqlite "SELECT id, name, source, length(embedding) FROM agent_memory"
860
-
861
- # 5. Search via MCP tool (requires MCP session - see CLAUDE.md "MCP Tool Testing")
862
- # Initialize session, then:
863
- curl -s -X POST http://localhost:3013/mcp \
864
- -H "Authorization: Bearer 123123" \
865
- -H "Content-Type: application/json" \
866
- -H "Accept: application/json, text/event-stream" \
867
- -H "X-Agent-ID: <agent-uuid>" \
868
- -H "mcp-session-id: $SESSION_ID" \
869
- -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"memory-search","arguments":{"query":"authentication header","limit":5}}}'
870
-
871
- # 6. Docker E2E (full hook integration)
872
- # Build worker: docker build -f Dockerfile.worker -t agent-swarm-worker:memory .
873
- # Start worker, create a task that writes to /workspace/personal/memory/
874
- # Verify memory appears in DB after task completes
875
- ```
876
-
877
- ## References
878
-
879
- - **Research document**: [`thoughts/taras/research/2026-02-19-swarm-gaps-implementation.md`](../research/2026-02-19-swarm-gaps-implementation.md) — Gap 2: Memory System section (lines 88-221)
880
- - **Related research**: [`thoughts/taras/research/2026-02-19-agent-native-swarm-architecture.md`](../research/2026-02-19-agent-native-swarm-architecture.md) — OpenClaw's self-learning loop analysis
881
- - **Identity implementation (Gap 1)**: [`thoughts/taras/plans/2026-02-20-worker-identity.md`](2026-02-20-worker-identity.md) — Pattern reference for the identity system this builds on
882
- - **Session attachment (Gap 3)**: [`thoughts/taras/plans/2026-02-20-session-attach.md`](2026-02-20-session-attach.md) — Session continuity that memory enhances