macro-agent 0.0.10 → 0.0.12

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 (518) hide show
  1. package/.macro-agent/teams/self-driving/prompts/grinder.md +27 -0
  2. package/.macro-agent/teams/self-driving/prompts/judge.md +27 -0
  3. package/.macro-agent/teams/self-driving/prompts/planner.md +33 -0
  4. package/.macro-agent/teams/self-driving/roles/grinder.yaml +17 -0
  5. package/.macro-agent/teams/self-driving/roles/judge.yaml +24 -0
  6. package/.macro-agent/teams/self-driving/roles/planner.yaml +18 -0
  7. package/.macro-agent/teams/self-driving/team.yaml +103 -0
  8. package/.macro-agent/teams/structured/prompts/developer.md +26 -0
  9. package/.macro-agent/teams/structured/prompts/lead.md +25 -0
  10. package/.macro-agent/teams/structured/prompts/reviewer.md +24 -0
  11. package/.macro-agent/teams/structured/roles/developer.yaml +12 -0
  12. package/.macro-agent/teams/structured/roles/lead.yaml +11 -0
  13. package/.macro-agent/teams/structured/roles/reviewer.yaml +19 -0
  14. package/.macro-agent/teams/structured/team.yaml +89 -0
  15. package/.sudocode/issues.jsonl +56 -51
  16. package/.sudocode/specs.jsonl +8 -1
  17. package/CLAUDE.md +121 -30
  18. package/README.md +60 -3
  19. package/dist/acp/macro-agent.d.ts +4 -0
  20. package/dist/acp/macro-agent.d.ts.map +1 -1
  21. package/dist/acp/macro-agent.js +50 -4
  22. package/dist/acp/macro-agent.js.map +1 -1
  23. package/dist/acp/session-mapper.d.ts +20 -1
  24. package/dist/acp/session-mapper.d.ts.map +1 -1
  25. package/dist/acp/session-mapper.js +90 -1
  26. package/dist/acp/session-mapper.js.map +1 -1
  27. package/dist/acp/types.d.ts +24 -1
  28. package/dist/acp/types.d.ts.map +1 -1
  29. package/dist/acp/types.js.map +1 -1
  30. package/dist/agent/agent-manager.d.ts +40 -1
  31. package/dist/agent/agent-manager.d.ts.map +1 -1
  32. package/dist/agent/agent-manager.js +172 -8
  33. package/dist/agent/agent-manager.js.map +1 -1
  34. package/dist/agent/types.d.ts +22 -0
  35. package/dist/agent/types.d.ts.map +1 -1
  36. package/dist/agent/types.js.map +1 -1
  37. package/dist/agent/wake.d.ts +15 -0
  38. package/dist/agent/wake.d.ts.map +1 -1
  39. package/dist/agent/wake.js +15 -0
  40. package/dist/agent/wake.js.map +1 -1
  41. package/dist/agent-detection/command-builder.d.ts +30 -0
  42. package/dist/agent-detection/command-builder.d.ts.map +1 -0
  43. package/dist/agent-detection/command-builder.js +71 -0
  44. package/dist/agent-detection/command-builder.js.map +1 -0
  45. package/dist/agent-detection/detector.d.ts +84 -0
  46. package/dist/agent-detection/detector.d.ts.map +1 -0
  47. package/dist/agent-detection/detector.js +240 -0
  48. package/dist/agent-detection/detector.js.map +1 -0
  49. package/dist/agent-detection/index.d.ts +12 -0
  50. package/dist/agent-detection/index.d.ts.map +1 -0
  51. package/dist/agent-detection/index.js +14 -0
  52. package/dist/agent-detection/index.js.map +1 -0
  53. package/dist/agent-detection/registry.d.ts +53 -0
  54. package/dist/agent-detection/registry.d.ts.map +1 -0
  55. package/dist/agent-detection/registry.js +177 -0
  56. package/dist/agent-detection/registry.js.map +1 -0
  57. package/dist/agent-detection/types.d.ts +121 -0
  58. package/dist/agent-detection/types.d.ts.map +1 -0
  59. package/dist/agent-detection/types.js +20 -0
  60. package/dist/agent-detection/types.js.map +1 -0
  61. package/dist/api/server.d.ts +5 -1
  62. package/dist/api/server.d.ts.map +1 -1
  63. package/dist/api/server.js +362 -0
  64. package/dist/api/server.js.map +1 -1
  65. package/dist/api/types.d.ts +50 -1
  66. package/dist/api/types.d.ts.map +1 -1
  67. package/dist/cli/acp.d.ts +2 -0
  68. package/dist/cli/acp.d.ts.map +1 -1
  69. package/dist/cli/acp.js +8 -1
  70. package/dist/cli/acp.js.map +1 -1
  71. package/dist/cli/index.js +29 -0
  72. package/dist/cli/index.js.map +1 -1
  73. package/dist/cli/mcp.js +38 -0
  74. package/dist/cli/mcp.js.map +1 -1
  75. package/dist/config/index.d.ts +2 -0
  76. package/dist/config/index.d.ts.map +1 -0
  77. package/dist/config/index.js +2 -0
  78. package/dist/config/index.js.map +1 -0
  79. package/dist/config/project-config.d.ts +46 -0
  80. package/dist/config/project-config.d.ts.map +1 -0
  81. package/dist/config/project-config.js +68 -0
  82. package/dist/config/project-config.js.map +1 -0
  83. package/dist/lifecycle/cascade.d.ts +1 -1
  84. package/dist/lifecycle/cascade.d.ts.map +1 -1
  85. package/dist/lifecycle/handlers/index.d.ts +4 -0
  86. package/dist/lifecycle/handlers/index.d.ts.map +1 -1
  87. package/dist/lifecycle/handlers/index.js +2 -0
  88. package/dist/lifecycle/handlers/index.js.map +1 -1
  89. package/dist/lifecycle/handlers/worker.d.ts +4 -0
  90. package/dist/lifecycle/handlers/worker.d.ts.map +1 -1
  91. package/dist/lifecycle/handlers/worker.js +35 -3
  92. package/dist/lifecycle/handlers/worker.js.map +1 -1
  93. package/dist/mail/conversation-map.d.ts +33 -0
  94. package/dist/mail/conversation-map.d.ts.map +1 -0
  95. package/dist/mail/conversation-map.js +61 -0
  96. package/dist/mail/conversation-map.js.map +1 -0
  97. package/dist/mail/index.d.ts +11 -0
  98. package/dist/mail/index.d.ts.map +1 -0
  99. package/dist/mail/index.js +11 -0
  100. package/dist/mail/index.js.map +1 -0
  101. package/dist/mail/mail-service.d.ts +85 -0
  102. package/dist/mail/mail-service.d.ts.map +1 -0
  103. package/dist/mail/mail-service.js +121 -0
  104. package/dist/mail/mail-service.js.map +1 -0
  105. package/dist/mail/stores/eventstore-conversation-store.d.ts +40 -0
  106. package/dist/mail/stores/eventstore-conversation-store.d.ts.map +1 -0
  107. package/dist/mail/stores/eventstore-conversation-store.js +131 -0
  108. package/dist/mail/stores/eventstore-conversation-store.js.map +1 -0
  109. package/dist/mail/stores/eventstore-participant-store.d.ts +43 -0
  110. package/dist/mail/stores/eventstore-participant-store.d.ts.map +1 -0
  111. package/dist/mail/stores/eventstore-participant-store.js +145 -0
  112. package/dist/mail/stores/eventstore-participant-store.js.map +1 -0
  113. package/dist/mail/stores/eventstore-thread-store.d.ts +46 -0
  114. package/dist/mail/stores/eventstore-thread-store.d.ts.map +1 -0
  115. package/dist/mail/stores/eventstore-thread-store.js +118 -0
  116. package/dist/mail/stores/eventstore-thread-store.js.map +1 -0
  117. package/dist/mail/stores/eventstore-turn-store.d.ts +47 -0
  118. package/dist/mail/stores/eventstore-turn-store.d.ts.map +1 -0
  119. package/dist/mail/stores/eventstore-turn-store.js +153 -0
  120. package/dist/mail/stores/eventstore-turn-store.js.map +1 -0
  121. package/dist/mail/stores/index.d.ts +12 -0
  122. package/dist/mail/stores/index.d.ts.map +1 -0
  123. package/dist/mail/stores/index.js +12 -0
  124. package/dist/mail/stores/index.js.map +1 -0
  125. package/dist/mail/stores/types.d.ts +146 -0
  126. package/dist/mail/stores/types.d.ts.map +1 -0
  127. package/dist/mail/stores/types.js +13 -0
  128. package/dist/mail/stores/types.js.map +1 -0
  129. package/dist/mail/turn-recorder.d.ts +30 -0
  130. package/dist/mail/turn-recorder.d.ts.map +1 -0
  131. package/dist/mail/turn-recorder.js +98 -0
  132. package/dist/mail/turn-recorder.js.map +1 -0
  133. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  134. package/dist/map/adapter/acp-over-map.js +32 -2
  135. package/dist/map/adapter/acp-over-map.js.map +1 -1
  136. package/dist/map/adapter/event-translator.d.ts.map +1 -1
  137. package/dist/map/adapter/event-translator.js +4 -0
  138. package/dist/map/adapter/event-translator.js.map +1 -1
  139. package/dist/map/adapter/extensions/agent-detection.d.ts +49 -0
  140. package/dist/map/adapter/extensions/agent-detection.d.ts.map +1 -0
  141. package/dist/map/adapter/extensions/agent-detection.js +91 -0
  142. package/dist/map/adapter/extensions/agent-detection.js.map +1 -0
  143. package/dist/map/adapter/extensions/index.d.ts +10 -1
  144. package/dist/map/adapter/extensions/index.d.ts.map +1 -1
  145. package/dist/map/adapter/extensions/index.js +39 -0
  146. package/dist/map/adapter/extensions/index.js.map +1 -1
  147. package/dist/map/adapter/extensions/resume.d.ts +47 -0
  148. package/dist/map/adapter/extensions/resume.d.ts.map +1 -0
  149. package/dist/map/adapter/extensions/resume.js +59 -0
  150. package/dist/map/adapter/extensions/resume.js.map +1 -0
  151. package/dist/map/adapter/extensions/workspace-files.d.ts +42 -0
  152. package/dist/map/adapter/extensions/workspace-files.d.ts.map +1 -0
  153. package/dist/map/adapter/extensions/workspace-files.js +338 -0
  154. package/dist/map/adapter/extensions/workspace-files.js.map +1 -0
  155. package/dist/map/adapter/mail-handler-adapter.d.ts +27 -0
  156. package/dist/map/adapter/mail-handler-adapter.d.ts.map +1 -0
  157. package/dist/map/adapter/mail-handler-adapter.js +292 -0
  158. package/dist/map/adapter/mail-handler-adapter.js.map +1 -0
  159. package/dist/map/adapter/map-adapter.d.ts +34 -10
  160. package/dist/map/adapter/map-adapter.d.ts.map +1 -1
  161. package/dist/map/adapter/map-adapter.js +110 -14
  162. package/dist/map/adapter/map-adapter.js.map +1 -1
  163. package/dist/map/adapter/rpc-handler.d.ts +4 -1
  164. package/dist/map/adapter/rpc-handler.d.ts.map +1 -1
  165. package/dist/map/adapter/rpc-handler.js +6 -0
  166. package/dist/map/adapter/rpc-handler.js.map +1 -1
  167. package/dist/map/index.d.ts +1 -0
  168. package/dist/map/index.d.ts.map +1 -1
  169. package/dist/map/index.js +2 -0
  170. package/dist/map/index.js.map +1 -1
  171. package/dist/map/types.d.ts +3 -1
  172. package/dist/map/types.d.ts.map +1 -1
  173. package/dist/map/types.js.map +1 -1
  174. package/dist/mcp/mcp-server.d.ts +6 -0
  175. package/dist/mcp/mcp-server.d.ts.map +1 -1
  176. package/dist/mcp/mcp-server.js +45 -0
  177. package/dist/mcp/mcp-server.js.map +1 -1
  178. package/dist/mcp/tools/claim_task.d.ts +35 -0
  179. package/dist/mcp/tools/claim_task.d.ts.map +1 -0
  180. package/dist/mcp/tools/claim_task.js +58 -0
  181. package/dist/mcp/tools/claim_task.js.map +1 -0
  182. package/dist/mcp/tools/done.d.ts +15 -2
  183. package/dist/mcp/tools/done.d.ts.map +1 -1
  184. package/dist/mcp/tools/done.js +45 -10
  185. package/dist/mcp/tools/done.js.map +1 -1
  186. package/dist/mcp/tools/list_claimable_tasks.d.ts +38 -0
  187. package/dist/mcp/tools/list_claimable_tasks.d.ts.map +1 -0
  188. package/dist/mcp/tools/list_claimable_tasks.js +63 -0
  189. package/dist/mcp/tools/list_claimable_tasks.js.map +1 -0
  190. package/dist/mcp/tools/unclaim_task.d.ts +31 -0
  191. package/dist/mcp/tools/unclaim_task.d.ts.map +1 -0
  192. package/dist/mcp/tools/unclaim_task.js +47 -0
  193. package/dist/mcp/tools/unclaim_task.js.map +1 -0
  194. package/dist/metrics/index.d.ts +2 -0
  195. package/dist/metrics/index.d.ts.map +1 -0
  196. package/dist/metrics/index.js +2 -0
  197. package/dist/metrics/index.js.map +1 -0
  198. package/dist/metrics/metrics.d.ts +79 -0
  199. package/dist/metrics/metrics.d.ts.map +1 -0
  200. package/dist/metrics/metrics.js +166 -0
  201. package/dist/metrics/metrics.js.map +1 -0
  202. package/dist/roles/capabilities.d.ts +1 -0
  203. package/dist/roles/capabilities.d.ts.map +1 -1
  204. package/dist/roles/capabilities.js +3 -0
  205. package/dist/roles/capabilities.js.map +1 -1
  206. package/dist/roles/types.d.ts +1 -1
  207. package/dist/roles/types.d.ts.map +1 -1
  208. package/dist/router/channels.d.ts +2 -4
  209. package/dist/router/channels.d.ts.map +1 -1
  210. package/dist/router/channels.js.map +1 -1
  211. package/dist/router/message-router.d.ts +85 -9
  212. package/dist/router/message-router.d.ts.map +1 -1
  213. package/dist/router/message-router.js +203 -14
  214. package/dist/router/message-router.js.map +1 -1
  215. package/dist/router/role-resolver.d.ts +10 -1
  216. package/dist/router/role-resolver.d.ts.map +1 -1
  217. package/dist/router/role-resolver.js +15 -1
  218. package/dist/router/role-resolver.js.map +1 -1
  219. package/dist/router/types.d.ts +30 -1
  220. package/dist/router/types.d.ts.map +1 -1
  221. package/dist/router/types.js.map +1 -1
  222. package/dist/server/combined-server.d.ts +6 -0
  223. package/dist/server/combined-server.d.ts.map +1 -1
  224. package/dist/server/combined-server.js +24 -2
  225. package/dist/server/combined-server.js.map +1 -1
  226. package/dist/store/event-store.d.ts +14 -1
  227. package/dist/store/event-store.d.ts.map +1 -1
  228. package/dist/store/event-store.js +456 -4
  229. package/dist/store/event-store.js.map +1 -1
  230. package/dist/store/types/agents.d.ts +1 -1
  231. package/dist/store/types/agents.d.ts.map +1 -1
  232. package/dist/store/types/conversations.d.ts +91 -0
  233. package/dist/store/types/conversations.d.ts.map +1 -0
  234. package/dist/store/types/conversations.js +8 -0
  235. package/dist/store/types/conversations.js.map +1 -0
  236. package/dist/store/types/events.d.ts +1 -1
  237. package/dist/store/types/events.d.ts.map +1 -1
  238. package/dist/store/types/events.js.map +1 -1
  239. package/dist/store/types/index.d.ts +2 -0
  240. package/dist/store/types/index.d.ts.map +1 -1
  241. package/dist/store/types/index.js +2 -0
  242. package/dist/store/types/index.js.map +1 -1
  243. package/dist/store/types/sessions.d.ts +44 -0
  244. package/dist/store/types/sessions.d.ts.map +1 -0
  245. package/dist/store/types/sessions.js +9 -0
  246. package/dist/store/types/sessions.js.map +1 -0
  247. package/dist/store/types/tasks.d.ts +2 -0
  248. package/dist/store/types/tasks.d.ts.map +1 -1
  249. package/dist/task/backend/memory.d.ts +4 -1
  250. package/dist/task/backend/memory.d.ts.map +1 -1
  251. package/dist/task/backend/memory.js +81 -0
  252. package/dist/task/backend/memory.js.map +1 -1
  253. package/dist/task/backend/types.d.ts +30 -0
  254. package/dist/task/backend/types.d.ts.map +1 -1
  255. package/dist/task/backend/types.js.map +1 -1
  256. package/dist/teams/index.d.ts +4 -0
  257. package/dist/teams/index.d.ts.map +1 -0
  258. package/dist/teams/index.js +4 -0
  259. package/dist/teams/index.js.map +1 -0
  260. package/dist/teams/team-loader.d.ts +20 -0
  261. package/dist/teams/team-loader.d.ts.map +1 -0
  262. package/dist/teams/team-loader.js +293 -0
  263. package/dist/teams/team-loader.js.map +1 -0
  264. package/dist/teams/team-runtime.d.ts +139 -0
  265. package/dist/teams/team-runtime.d.ts.map +1 -0
  266. package/dist/teams/team-runtime.js +613 -0
  267. package/dist/teams/team-runtime.js.map +1 -0
  268. package/dist/teams/types.d.ts +266 -0
  269. package/dist/teams/types.d.ts.map +1 -0
  270. package/dist/teams/types.js +20 -0
  271. package/dist/teams/types.js.map +1 -0
  272. package/dist/trigger/router/trigger-router.d.ts +30 -3
  273. package/dist/trigger/router/trigger-router.d.ts.map +1 -1
  274. package/dist/trigger/router/trigger-router.js +30 -3
  275. package/dist/trigger/router/trigger-router.js.map +1 -1
  276. package/dist/trigger/wake/types.d.ts +31 -5
  277. package/dist/trigger/wake/types.d.ts.map +1 -1
  278. package/dist/trigger/wake/types.js +19 -0
  279. package/dist/trigger/wake/types.js.map +1 -1
  280. package/dist/workspace/dataplane-adapter.d.ts +1 -1
  281. package/dist/workspace/dataplane-adapter.d.ts.map +1 -1
  282. package/dist/workspace/dataplane-adapter.js +1 -1
  283. package/dist/workspace/dataplane-adapter.js.map +1 -1
  284. package/dist/workspace/index.d.ts +1 -1
  285. package/dist/workspace/index.d.ts.map +1 -1
  286. package/dist/workspace/strategies/index.d.ts +6 -0
  287. package/dist/workspace/strategies/index.d.ts.map +1 -0
  288. package/dist/workspace/strategies/index.js +5 -0
  289. package/dist/workspace/strategies/index.js.map +1 -0
  290. package/dist/workspace/strategies/optimistic.d.ts +26 -0
  291. package/dist/workspace/strategies/optimistic.d.ts.map +1 -0
  292. package/dist/workspace/strategies/optimistic.js +121 -0
  293. package/dist/workspace/strategies/optimistic.js.map +1 -0
  294. package/dist/workspace/strategies/queue.d.ts +26 -0
  295. package/dist/workspace/strategies/queue.d.ts.map +1 -0
  296. package/dist/workspace/strategies/queue.js +67 -0
  297. package/dist/workspace/strategies/queue.js.map +1 -0
  298. package/dist/workspace/strategies/registry.d.ts +37 -0
  299. package/dist/workspace/strategies/registry.d.ts.map +1 -0
  300. package/dist/workspace/strategies/registry.js +63 -0
  301. package/dist/workspace/strategies/registry.js.map +1 -0
  302. package/dist/workspace/strategies/trunk.d.ts +20 -0
  303. package/dist/workspace/strategies/trunk.d.ts.map +1 -0
  304. package/dist/workspace/strategies/trunk.js +108 -0
  305. package/dist/workspace/strategies/trunk.js.map +1 -0
  306. package/dist/workspace/strategies/types.d.ts +104 -0
  307. package/dist/workspace/strategies/types.d.ts.map +1 -0
  308. package/dist/workspace/strategies/types.js +11 -0
  309. package/dist/workspace/strategies/types.js.map +1 -0
  310. package/dist/workspace/types.d.ts +1 -1
  311. package/dist/workspace/types.d.ts.map +1 -1
  312. package/dist/workspace/workspace-manager.d.ts +1 -1
  313. package/dist/workspace/workspace-manager.d.ts.map +1 -1
  314. package/docs/implementation-details.md +1127 -0
  315. package/docs/implementation-summary.md +448 -0
  316. package/docs/mail-integration.md +608 -0
  317. package/docs/plan-self-driving-support.md +433 -0
  318. package/docs/spec-self-driving-support.md +462 -0
  319. package/docs/team-templates.md +860 -0
  320. package/docs/teams.md +233 -0
  321. package/package.json +5 -3
  322. package/src/acp/__tests__/integration.test.ts +161 -1
  323. package/src/acp/__tests__/macro-agent.test.ts +95 -0
  324. package/src/acp/__tests__/session-persistence.test.ts +276 -0
  325. package/src/acp/macro-agent.ts +79 -7
  326. package/src/acp/session-mapper.ts +108 -1
  327. package/src/acp/types.ts +33 -1
  328. package/src/agent/agent-manager.ts +278 -6
  329. package/src/agent/types.ts +27 -0
  330. package/src/agent/wake.ts +15 -0
  331. package/src/agent-detection/__tests__/command-builder.test.ts +336 -0
  332. package/src/agent-detection/__tests__/detector.test.ts +768 -0
  333. package/src/agent-detection/__tests__/registry.test.ts +254 -0
  334. package/src/agent-detection/command-builder.ts +90 -0
  335. package/src/agent-detection/detector.ts +307 -0
  336. package/src/agent-detection/index.ts +36 -0
  337. package/src/agent-detection/registry.ts +200 -0
  338. package/src/agent-detection/types.ts +184 -0
  339. package/src/api/__tests__/conversation-api.test.ts +468 -0
  340. package/src/api/server.ts +425 -1
  341. package/src/api/types.ts +64 -1
  342. package/src/cli/acp.ts +9 -1
  343. package/src/cli/index.ts +44 -0
  344. package/src/cli/mcp.ts +47 -0
  345. package/src/config/index.ts +9 -0
  346. package/src/config/project-config.ts +107 -0
  347. package/src/lifecycle/cascade.ts +1 -1
  348. package/src/lifecycle/handlers/index.ts +8 -0
  349. package/src/lifecycle/handlers/worker.ts +48 -3
  350. package/src/mail/__tests__/conversation-lifecycle.test.ts +409 -0
  351. package/src/mail/__tests__/eventstore-stores.test.ts +1073 -0
  352. package/src/mail/__tests__/mail-full-agent.e2e.test.ts +575 -0
  353. package/src/mail/__tests__/mail-integration.test.ts +759 -0
  354. package/src/mail/__tests__/mail-map-protocol.e2e.test.ts +1068 -0
  355. package/src/mail/__tests__/mail-service.test.ts +506 -0
  356. package/src/mail/__tests__/turn-recorder.test.ts +328 -0
  357. package/src/mail/conversation-map.ts +107 -0
  358. package/src/mail/index.ts +25 -0
  359. package/src/mail/mail-service.ts +257 -0
  360. package/src/mail/stores/eventstore-conversation-store.ts +146 -0
  361. package/src/mail/stores/eventstore-participant-store.ts +172 -0
  362. package/src/mail/stores/eventstore-thread-store.ts +129 -0
  363. package/src/mail/stores/eventstore-turn-store.ts +173 -0
  364. package/src/mail/stores/index.ts +12 -0
  365. package/src/mail/stores/types.ts +160 -0
  366. package/src/mail/turn-recorder.ts +124 -0
  367. package/src/map/README.md +79 -0
  368. package/src/map/adapter/__tests__/extensions.test.ts +359 -0
  369. package/src/map/adapter/__tests__/map-adapter.test.ts +90 -0
  370. package/src/map/adapter/__tests__/workspace-files.test.ts +673 -0
  371. package/src/map/adapter/acp-over-map.ts +45 -2
  372. package/src/map/adapter/event-translator.ts +4 -0
  373. package/src/map/adapter/extensions/agent-detection.ts +201 -0
  374. package/src/map/adapter/extensions/index.ts +63 -0
  375. package/src/map/adapter/extensions/resume.ts +114 -0
  376. package/src/map/adapter/extensions/workspace-files.ts +449 -0
  377. package/src/map/adapter/mail-handler-adapter.ts +429 -0
  378. package/src/map/adapter/map-adapter.ts +173 -27
  379. package/src/map/adapter/rpc-handler.ts +8 -1
  380. package/src/map/index.ts +3 -0
  381. package/src/map/types.ts +3 -1
  382. package/src/mcp/mcp-server.ts +67 -0
  383. package/src/mcp/tools/claim_task.ts +86 -0
  384. package/src/mcp/tools/done.ts +59 -10
  385. package/src/mcp/tools/list_claimable_tasks.ts +93 -0
  386. package/src/mcp/tools/unclaim_task.ts +71 -0
  387. package/src/metrics/index.ts +9 -0
  388. package/src/metrics/metrics.ts +280 -0
  389. package/src/roles/capabilities.ts +3 -0
  390. package/src/roles/types.ts +2 -1
  391. package/src/router/README.md +120 -0
  392. package/src/router/__tests__/message-router.test.ts +561 -0
  393. package/src/router/channels.ts +3 -4
  394. package/src/router/message-router.ts +308 -22
  395. package/src/router/role-resolver.ts +22 -1
  396. package/src/router/types.ts +36 -1
  397. package/src/server/combined-server.ts +36 -2
  398. package/src/store/README.md +134 -0
  399. package/src/store/event-store.ts +546 -3
  400. package/src/store/types/agents.ts +1 -1
  401. package/src/store/types/conversations.ts +129 -0
  402. package/src/store/types/events.ts +5 -1
  403. package/src/store/types/index.ts +2 -0
  404. package/src/store/types/sessions.ts +53 -0
  405. package/src/store/types/tasks.ts +3 -0
  406. package/src/task/backend/memory.ts +116 -0
  407. package/src/task/backend/types.ts +43 -0
  408. package/src/teams/__tests__/cross-subsystem.integration.test.ts +983 -0
  409. package/src/teams/__tests__/e2e/team-runtime.e2e.test.ts +553 -0
  410. package/src/teams/__tests__/team-system.test.ts +1280 -0
  411. package/src/teams/index.ts +13 -0
  412. package/src/teams/team-loader.ts +434 -0
  413. package/src/teams/team-runtime.ts +727 -0
  414. package/src/teams/types.ts +377 -0
  415. package/src/trigger/router/trigger-router.ts +30 -3
  416. package/src/trigger/wake/types.ts +32 -5
  417. package/src/trigger/wake/wake-manager.ts +2 -2
  418. package/src/workspace/dataplane-adapter.ts +1 -1
  419. package/src/workspace/index.ts +1 -1
  420. package/src/workspace/strategies/index.ts +18 -0
  421. package/src/workspace/strategies/optimistic.ts +136 -0
  422. package/src/workspace/strategies/queue.ts +81 -0
  423. package/src/workspace/strategies/registry.ts +89 -0
  424. package/src/workspace/strategies/trunk.ts +123 -0
  425. package/src/workspace/strategies/types.ts +145 -0
  426. package/src/workspace/types.ts +1 -1
  427. package/src/workspace/workspace-manager.ts +1 -1
  428. package/.claude/settings.local.json +0 -59
  429. package/dist/map/utils/address-translation.d.ts +0 -99
  430. package/dist/map/utils/address-translation.d.ts.map +0 -1
  431. package/dist/map/utils/address-translation.js +0 -285
  432. package/dist/map/utils/address-translation.js.map +0 -1
  433. package/dist/map/utils/index.d.ts +0 -7
  434. package/dist/map/utils/index.d.ts.map +0 -1
  435. package/dist/map/utils/index.js +0 -7
  436. package/dist/map/utils/index.js.map +0 -1
  437. package/openspec/AGENTS.md +0 -456
  438. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/design.md +0 -128
  439. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/proposal.md +0 -49
  440. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/agent-manager/spec.md +0 -150
  441. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/cli-api/spec.md +0 -258
  442. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/event-store/spec.md +0 -160
  443. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/mcp-tools/spec.md +0 -224
  444. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/message-router/spec.md +0 -153
  445. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/task-manager/spec.md +0 -136
  446. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/tasks.md +0 -147
  447. package/openspec/project.md +0 -31
  448. package/openspec/specs/agent-manager/spec.md +0 -154
  449. package/openspec/specs/cli-api/spec.md +0 -262
  450. package/openspec/specs/event-store/spec.md +0 -164
  451. package/openspec/specs/mcp-tools/spec.md +0 -228
  452. package/openspec/specs/message-router/spec.md +0 -157
  453. package/openspec/specs/task-manager/spec.md +0 -140
  454. package/references/acp-factory-ref/CHANGELOG.md +0 -33
  455. package/references/acp-factory-ref/LICENSE +0 -21
  456. package/references/acp-factory-ref/README.md +0 -341
  457. package/references/acp-factory-ref/package-lock.json +0 -3102
  458. package/references/acp-factory-ref/package.json +0 -96
  459. package/references/acp-factory-ref/python/CHANGELOG.md +0 -33
  460. package/references/acp-factory-ref/python/LICENSE +0 -21
  461. package/references/acp-factory-ref/python/Makefile +0 -57
  462. package/references/acp-factory-ref/python/README.md +0 -253
  463. package/references/acp-factory-ref/python/pyproject.toml +0 -73
  464. package/references/acp-factory-ref/python/tests/__init__.py +0 -0
  465. package/references/acp-factory-ref/python/tests/e2e/__init__.py +0 -1
  466. package/references/acp-factory-ref/python/tests/e2e/test_codex_e2e.py +0 -349
  467. package/references/acp-factory-ref/python/tests/e2e/test_gemini_e2e.py +0 -165
  468. package/references/acp-factory-ref/python/tests/e2e/test_opencode_e2e.py +0 -296
  469. package/references/acp-factory-ref/python/tests/test_client_handler.py +0 -543
  470. package/references/acp-factory-ref/python/tests/test_pushable.py +0 -199
  471. package/references/claude-code-acp/.github/workflows/ci.yml +0 -45
  472. package/references/claude-code-acp/.github/workflows/publish.yml +0 -34
  473. package/references/claude-code-acp/.prettierrc.json +0 -4
  474. package/references/claude-code-acp/CHANGELOG.md +0 -249
  475. package/references/claude-code-acp/LICENSE +0 -222
  476. package/references/claude-code-acp/README.md +0 -53
  477. package/references/claude-code-acp/docs/RELEASES.md +0 -24
  478. package/references/claude-code-acp/eslint.config.js +0 -48
  479. package/references/claude-code-acp/package-lock.json +0 -4570
  480. package/references/claude-code-acp/package.json +0 -88
  481. package/references/claude-code-acp/scripts/release.sh +0 -119
  482. package/references/claude-code-acp/src/acp-agent.ts +0 -2065
  483. package/references/claude-code-acp/src/index.ts +0 -26
  484. package/references/claude-code-acp/src/lib.ts +0 -38
  485. package/references/claude-code-acp/src/mcp-server.ts +0 -911
  486. package/references/claude-code-acp/src/settings.ts +0 -522
  487. package/references/claude-code-acp/src/tests/.claude/commands/quick-math.md +0 -5
  488. package/references/claude-code-acp/src/tests/.claude/commands/say-hello.md +0 -6
  489. package/references/claude-code-acp/src/tests/acp-agent-fork.test.ts +0 -479
  490. package/references/claude-code-acp/src/tests/acp-agent.test.ts +0 -1502
  491. package/references/claude-code-acp/src/tests/extract-lines.test.ts +0 -103
  492. package/references/claude-code-acp/src/tests/fork-session.test.ts +0 -335
  493. package/references/claude-code-acp/src/tests/replace-and-calculate-location.test.ts +0 -334
  494. package/references/claude-code-acp/src/tests/settings.test.ts +0 -617
  495. package/references/claude-code-acp/src/tests/skills-options.test.ts +0 -187
  496. package/references/claude-code-acp/src/tests/tools.test.ts +0 -318
  497. package/references/claude-code-acp/src/tests/typescript-declarations.test.ts +0 -558
  498. package/references/claude-code-acp/src/tools.ts +0 -819
  499. package/references/claude-code-acp/src/utils.ts +0 -171
  500. package/references/claude-code-acp/tsconfig.json +0 -18
  501. package/references/claude-code-acp/vitest.config.ts +0 -19
  502. package/references/multi-agent-protocol/.sudocode/issues.jsonl +0 -82
  503. package/references/multi-agent-protocol/.sudocode/specs.jsonl +0 -9
  504. package/references/multi-agent-protocol/LICENSE +0 -21
  505. package/references/multi-agent-protocol/README.md +0 -113
  506. package/references/multi-agent-protocol/docs/00-design-specification.md +0 -460
  507. package/references/multi-agent-protocol/docs/01-open-questions.md +0 -1050
  508. package/references/multi-agent-protocol/docs/02-wire-protocol.md +0 -296
  509. package/references/multi-agent-protocol/docs/03-streaming-semantics.md +0 -252
  510. package/references/multi-agent-protocol/docs/04-error-handling.md +0 -231
  511. package/references/multi-agent-protocol/docs/05-connection-model.md +0 -244
  512. package/references/multi-agent-protocol/docs/06-visibility-permissions.md +0 -243
  513. package/references/multi-agent-protocol/docs/07-federation.md +0 -259
  514. package/references/multi-agent-protocol/docs/08-macro-agent-migration.md +0 -253
  515. package/references/multi-agent-protocol/package-lock.json +0 -3239
  516. package/references/multi-agent-protocol/package.json +0 -56
  517. package/references/multi-agent-protocol/schema/meta.json +0 -337
  518. package/references/multi-agent-protocol/schema/schema.json +0 -1828
package/src/api/server.ts CHANGED
@@ -42,6 +42,14 @@ import type {
42
42
  WSTaskUpdate,
43
43
  InjectContextRequest,
44
44
  InjectContextResponse,
45
+ MailConversationSummary,
46
+ MailConversationDetail,
47
+ MailConversationListResponse,
48
+ MailTurnSummary,
49
+ MailTurnListResponse,
50
+ MailConversationQueryParams,
51
+ WSTurnAdded,
52
+ WSConversationUpdate,
45
53
  } from "./types.js";
46
54
  import {
47
55
  injectContext,
@@ -72,6 +80,10 @@ export interface APIServices {
72
80
  agentManager: AgentManager;
73
81
  taskManager: TaskManager;
74
82
  messageRouter: MessageRouter;
83
+ /** Optional mail service for conversation tracking */
84
+ mailService?: import("../mail/mail-service.js").MailService;
85
+ /** Optional conversation map for agent-to-conversation tracking */
86
+ conversationMap?: import("../mail/conversation-map.js").ConversationMap;
75
87
  }
76
88
 
77
89
  // ─────────────────────────────────────────────────────────────────
@@ -197,6 +209,140 @@ export function createAPISharedState(): APISharedState {
197
209
  };
198
210
  }
199
211
 
212
+ // ─────────────────────────────────────────────────────────────────
213
+ // Conversation API Routes (shared between standalone and app mode)
214
+ // ─────────────────────────────────────────────────────────────────
215
+
216
+ import type { Conversation, ConversationTurn } from "../store/types/conversations.js";
217
+
218
+ function conversationToSummary(conv: Conversation): MailConversationSummary {
219
+ return {
220
+ id: conv.id,
221
+ type: conv.type,
222
+ status: conv.status,
223
+ subject: conv.subject ?? "",
224
+ created_by: conv.createdBy,
225
+ created_at: conv.createdAt,
226
+ updated_at: conv.updatedAt,
227
+ participant_count: conv.participantCount,
228
+ parent_conversation_id: conv.parentConversationId || undefined,
229
+ };
230
+ }
231
+
232
+ function conversationToDetail(conv: Conversation): MailConversationDetail {
233
+ return {
234
+ ...conversationToSummary(conv),
235
+ closed_at: conv.closedAt || undefined,
236
+ closed_by: conv.closedBy || undefined,
237
+ close_reason: conv.closeReason || undefined,
238
+ };
239
+ }
240
+
241
+ function turnToSummary(turn: ConversationTurn): MailTurnSummary {
242
+ return {
243
+ id: turn.id,
244
+ conversation_id: turn.conversationId,
245
+ participant: turn.participant,
246
+ content_type: turn.contentType,
247
+ content: turn.content,
248
+ timestamp: turn.timestamp,
249
+ source_type: turn.sourceType || undefined,
250
+ source_message_id: turn.sourceMessageId || undefined,
251
+ };
252
+ }
253
+
254
+ /**
255
+ * Register conversation API routes on an Express app.
256
+ * Used by both standalone and shared server modes.
257
+ */
258
+ function registerConversationRoutes(
259
+ app: Express,
260
+ services: Pick<APIServices, "mailService">,
261
+ sendError: (res: Response, status: number, code: string, message: string) => void
262
+ ): void {
263
+ if (!services.mailService) return;
264
+ const { mailService } = services;
265
+
266
+ // GET /api/conversations - List conversations
267
+ app.get("/api/conversations", (req: Request, res: Response) => {
268
+ const params = req.query as Record<string, string | undefined>;
269
+ let conversations = mailService.listConversations({
270
+ type: params.type as any,
271
+ status: params.status as any,
272
+ });
273
+
274
+ const total = conversations.length;
275
+ const offset = parseInt(params.offset as string) || 0;
276
+ const limit = parseInt(params.limit as string) || 50;
277
+ conversations = conversations.slice(offset, offset + limit);
278
+
279
+ const response: MailConversationListResponse = {
280
+ conversations: conversations.map(conversationToSummary),
281
+ total,
282
+ };
283
+ res.json(response);
284
+ });
285
+
286
+ // GET /api/conversations/:id - Get conversation detail
287
+ app.get("/api/conversations/:id", (req: Request, res: Response) => {
288
+ const conv = mailService.getConversation(req.params.id);
289
+ if (!conv) {
290
+ return sendError(res, 404, "CONVERSATION_NOT_FOUND", `Conversation not found: ${req.params.id}`);
291
+ }
292
+ res.json(conversationToDetail(conv));
293
+ });
294
+
295
+ // GET /api/conversations/:id/turns - List turns for a conversation
296
+ app.get("/api/conversations/:id/turns", (req: Request, res: Response) => {
297
+ const conv = mailService.getConversation(req.params.id);
298
+ if (!conv) {
299
+ return sendError(res, 404, "CONVERSATION_NOT_FOUND", `Conversation not found: ${req.params.id}`);
300
+ }
301
+
302
+ const turns = mailService.listTurns({ conversationId: req.params.id });
303
+ const limit = parseInt(req.query.limit as string) || 50;
304
+ const offset = parseInt(req.query.offset as string) || 0;
305
+ const paged = turns.slice(offset, offset + limit);
306
+
307
+ const response: MailTurnListResponse = {
308
+ turns: paged.map(turnToSummary),
309
+ total: turns.length,
310
+ };
311
+ res.json(response);
312
+ });
313
+
314
+ // POST /api/conversations/:id/close - Close a conversation
315
+ app.post("/api/conversations/:id/close", (req: Request, res: Response) => {
316
+ const conv = mailService.getConversation(req.params.id);
317
+ if (!conv) {
318
+ return sendError(res, 404, "CONVERSATION_NOT_FOUND", `Conversation not found: ${req.params.id}`);
319
+ }
320
+ if (conv.status !== "active") {
321
+ return sendError(res, 400, "ALREADY_CLOSED", `Conversation already ${conv.status}`);
322
+ }
323
+
324
+ const body = req.body as { reason?: string };
325
+ mailService.closeConversation({
326
+ conversationId: req.params.id,
327
+ closedBy: "api",
328
+ reason: body.reason ?? "completed",
329
+ });
330
+
331
+ res.json({ success: true });
332
+ });
333
+
334
+ // GET /api/conversations/:id/participants - List participants
335
+ app.get("/api/conversations/:id/participants", (req: Request, res: Response) => {
336
+ const conv = mailService.getConversation(req.params.id);
337
+ if (!conv) {
338
+ return sendError(res, 404, "CONVERSATION_NOT_FOUND", `Conversation not found: ${req.params.id}`);
339
+ }
340
+
341
+ const participants = mailService.listParticipants(req.params.id);
342
+ res.json({ participants, total: participants.length });
343
+ });
344
+ }
345
+
200
346
  // ─────────────────────────────────────────────────────────────────
201
347
  // Create API Server
202
348
  // ─────────────────────────────────────────────────────────────────
@@ -366,6 +512,25 @@ export function createAPIServer(
366
512
  state.headManagerId = headManager.id;
367
513
  state.startedAt = Date.now();
368
514
 
515
+ // Create session conversation for mail tracking
516
+ if (services.mailService && services.conversationMap) {
517
+ try {
518
+ const { conversationId } = services.mailService.createConversation({
519
+ type: "session",
520
+ subject: "User session",
521
+ createdBy: "user",
522
+ });
523
+ services.mailService.joinConversation({
524
+ conversationId,
525
+ participantId: headManager.id,
526
+ role: "worker",
527
+ });
528
+ services.conversationMap.setSessionConversation(headManager.id, conversationId);
529
+ } catch {
530
+ // Never fail init due to mail errors
531
+ }
532
+ }
533
+
369
534
  const response: InitResponse = {
370
535
  success: true,
371
536
  head_manager_id: headManager.id,
@@ -384,6 +549,116 @@ export function createAPIServer(
384
549
  res.json(status);
385
550
  });
386
551
 
552
+ // GET /api/team - Get active team info
553
+ app.get("/api/team", (_req: Request, res: Response) => {
554
+ // Check for team config in EventStore
555
+ const statusEvents = eventStore.query({ type: "status", limit: 50 });
556
+ const teamConfigEvent = statusEvents.find(
557
+ (e) => e.payload?.team_config != null
558
+ );
559
+
560
+ if (!teamConfigEvent?.payload?.team_config) {
561
+ res.json({ active: false });
562
+ return;
563
+ }
564
+
565
+ const tc = teamConfigEvent.payload.team_config as Record<string, unknown>;
566
+ res.json({
567
+ active: true,
568
+ name: tc.teamName,
569
+ strategy: tc.strategy,
570
+ taskMode: tc.taskMode,
571
+ enforcement: tc.enforcement,
572
+ });
573
+ });
574
+
575
+ // ─────────────────────────────────────────────────────────────────
576
+ // Metrics Endpoints (Phase 5)
577
+ // ─────────────────────────────────────────────────────────────────
578
+
579
+ // GET /api/metrics/throughput - Task throughput metrics
580
+ app.get("/api/metrics/throughput", (req: Request, res: Response) => {
581
+ const windowMs = req.query.window_ms
582
+ ? Number(req.query.window_ms)
583
+ : 5 * 60 * 1000;
584
+ const after = Date.now() - windowMs;
585
+
586
+ const taskEvents = eventStore.query({ type: "task", after });
587
+ let completed = 0, failed = 0, created = 0;
588
+ for (const e of taskEvents) {
589
+ const action = e.payload?.action as string | undefined;
590
+ if (action === "created") created++;
591
+ else if (action === "completed") completed++;
592
+ else if (action === "failed") failed++;
593
+ }
594
+ const windowMin = windowMs / 60000;
595
+
596
+ res.json({
597
+ tasksCompleted: completed,
598
+ tasksFailed: failed,
599
+ tasksCreated: created,
600
+ completedPerMinute: windowMin > 0 ? Math.round((completed / windowMin) * 100) / 100 : 0,
601
+ windowMs,
602
+ });
603
+ });
604
+
605
+ // GET /api/metrics/utilization - Agent utilization metrics
606
+ app.get("/api/metrics/utilization", (_req: Request, res: Response) => {
607
+ const allAgents = eventStore.listAgents();
608
+ const active = allAgents.filter(
609
+ (a) => a.state === "running" || a.state === "spawning"
610
+ );
611
+ const byRole: Record<string, number> = {};
612
+ const byState: Record<string, number> = {};
613
+ for (const a of active) {
614
+ const role = a.role ?? "unknown";
615
+ byRole[role] = (byRole[role] ?? 0) + 1;
616
+ }
617
+ for (const a of allAgents) {
618
+ byState[a.state] = (byState[a.state] ?? 0) + 1;
619
+ }
620
+
621
+ res.json({
622
+ activeAgents: active.length,
623
+ totalAgents: allAgents.length,
624
+ agentsByRole: byRole,
625
+ agentsByState: byState,
626
+ });
627
+ });
628
+
629
+ // GET /api/metrics/errors - Error metrics
630
+ app.get("/api/metrics/errors", (req: Request, res: Response) => {
631
+ const windowMs = req.query.window_ms
632
+ ? Number(req.query.window_ms)
633
+ : 30 * 60 * 1000;
634
+ const limit = req.query.limit ? Number(req.query.limit) : 20;
635
+
636
+ const statusEvents = eventStore.query({
637
+ type: "status",
638
+ after: Date.now() - windowMs,
639
+ });
640
+
641
+ const errors: Array<{ timestamp: number; agentId: string; type: string; summary: string }> = [];
642
+ const byType: Record<string, number> = {};
643
+
644
+ for (const e of statusEvents) {
645
+ if (e.payload?.status_type !== "failed") continue;
646
+ const agentId = (e.source as { agent_id?: string })?.agent_id ?? "unknown";
647
+ const summary = (e.payload?.summary as string) ?? "Unknown error";
648
+ const errorType = ((e.payload?.details as Record<string, unknown>)?.signal as string) ?? "agent_failed";
649
+ errors.push({ timestamp: e.timestamp, agentId, type: errorType, summary });
650
+ byType[errorType] = (byType[errorType] ?? 0) + 1;
651
+ }
652
+
653
+ errors.sort((a, b) => b.timestamp - a.timestamp);
654
+
655
+ res.json({
656
+ totalErrors: errors.length,
657
+ errorsByType: byType,
658
+ recentErrors: errors.slice(0, limit),
659
+ });
660
+ });
661
+
387
662
  // POST /api/conversation/message - Send message to head manager
388
663
  app.post("/api/conversation/message", async (req: Request, res: Response) => {
389
664
  // Reject new messages during shutdown
@@ -410,6 +685,23 @@ export function createAPIServer(
410
685
  timestamp: Date.now(),
411
686
  });
412
687
 
688
+ // Record user turn in session conversation
689
+ if (services.mailService && services.conversationMap && state.headManagerId) {
690
+ try {
691
+ const sessionConvId = services.conversationMap.getSessionConversation(state.headManagerId);
692
+ if (sessionConvId) {
693
+ services.mailService.recordTurn({
694
+ conversationId: sessionConvId,
695
+ participant: "user",
696
+ contentType: "text",
697
+ content: body.message,
698
+ });
699
+ }
700
+ } catch {
701
+ // Never fail message handling due to mail errors
702
+ }
703
+ }
704
+
413
705
  // Broadcast to conversation channel
414
706
  broadcastToChannel("conversation", {
415
707
  type: "message",
@@ -452,6 +744,23 @@ export function createAPIServer(
452
744
  timestamp: Date.now(),
453
745
  });
454
746
 
747
+ // Record assistant turn in session conversation
748
+ if (services.mailService && services.conversationMap && state.headManagerId) {
749
+ try {
750
+ const sessionConvId = services.conversationMap.getSessionConversation(state.headManagerId);
751
+ if (sessionConvId) {
752
+ services.mailService.recordTurn({
753
+ conversationId: sessionConvId,
754
+ participant: state.headManagerId,
755
+ contentType: "text",
756
+ content: responseContent,
757
+ });
758
+ }
759
+ } catch {
760
+ // Never fail message handling due to mail errors
761
+ }
762
+ }
763
+
455
764
  // Broadcast response
456
765
  broadcastToChannel("conversation", {
457
766
  type: "message",
@@ -686,6 +995,9 @@ export function createAPIServer(
686
995
  }
687
996
  });
688
997
 
998
+ // Register conversation API routes (if mail service available)
999
+ registerConversationRoutes(app, services, sendError);
1000
+
689
1001
  // ─────────────────────────────────────────────────────────────────
690
1002
  // HTTP Server
691
1003
  // ─────────────────────────────────────────────────────────────────
@@ -756,6 +1068,34 @@ export function createAPIServer(
756
1068
  broadcastToChannel("tasks", update);
757
1069
  });
758
1070
 
1071
+ // Listen for conversation changes (if available)
1072
+ if (eventStore.onConversationChange) {
1073
+ eventStore.onConversationChange((conversationId, conversation) => {
1074
+ if (!conversation) return;
1075
+
1076
+ const update: WSConversationUpdate = {
1077
+ type: "conversation_update",
1078
+ conversation: conversationToSummary(conversation),
1079
+ };
1080
+
1081
+ broadcastToChannel("conversations", update);
1082
+ broadcastToChannel(`conversation:${conversationId}`, update);
1083
+ });
1084
+ }
1085
+
1086
+ // Listen for turn changes (if available)
1087
+ if (eventStore.onTurnChange) {
1088
+ eventStore.onTurnChange((conversationId, turn) => {
1089
+ const update: WSTurnAdded = {
1090
+ type: "turn_added",
1091
+ conversation_id: conversationId,
1092
+ turn: turnToSummary(turn),
1093
+ };
1094
+
1095
+ broadcastToChannel(`conversation:${conversationId}`, update);
1096
+ });
1097
+ }
1098
+
759
1099
  // ─────────────────────────────────────────────────────────────────
760
1100
  // Server Lifecycle
761
1101
  // ─────────────────────────────────────────────────────────────────
@@ -900,7 +1240,7 @@ export function createAPIServer(
900
1240
  * @returns Express app
901
1241
  */
902
1242
  export function createAPIApp(
903
- services: Pick<APIServices, "eventStore" | "agentManager" | "taskManager" | "messageRouter">,
1243
+ services: Pick<APIServices, "eventStore" | "agentManager" | "taskManager" | "messageRouter"> & Pick<Partial<APIServices>, "mailService" | "conversationMap">,
904
1244
  config: { cors?: boolean } = {}
905
1245
  ): Express {
906
1246
  const { cors = true } = config;
@@ -1051,6 +1391,25 @@ export function createAPIApp(
1051
1391
  state.headManagerId = headManager.id;
1052
1392
  state.startedAt = Date.now();
1053
1393
 
1394
+ // Create session conversation for mail tracking
1395
+ if (services.mailService && services.conversationMap) {
1396
+ try {
1397
+ const { conversationId } = services.mailService.createConversation({
1398
+ type: "session",
1399
+ subject: "User session",
1400
+ createdBy: "user",
1401
+ });
1402
+ services.mailService.joinConversation({
1403
+ conversationId,
1404
+ participantId: headManager.id,
1405
+ role: "worker",
1406
+ });
1407
+ services.conversationMap.setSessionConversation(headManager.id, conversationId);
1408
+ } catch {
1409
+ // Never fail init due to mail errors
1410
+ }
1411
+ }
1412
+
1054
1413
  const response: InitResponse = {
1055
1414
  success: true,
1056
1415
  head_manager_id: headManager.id,
@@ -1116,6 +1475,23 @@ export function createAPIApp(
1116
1475
  timestamp: Date.now(),
1117
1476
  });
1118
1477
 
1478
+ // Record user turn in session conversation
1479
+ if (services.mailService && services.conversationMap && state.headManagerId) {
1480
+ try {
1481
+ const sessionConvId = services.conversationMap.getSessionConversation(state.headManagerId);
1482
+ if (sessionConvId) {
1483
+ services.mailService.recordTurn({
1484
+ conversationId: sessionConvId,
1485
+ participant: "user",
1486
+ contentType: "text",
1487
+ content: body.message,
1488
+ });
1489
+ }
1490
+ } catch {
1491
+ // Never fail message handling due to mail errors
1492
+ }
1493
+ }
1494
+
1119
1495
  // Broadcast to conversation channel
1120
1496
  state.broadcast("conversation", {
1121
1497
  type: "message",
@@ -1158,6 +1534,23 @@ export function createAPIApp(
1158
1534
  timestamp: Date.now(),
1159
1535
  });
1160
1536
 
1537
+ // Record assistant turn in session conversation
1538
+ if (services.mailService && services.conversationMap && state.headManagerId) {
1539
+ try {
1540
+ const sessionConvId = services.conversationMap.getSessionConversation(state.headManagerId);
1541
+ if (sessionConvId) {
1542
+ services.mailService.recordTurn({
1543
+ conversationId: sessionConvId,
1544
+ participant: state.headManagerId,
1545
+ contentType: "text",
1546
+ content: responseContent,
1547
+ });
1548
+ }
1549
+ } catch {
1550
+ // Never fail message handling due to mail errors
1551
+ }
1552
+ }
1553
+
1161
1554
  // Broadcast response
1162
1555
  state.broadcast("conversation", {
1163
1556
  type: "message",
@@ -1393,6 +1786,9 @@ export function createAPIApp(
1393
1786
  }
1394
1787
  });
1395
1788
 
1789
+ // Register conversation API routes (if mail service available)
1790
+ registerConversationRoutes(app, services, sendError);
1791
+
1396
1792
  return app;
1397
1793
  }
1398
1794
 
@@ -1498,6 +1894,34 @@ export function setupAPIWebSocket(
1498
1894
  broadcast("tasks", update);
1499
1895
  });
1500
1896
 
1897
+ // Listen for conversation changes (if available)
1898
+ if (eventStore.onConversationChange) {
1899
+ eventStore.onConversationChange((conversationId, conversation) => {
1900
+ if (!conversation) return;
1901
+
1902
+ const update: WSConversationUpdate = {
1903
+ type: "conversation_update",
1904
+ conversation: conversationToSummary(conversation),
1905
+ };
1906
+
1907
+ broadcast("conversations", update);
1908
+ broadcast(`conversation:${conversationId}`, update);
1909
+ });
1910
+ }
1911
+
1912
+ // Listen for turn changes (if available)
1913
+ if (eventStore.onTurnChange) {
1914
+ eventStore.onTurnChange((conversationId, turn) => {
1915
+ const update: WSTurnAdded = {
1916
+ type: "turn_added",
1917
+ conversation_id: conversationId,
1918
+ turn: turnToSummary(turn),
1919
+ };
1920
+
1921
+ broadcast(`conversation:${conversationId}`, update);
1922
+ });
1923
+ }
1924
+
1501
1925
  return {
1502
1926
  getConnectionCount(): number {
1503
1927
  return wsClients.size;
package/src/api/types.ts CHANGED
@@ -182,7 +182,9 @@ export type WSMessageType =
182
182
  | "task_update"
183
183
  | "message"
184
184
  | "status"
185
- | "error";
185
+ | "error"
186
+ | "conversation_update"
187
+ | "turn_added";
186
188
 
187
189
  export interface WSMessage {
188
190
  type: WSMessageType;
@@ -277,6 +279,67 @@ export interface InjectContextResponse {
277
279
  note?: string;
278
280
  }
279
281
 
282
+ // ─────────────────────────────────────────────────────────────────
283
+ // Mail Conversations
284
+ // ─────────────────────────────────────────────────────────────────
285
+
286
+ export interface MailConversationSummary {
287
+ id: string;
288
+ type: string;
289
+ status: string;
290
+ subject: string;
291
+ created_by: string;
292
+ created_at: Timestamp;
293
+ updated_at: Timestamp;
294
+ participant_count: number;
295
+ parent_conversation_id?: string;
296
+ }
297
+
298
+ export interface MailConversationDetail extends MailConversationSummary {
299
+ closed_at?: Timestamp;
300
+ closed_by?: string;
301
+ close_reason?: string;
302
+ }
303
+
304
+ export interface MailConversationListResponse {
305
+ conversations: MailConversationSummary[];
306
+ total: number;
307
+ }
308
+
309
+ export interface MailTurnSummary {
310
+ id: string;
311
+ conversation_id: string;
312
+ participant: string;
313
+ content_type: string;
314
+ content: unknown;
315
+ timestamp: Timestamp;
316
+ source_type?: string;
317
+ source_message_id?: string;
318
+ }
319
+
320
+ export interface MailTurnListResponse {
321
+ turns: MailTurnSummary[];
322
+ total: number;
323
+ }
324
+
325
+ export interface MailConversationQueryParams {
326
+ type?: string;
327
+ status?: string;
328
+ limit?: number;
329
+ offset?: number;
330
+ }
331
+
332
+ export interface WSTurnAdded {
333
+ type: "turn_added";
334
+ conversation_id: string;
335
+ turn: MailTurnSummary;
336
+ }
337
+
338
+ export interface WSConversationUpdate {
339
+ type: "conversation_update";
340
+ conversation: MailConversationSummary;
341
+ }
342
+
280
343
  // ─────────────────────────────────────────────────────────────────
281
344
  // Error Response
282
345
  // ─────────────────────────────────────────────────────────────────
package/src/cli/acp.ts CHANGED
@@ -81,6 +81,8 @@ export interface ACPServerOptions {
81
81
  port?: number;
82
82
  /** Host for server (default: localhost) */
83
83
  host?: string;
84
+ /** Instance ID to reuse an existing event store (omit for new instance) */
85
+ instanceId?: string;
84
86
  }
85
87
 
86
88
  /**
@@ -108,6 +110,9 @@ export function parseArgs(argv?: string[]): ACPServerOptions {
108
110
  } else if (args[i] === "--host" && args[i + 1]) {
109
111
  options.host = args[i + 1];
110
112
  i++;
113
+ } else if (args[i] === "--instance-id" && args[i + 1]) {
114
+ options.instanceId = args[i + 1];
115
+ i++;
111
116
  }
112
117
  }
113
118
 
@@ -154,7 +159,10 @@ async function main() {
154
159
  const defaultCwd = options.cwd ?? process.cwd();
155
160
 
156
161
  // Initialize services
157
- const eventStore = await createEventStore({ inMemory: false });
162
+ const eventStore = await createEventStore({
163
+ inMemory: false,
164
+ instanceId: options.instanceId,
165
+ });
158
166
 
159
167
  // We need to create agentManager first (with a placeholder router),
160
168
  // then wire the sessionChecker/wakeHandler into the router,