macro-agent 0.0.11 → 0.0.13

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 (408) 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 +6 -0
  16. package/.sudocode/specs.jsonl +7 -0
  17. package/CLAUDE.md +110 -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 +25 -1
  31. package/dist/agent/agent-manager.d.ts.map +1 -1
  32. package/dist/agent/agent-manager.js +93 -7
  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-detection/command-builder.d.ts +30 -0
  38. package/dist/agent-detection/command-builder.d.ts.map +1 -0
  39. package/dist/agent-detection/command-builder.js +71 -0
  40. package/dist/agent-detection/command-builder.js.map +1 -0
  41. package/dist/agent-detection/detector.d.ts +84 -0
  42. package/dist/agent-detection/detector.d.ts.map +1 -0
  43. package/dist/agent-detection/detector.js +240 -0
  44. package/dist/agent-detection/detector.js.map +1 -0
  45. package/dist/agent-detection/index.d.ts +12 -0
  46. package/dist/agent-detection/index.d.ts.map +1 -0
  47. package/dist/agent-detection/index.js +14 -0
  48. package/dist/agent-detection/index.js.map +1 -0
  49. package/dist/agent-detection/registry.d.ts +53 -0
  50. package/dist/agent-detection/registry.d.ts.map +1 -0
  51. package/dist/agent-detection/registry.js +177 -0
  52. package/dist/agent-detection/registry.js.map +1 -0
  53. package/dist/agent-detection/types.d.ts +121 -0
  54. package/dist/agent-detection/types.d.ts.map +1 -0
  55. package/dist/agent-detection/types.js +20 -0
  56. package/dist/agent-detection/types.js.map +1 -0
  57. package/dist/api/server.d.ts.map +1 -1
  58. package/dist/api/server.js +95 -0
  59. package/dist/api/server.js.map +1 -1
  60. package/dist/cli/index.js +29 -0
  61. package/dist/cli/index.js.map +1 -1
  62. package/dist/cli/mcp.js +38 -0
  63. package/dist/cli/mcp.js.map +1 -1
  64. package/dist/config/index.d.ts +2 -0
  65. package/dist/config/index.d.ts.map +1 -0
  66. package/dist/config/index.js +2 -0
  67. package/dist/config/index.js.map +1 -0
  68. package/dist/config/project-config.d.ts +46 -0
  69. package/dist/config/project-config.d.ts.map +1 -0
  70. package/dist/config/project-config.js +68 -0
  71. package/dist/config/project-config.js.map +1 -0
  72. package/dist/lifecycle/cascade.d.ts +1 -1
  73. package/dist/lifecycle/cascade.d.ts.map +1 -1
  74. package/dist/lifecycle/handlers/index.d.ts +4 -0
  75. package/dist/lifecycle/handlers/index.d.ts.map +1 -1
  76. package/dist/lifecycle/handlers/index.js +2 -0
  77. package/dist/lifecycle/handlers/index.js.map +1 -1
  78. package/dist/lifecycle/handlers/worker.d.ts +4 -0
  79. package/dist/lifecycle/handlers/worker.d.ts.map +1 -1
  80. package/dist/lifecycle/handlers/worker.js +35 -3
  81. package/dist/lifecycle/handlers/worker.js.map +1 -1
  82. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  83. package/dist/map/adapter/acp-over-map.js +32 -2
  84. package/dist/map/adapter/acp-over-map.js.map +1 -1
  85. package/dist/map/adapter/event-translator.d.ts.map +1 -1
  86. package/dist/map/adapter/event-translator.js +1 -0
  87. package/dist/map/adapter/event-translator.js.map +1 -1
  88. package/dist/map/adapter/extensions/agent-detection.d.ts +49 -0
  89. package/dist/map/adapter/extensions/agent-detection.d.ts.map +1 -0
  90. package/dist/map/adapter/extensions/agent-detection.js +91 -0
  91. package/dist/map/adapter/extensions/agent-detection.js.map +1 -0
  92. package/dist/map/adapter/extensions/index.d.ts +10 -1
  93. package/dist/map/adapter/extensions/index.d.ts.map +1 -1
  94. package/dist/map/adapter/extensions/index.js +39 -0
  95. package/dist/map/adapter/extensions/index.js.map +1 -1
  96. package/dist/map/adapter/extensions/resume.d.ts +47 -0
  97. package/dist/map/adapter/extensions/resume.d.ts.map +1 -0
  98. package/dist/map/adapter/extensions/resume.js +59 -0
  99. package/dist/map/adapter/extensions/resume.js.map +1 -0
  100. package/dist/map/adapter/extensions/workspace-files.d.ts +42 -0
  101. package/dist/map/adapter/extensions/workspace-files.d.ts.map +1 -0
  102. package/dist/map/adapter/extensions/workspace-files.js +338 -0
  103. package/dist/map/adapter/extensions/workspace-files.js.map +1 -0
  104. package/dist/mcp/mcp-server.d.ts +6 -0
  105. package/dist/mcp/mcp-server.d.ts.map +1 -1
  106. package/dist/mcp/mcp-server.js +45 -0
  107. package/dist/mcp/mcp-server.js.map +1 -1
  108. package/dist/mcp/tools/claim_task.d.ts +35 -0
  109. package/dist/mcp/tools/claim_task.d.ts.map +1 -0
  110. package/dist/mcp/tools/claim_task.js +58 -0
  111. package/dist/mcp/tools/claim_task.js.map +1 -0
  112. package/dist/mcp/tools/done.d.ts +11 -2
  113. package/dist/mcp/tools/done.d.ts.map +1 -1
  114. package/dist/mcp/tools/done.js +15 -10
  115. package/dist/mcp/tools/done.js.map +1 -1
  116. package/dist/mcp/tools/list_claimable_tasks.d.ts +38 -0
  117. package/dist/mcp/tools/list_claimable_tasks.d.ts.map +1 -0
  118. package/dist/mcp/tools/list_claimable_tasks.js +63 -0
  119. package/dist/mcp/tools/list_claimable_tasks.js.map +1 -0
  120. package/dist/mcp/tools/unclaim_task.d.ts +31 -0
  121. package/dist/mcp/tools/unclaim_task.d.ts.map +1 -0
  122. package/dist/mcp/tools/unclaim_task.js +47 -0
  123. package/dist/mcp/tools/unclaim_task.js.map +1 -0
  124. package/dist/metrics/index.d.ts +2 -0
  125. package/dist/metrics/index.d.ts.map +1 -0
  126. package/dist/metrics/index.js +2 -0
  127. package/dist/metrics/index.js.map +1 -0
  128. package/dist/metrics/metrics.d.ts +79 -0
  129. package/dist/metrics/metrics.d.ts.map +1 -0
  130. package/dist/metrics/metrics.js +166 -0
  131. package/dist/metrics/metrics.js.map +1 -0
  132. package/dist/roles/capabilities.d.ts +1 -0
  133. package/dist/roles/capabilities.d.ts.map +1 -1
  134. package/dist/roles/capabilities.js +3 -0
  135. package/dist/roles/capabilities.js.map +1 -1
  136. package/dist/roles/types.d.ts +1 -1
  137. package/dist/roles/types.d.ts.map +1 -1
  138. package/dist/router/message-router.d.ts +41 -0
  139. package/dist/router/message-router.d.ts.map +1 -1
  140. package/dist/router/message-router.js +136 -5
  141. package/dist/router/message-router.js.map +1 -1
  142. package/dist/store/event-store.d.ts +8 -1
  143. package/dist/store/event-store.d.ts.map +1 -1
  144. package/dist/store/event-store.js +120 -4
  145. package/dist/store/event-store.js.map +1 -1
  146. package/dist/store/types/agents.d.ts +1 -1
  147. package/dist/store/types/agents.d.ts.map +1 -1
  148. package/dist/store/types/events.d.ts +1 -1
  149. package/dist/store/types/events.d.ts.map +1 -1
  150. package/dist/store/types/events.js.map +1 -1
  151. package/dist/store/types/index.d.ts +1 -0
  152. package/dist/store/types/index.d.ts.map +1 -1
  153. package/dist/store/types/index.js +1 -0
  154. package/dist/store/types/index.js.map +1 -1
  155. package/dist/store/types/sessions.d.ts +44 -0
  156. package/dist/store/types/sessions.d.ts.map +1 -0
  157. package/dist/store/types/sessions.js +9 -0
  158. package/dist/store/types/sessions.js.map +1 -0
  159. package/dist/store/types/tasks.d.ts +2 -0
  160. package/dist/store/types/tasks.d.ts.map +1 -1
  161. package/dist/task/backend/memory.d.ts +4 -1
  162. package/dist/task/backend/memory.d.ts.map +1 -1
  163. package/dist/task/backend/memory.js +81 -0
  164. package/dist/task/backend/memory.js.map +1 -1
  165. package/dist/task/backend/types.d.ts +30 -0
  166. package/dist/task/backend/types.d.ts.map +1 -1
  167. package/dist/task/backend/types.js.map +1 -1
  168. package/dist/teams/index.d.ts +4 -0
  169. package/dist/teams/index.d.ts.map +1 -0
  170. package/dist/teams/index.js +4 -0
  171. package/dist/teams/index.js.map +1 -0
  172. package/dist/teams/team-loader.d.ts +20 -0
  173. package/dist/teams/team-loader.d.ts.map +1 -0
  174. package/dist/teams/team-loader.js +293 -0
  175. package/dist/teams/team-loader.js.map +1 -0
  176. package/dist/teams/team-runtime.d.ts +139 -0
  177. package/dist/teams/team-runtime.d.ts.map +1 -0
  178. package/dist/teams/team-runtime.js +613 -0
  179. package/dist/teams/team-runtime.js.map +1 -0
  180. package/dist/teams/types.d.ts +266 -0
  181. package/dist/teams/types.d.ts.map +1 -0
  182. package/dist/teams/types.js +20 -0
  183. package/dist/teams/types.js.map +1 -0
  184. package/dist/workspace/dataplane-adapter.d.ts +1 -1
  185. package/dist/workspace/dataplane-adapter.d.ts.map +1 -1
  186. package/dist/workspace/dataplane-adapter.js +1 -1
  187. package/dist/workspace/dataplane-adapter.js.map +1 -1
  188. package/dist/workspace/index.d.ts +1 -1
  189. package/dist/workspace/index.d.ts.map +1 -1
  190. package/dist/workspace/strategies/index.d.ts +6 -0
  191. package/dist/workspace/strategies/index.d.ts.map +1 -0
  192. package/dist/workspace/strategies/index.js +5 -0
  193. package/dist/workspace/strategies/index.js.map +1 -0
  194. package/dist/workspace/strategies/optimistic.d.ts +26 -0
  195. package/dist/workspace/strategies/optimistic.d.ts.map +1 -0
  196. package/dist/workspace/strategies/optimistic.js +121 -0
  197. package/dist/workspace/strategies/optimistic.js.map +1 -0
  198. package/dist/workspace/strategies/queue.d.ts +26 -0
  199. package/dist/workspace/strategies/queue.d.ts.map +1 -0
  200. package/dist/workspace/strategies/queue.js +67 -0
  201. package/dist/workspace/strategies/queue.js.map +1 -0
  202. package/dist/workspace/strategies/registry.d.ts +37 -0
  203. package/dist/workspace/strategies/registry.d.ts.map +1 -0
  204. package/dist/workspace/strategies/registry.js +63 -0
  205. package/dist/workspace/strategies/registry.js.map +1 -0
  206. package/dist/workspace/strategies/trunk.d.ts +20 -0
  207. package/dist/workspace/strategies/trunk.d.ts.map +1 -0
  208. package/dist/workspace/strategies/trunk.js +108 -0
  209. package/dist/workspace/strategies/trunk.js.map +1 -0
  210. package/dist/workspace/strategies/types.d.ts +104 -0
  211. package/dist/workspace/strategies/types.d.ts.map +1 -0
  212. package/dist/workspace/strategies/types.js +11 -0
  213. package/dist/workspace/strategies/types.js.map +1 -0
  214. package/dist/workspace/types.d.ts +1 -1
  215. package/dist/workspace/types.d.ts.map +1 -1
  216. package/dist/workspace/workspace-manager.d.ts +1 -1
  217. package/dist/workspace/workspace-manager.d.ts.map +1 -1
  218. package/docs/implementation-details.md +1127 -0
  219. package/docs/implementation-summary.md +448 -0
  220. package/docs/plan-self-driving-support.md +433 -0
  221. package/docs/spec-self-driving-support.md +462 -0
  222. package/docs/team-templates.md +860 -0
  223. package/docs/teams.md +233 -0
  224. package/package.json +5 -3
  225. package/src/acp/__tests__/integration.test.ts +161 -1
  226. package/src/acp/__tests__/macro-agent.test.ts +95 -0
  227. package/src/acp/__tests__/session-persistence.test.ts +276 -0
  228. package/src/acp/macro-agent.ts +79 -7
  229. package/src/acp/session-mapper.ts +108 -1
  230. package/src/acp/types.ts +33 -1
  231. package/src/agent/agent-manager.ts +158 -6
  232. package/src/agent/types.ts +27 -0
  233. package/src/agent-detection/__tests__/command-builder.test.ts +336 -0
  234. package/src/agent-detection/__tests__/detector.test.ts +768 -0
  235. package/src/agent-detection/__tests__/registry.test.ts +254 -0
  236. package/src/agent-detection/command-builder.ts +90 -0
  237. package/src/agent-detection/detector.ts +307 -0
  238. package/src/agent-detection/index.ts +36 -0
  239. package/src/agent-detection/registry.ts +200 -0
  240. package/src/agent-detection/types.ts +184 -0
  241. package/src/api/server.ts +110 -0
  242. package/src/cli/index.ts +44 -0
  243. package/src/cli/mcp.ts +47 -0
  244. package/src/config/index.ts +9 -0
  245. package/src/config/project-config.ts +107 -0
  246. package/src/lifecycle/cascade.ts +1 -1
  247. package/src/lifecycle/handlers/index.ts +8 -0
  248. package/src/lifecycle/handlers/worker.ts +48 -3
  249. package/src/map/adapter/__tests__/extensions.test.ts +359 -0
  250. package/src/map/adapter/__tests__/workspace-files.test.ts +673 -0
  251. package/src/map/adapter/acp-over-map.ts +45 -2
  252. package/src/map/adapter/event-translator.ts +1 -0
  253. package/src/map/adapter/extensions/agent-detection.ts +201 -0
  254. package/src/map/adapter/extensions/index.ts +63 -0
  255. package/src/map/adapter/extensions/resume.ts +114 -0
  256. package/src/map/adapter/extensions/workspace-files.ts +449 -0
  257. package/src/mcp/mcp-server.ts +67 -0
  258. package/src/mcp/tools/claim_task.ts +86 -0
  259. package/src/mcp/tools/done.ts +24 -10
  260. package/src/mcp/tools/list_claimable_tasks.ts +93 -0
  261. package/src/mcp/tools/unclaim_task.ts +71 -0
  262. package/src/metrics/index.ts +9 -0
  263. package/src/metrics/metrics.ts +280 -0
  264. package/src/roles/capabilities.ts +3 -0
  265. package/src/roles/types.ts +2 -1
  266. package/src/router/__tests__/message-router.test.ts +561 -0
  267. package/src/router/message-router.ts +223 -6
  268. package/src/store/event-store.ts +151 -3
  269. package/src/store/types/agents.ts +1 -1
  270. package/src/store/types/events.ts +2 -1
  271. package/src/store/types/index.ts +1 -0
  272. package/src/store/types/sessions.ts +53 -0
  273. package/src/store/types/tasks.ts +3 -0
  274. package/src/task/backend/memory.ts +116 -0
  275. package/src/task/backend/types.ts +43 -0
  276. package/src/teams/__tests__/cross-subsystem.integration.test.ts +983 -0
  277. package/src/teams/__tests__/e2e/team-runtime.e2e.test.ts +553 -0
  278. package/src/teams/__tests__/team-system.test.ts +1280 -0
  279. package/src/teams/index.ts +13 -0
  280. package/src/teams/team-loader.ts +434 -0
  281. package/src/teams/team-runtime.ts +727 -0
  282. package/src/teams/types.ts +377 -0
  283. package/src/workspace/dataplane-adapter.ts +1 -1
  284. package/src/workspace/index.ts +1 -1
  285. package/src/workspace/strategies/index.ts +18 -0
  286. package/src/workspace/strategies/optimistic.ts +136 -0
  287. package/src/workspace/strategies/queue.ts +81 -0
  288. package/src/workspace/strategies/registry.ts +89 -0
  289. package/src/workspace/strategies/trunk.ts +123 -0
  290. package/src/workspace/strategies/types.ts +145 -0
  291. package/src/workspace/types.ts +1 -1
  292. package/src/workspace/workspace-manager.ts +1 -1
  293. package/.claude/settings.local.json +0 -59
  294. package/dist/map/utils/address-translation.d.ts +0 -99
  295. package/dist/map/utils/address-translation.d.ts.map +0 -1
  296. package/dist/map/utils/address-translation.js +0 -285
  297. package/dist/map/utils/address-translation.js.map +0 -1
  298. package/dist/map/utils/index.d.ts +0 -7
  299. package/dist/map/utils/index.d.ts.map +0 -1
  300. package/dist/map/utils/index.js +0 -7
  301. package/dist/map/utils/index.js.map +0 -1
  302. package/references/acp-factory-ref/CHANGELOG.md +0 -33
  303. package/references/acp-factory-ref/LICENSE +0 -21
  304. package/references/acp-factory-ref/README.md +0 -341
  305. package/references/acp-factory-ref/package-lock.json +0 -3102
  306. package/references/acp-factory-ref/package.json +0 -96
  307. package/references/acp-factory-ref/python/CHANGELOG.md +0 -33
  308. package/references/acp-factory-ref/python/LICENSE +0 -21
  309. package/references/acp-factory-ref/python/Makefile +0 -57
  310. package/references/acp-factory-ref/python/README.md +0 -253
  311. package/references/acp-factory-ref/python/pyproject.toml +0 -73
  312. package/references/acp-factory-ref/python/tests/__init__.py +0 -0
  313. package/references/acp-factory-ref/python/tests/e2e/__init__.py +0 -1
  314. package/references/acp-factory-ref/python/tests/e2e/test_codex_e2e.py +0 -349
  315. package/references/acp-factory-ref/python/tests/e2e/test_gemini_e2e.py +0 -165
  316. package/references/acp-factory-ref/python/tests/e2e/test_opencode_e2e.py +0 -296
  317. package/references/acp-factory-ref/python/tests/test_client_handler.py +0 -543
  318. package/references/acp-factory-ref/python/tests/test_pushable.py +0 -199
  319. package/references/claude-code-acp/.github/workflows/ci.yml +0 -45
  320. package/references/claude-code-acp/.github/workflows/publish.yml +0 -34
  321. package/references/claude-code-acp/.prettierrc.json +0 -4
  322. package/references/claude-code-acp/CHANGELOG.md +0 -249
  323. package/references/claude-code-acp/LICENSE +0 -222
  324. package/references/claude-code-acp/README.md +0 -53
  325. package/references/claude-code-acp/docs/RELEASES.md +0 -24
  326. package/references/claude-code-acp/eslint.config.js +0 -48
  327. package/references/claude-code-acp/package-lock.json +0 -4570
  328. package/references/claude-code-acp/package.json +0 -88
  329. package/references/claude-code-acp/scripts/release.sh +0 -119
  330. package/references/claude-code-acp/src/acp-agent.ts +0 -2065
  331. package/references/claude-code-acp/src/index.ts +0 -26
  332. package/references/claude-code-acp/src/lib.ts +0 -38
  333. package/references/claude-code-acp/src/mcp-server.ts +0 -911
  334. package/references/claude-code-acp/src/settings.ts +0 -522
  335. package/references/claude-code-acp/src/tests/.claude/commands/quick-math.md +0 -5
  336. package/references/claude-code-acp/src/tests/.claude/commands/say-hello.md +0 -6
  337. package/references/claude-code-acp/src/tests/acp-agent-fork.test.ts +0 -479
  338. package/references/claude-code-acp/src/tests/acp-agent.test.ts +0 -1502
  339. package/references/claude-code-acp/src/tests/extract-lines.test.ts +0 -103
  340. package/references/claude-code-acp/src/tests/fork-session.test.ts +0 -335
  341. package/references/claude-code-acp/src/tests/replace-and-calculate-location.test.ts +0 -334
  342. package/references/claude-code-acp/src/tests/settings.test.ts +0 -617
  343. package/references/claude-code-acp/src/tests/skills-options.test.ts +0 -187
  344. package/references/claude-code-acp/src/tests/tools.test.ts +0 -318
  345. package/references/claude-code-acp/src/tests/typescript-declarations.test.ts +0 -558
  346. package/references/claude-code-acp/src/tools.ts +0 -819
  347. package/references/claude-code-acp/src/utils.ts +0 -171
  348. package/references/claude-code-acp/tsconfig.json +0 -18
  349. package/references/claude-code-acp/vitest.config.ts +0 -19
  350. package/references/multi-agent-protocol/.sudocode/issues.jsonl +0 -111
  351. package/references/multi-agent-protocol/.sudocode/specs.jsonl +0 -13
  352. package/references/multi-agent-protocol/LICENSE +0 -21
  353. package/references/multi-agent-protocol/README.md +0 -113
  354. package/references/multi-agent-protocol/docs/00-design-specification.md +0 -496
  355. package/references/multi-agent-protocol/docs/01-open-questions.md +0 -1050
  356. package/references/multi-agent-protocol/docs/02-wire-protocol.md +0 -296
  357. package/references/multi-agent-protocol/docs/03-streaming-semantics.md +0 -252
  358. package/references/multi-agent-protocol/docs/04-error-handling.md +0 -231
  359. package/references/multi-agent-protocol/docs/05-connection-model.md +0 -244
  360. package/references/multi-agent-protocol/docs/06-visibility-permissions.md +0 -243
  361. package/references/multi-agent-protocol/docs/07-federation.md +0 -259
  362. package/references/multi-agent-protocol/docs/08-macro-agent-migration.md +0 -253
  363. package/references/multi-agent-protocol/docs/09-authentication.md +0 -680
  364. package/references/multi-agent-protocol/docs/10-mail-protocol.md +0 -553
  365. package/references/multi-agent-protocol/docs/agent-iam-integration.md +0 -877
  366. package/references/multi-agent-protocol/docs/agentic-mesh-integration-draft.md +0 -459
  367. package/references/multi-agent-protocol/docs/git-transport-draft.md +0 -251
  368. package/references/multi-agent-protocol/docs-site/Gemfile +0 -22
  369. package/references/multi-agent-protocol/docs-site/README.md +0 -82
  370. package/references/multi-agent-protocol/docs-site/_config.yml +0 -91
  371. package/references/multi-agent-protocol/docs-site/_includes/head_custom.html +0 -20
  372. package/references/multi-agent-protocol/docs-site/_sass/color_schemes/map.scss +0 -42
  373. package/references/multi-agent-protocol/docs-site/_sass/custom/custom.scss +0 -34
  374. package/references/multi-agent-protocol/docs-site/examples/full-integration.md +0 -510
  375. package/references/multi-agent-protocol/docs-site/examples/index.md +0 -138
  376. package/references/multi-agent-protocol/docs-site/examples/simple-chat.md +0 -282
  377. package/references/multi-agent-protocol/docs-site/examples/task-queue.md +0 -399
  378. package/references/multi-agent-protocol/docs-site/getting-started/index.md +0 -98
  379. package/references/multi-agent-protocol/docs-site/getting-started/installation.md +0 -219
  380. package/references/multi-agent-protocol/docs-site/getting-started/overview.md +0 -172
  381. package/references/multi-agent-protocol/docs-site/getting-started/quickstart.md +0 -237
  382. package/references/multi-agent-protocol/docs-site/index.md +0 -136
  383. package/references/multi-agent-protocol/docs-site/protocol/authentication.md +0 -391
  384. package/references/multi-agent-protocol/docs-site/protocol/connection-model.md +0 -376
  385. package/references/multi-agent-protocol/docs-site/protocol/design.md +0 -284
  386. package/references/multi-agent-protocol/docs-site/protocol/error-handling.md +0 -312
  387. package/references/multi-agent-protocol/docs-site/protocol/federation.md +0 -449
  388. package/references/multi-agent-protocol/docs-site/protocol/index.md +0 -129
  389. package/references/multi-agent-protocol/docs-site/protocol/permissions.md +0 -398
  390. package/references/multi-agent-protocol/docs-site/protocol/streaming.md +0 -353
  391. package/references/multi-agent-protocol/docs-site/protocol/wire-protocol.md +0 -369
  392. package/references/multi-agent-protocol/docs-site/sdk/api/agent.md +0 -357
  393. package/references/multi-agent-protocol/docs-site/sdk/api/client.md +0 -380
  394. package/references/multi-agent-protocol/docs-site/sdk/api/index.md +0 -62
  395. package/references/multi-agent-protocol/docs-site/sdk/api/server.md +0 -453
  396. package/references/multi-agent-protocol/docs-site/sdk/api/types.md +0 -468
  397. package/references/multi-agent-protocol/docs-site/sdk/guides/agent.md +0 -375
  398. package/references/multi-agent-protocol/docs-site/sdk/guides/authentication.md +0 -405
  399. package/references/multi-agent-protocol/docs-site/sdk/guides/client.md +0 -352
  400. package/references/multi-agent-protocol/docs-site/sdk/guides/index.md +0 -89
  401. package/references/multi-agent-protocol/docs-site/sdk/guides/server.md +0 -360
  402. package/references/multi-agent-protocol/docs-site/sdk/guides/testing.md +0 -446
  403. package/references/multi-agent-protocol/docs-site/sdk/guides/transports.md +0 -363
  404. package/references/multi-agent-protocol/docs-site/sdk/index.md +0 -206
  405. package/references/multi-agent-protocol/package-lock.json +0 -3886
  406. package/references/multi-agent-protocol/package.json +0 -56
  407. package/references/multi-agent-protocol/schema/meta.json +0 -467
  408. package/references/multi-agent-protocol/schema/schema.json +0 -2558
@@ -0,0 +1,276 @@
1
+ /**
2
+ * Session persistence and recovery tests
3
+ *
4
+ * Tests that session lifecycle events are persisted to the EventStore
5
+ * and that SessionMapper can recover its state from persisted sessions.
6
+ */
7
+
8
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
9
+ import { SessionMapper } from "../session-mapper.js";
10
+ import { createEventStore, type EventStore } from "../../store/event-store.js";
11
+
12
+ describe("Session Persistence", () => {
13
+ let eventStore: EventStore;
14
+ let mapper: SessionMapper;
15
+
16
+ beforeEach(async () => {
17
+ eventStore = await createEventStore({ inMemory: true });
18
+ mapper = new SessionMapper(eventStore);
19
+ });
20
+
21
+ afterEach(async () => {
22
+ await eventStore.close();
23
+ });
24
+
25
+ describe("session lifecycle events", () => {
26
+ it("should emit session created event on createMapping", () => {
27
+ mapper.createMapping("session-1", "agent-head");
28
+
29
+ const session = eventStore.getSession("session-1");
30
+ expect(session).not.toBeNull();
31
+ expect(session!.id).toBe("session-1");
32
+ expect(session!.head_manager_id).toBe("agent-head");
33
+ expect(session!.current_agent_id).toBe("agent-head");
34
+ expect(session!.state).toBe("active");
35
+ expect(session!.created_at).toBeGreaterThan(0);
36
+ });
37
+
38
+ it("should emit session mounted event on mount", () => {
39
+ mapper.createMapping("session-1", "agent-head");
40
+ mapper.mount("session-1", "agent-child");
41
+
42
+ const session = eventStore.getSession("session-1");
43
+ expect(session!.state).toBe("mounted");
44
+ expect(session!.current_agent_id).toBe("agent-child");
45
+ expect(session!.head_manager_id).toBe("agent-head");
46
+ });
47
+
48
+ it("should emit session unmounted event on unmount", () => {
49
+ mapper.createMapping("session-1", "agent-head");
50
+ mapper.mount("session-1", "agent-child");
51
+ mapper.unmount("session-1");
52
+
53
+ const session = eventStore.getSession("session-1");
54
+ expect(session!.state).toBe("active");
55
+ expect(session!.current_agent_id).toBe("agent-head");
56
+ });
57
+
58
+ it("should emit unmounted when mounting back to head manager", () => {
59
+ mapper.createMapping("session-1", "agent-head");
60
+ mapper.mount("session-1", "agent-child");
61
+ mapper.mount("session-1", "agent-head");
62
+
63
+ const session = eventStore.getSession("session-1");
64
+ expect(session!.state).toBe("active");
65
+ expect(session!.current_agent_id).toBe("agent-head");
66
+ });
67
+
68
+ it("should emit session closed event on removeMapping", () => {
69
+ mapper.createMapping("session-1", "agent-head");
70
+ mapper.removeMapping("session-1");
71
+
72
+ const session = eventStore.getSession("session-1");
73
+ expect(session!.state).toBe("closed");
74
+ expect(session!.closed_at).toBeGreaterThan(0);
75
+ });
76
+
77
+ it("should not emit close for non-existent session", () => {
78
+ mapper.removeMapping("non-existent");
79
+
80
+ const session = eventStore.getSession("non-existent");
81
+ expect(session).toBeNull();
82
+ });
83
+
84
+ it("should track multiple sessions independently", () => {
85
+ mapper.createMapping("session-1", "agent-1");
86
+ mapper.createMapping("session-2", "agent-2");
87
+ mapper.mount("session-1", "agent-child");
88
+
89
+ const s1 = eventStore.getSession("session-1");
90
+ const s2 = eventStore.getSession("session-2");
91
+
92
+ expect(s1!.state).toBe("mounted");
93
+ expect(s2!.state).toBe("active");
94
+ });
95
+ });
96
+
97
+ describe("listSessions", () => {
98
+ it("should list sessions by state", () => {
99
+ mapper.createMapping("session-1", "agent-1");
100
+ mapper.createMapping("session-2", "agent-2");
101
+ mapper.mount("session-1", "agent-child");
102
+
103
+ const active = eventStore.listSessions({ state: "active" });
104
+ const mounted = eventStore.listSessions({ state: "mounted" });
105
+
106
+ expect(active).toHaveLength(1);
107
+ expect(active[0].id).toBe("session-2");
108
+ expect(mounted).toHaveLength(1);
109
+ expect(mounted[0].id).toBe("session-1");
110
+ });
111
+
112
+ it("should list sessions by agent", () => {
113
+ mapper.createMapping("session-1", "agent-1");
114
+ mapper.createMapping("session-2", "agent-2");
115
+
116
+ const sessions = eventStore.listSessions({ agent_id: "agent-1" });
117
+ expect(sessions).toHaveLength(1);
118
+ expect(sessions[0].id).toBe("session-1");
119
+ });
120
+
121
+ it("should filter closed sessions", () => {
122
+ mapper.createMapping("session-1", "agent-1");
123
+ mapper.createMapping("session-2", "agent-2");
124
+ mapper.removeMapping("session-1");
125
+
126
+ const active = eventStore.listSessions({ state: "active" });
127
+ const closed = eventStore.listSessions({ state: "closed" });
128
+
129
+ expect(active).toHaveLength(1);
130
+ expect(active[0].id).toBe("session-2");
131
+ expect(closed).toHaveLength(1);
132
+ expect(closed[0].id).toBe("session-1");
133
+ });
134
+ });
135
+
136
+ describe("session events in event log", () => {
137
+ it("should persist session events that can be queried", () => {
138
+ mapper.createMapping("session-1", "agent-head");
139
+ mapper.mount("session-1", "agent-child");
140
+ mapper.unmount("session-1");
141
+ mapper.removeMapping("session-1");
142
+
143
+ const events = eventStore.query({ type: "session" });
144
+ expect(events).toHaveLength(4);
145
+ expect(events[0].payload.action).toBe("created");
146
+ expect(events[1].payload.action).toBe("mounted");
147
+ expect(events[2].payload.action).toBe("unmounted");
148
+ expect(events[3].payload.action).toBe("closed");
149
+ });
150
+ });
151
+ });
152
+
153
+ describe("Session Recovery", () => {
154
+ let eventStore: EventStore;
155
+
156
+ beforeEach(async () => {
157
+ eventStore = await createEventStore({ inMemory: true });
158
+ });
159
+
160
+ afterEach(async () => {
161
+ await eventStore.close();
162
+ });
163
+
164
+ it("should recover active sessions from EventStore", () => {
165
+ // Create sessions with original mapper
166
+ const original = new SessionMapper(eventStore);
167
+ original.createMapping("session-1", "agent-1");
168
+ original.createMapping("session-2", "agent-2");
169
+
170
+ // Create new mapper and recover
171
+ const recovered = new SessionMapper(eventStore);
172
+ const count = recovered.recoverFromStore();
173
+
174
+ expect(count).toBe(2);
175
+ expect(recovered.size).toBe(2);
176
+ expect(recovered.getAgentId("session-1")).toBe("agent-1");
177
+ expect(recovered.getAgentId("session-2")).toBe("agent-2");
178
+ });
179
+
180
+ it("should recover mounted sessions with correct state", () => {
181
+ const original = new SessionMapper(eventStore);
182
+ original.createMapping("session-1", "agent-head");
183
+ original.mount("session-1", "agent-child");
184
+
185
+ const recovered = new SessionMapper(eventStore);
186
+ const count = recovered.recoverFromStore();
187
+
188
+ expect(count).toBe(1);
189
+ expect(recovered.getAgentId("session-1")).toBe("agent-child");
190
+ expect(recovered.getHeadManagerId("session-1")).toBe("agent-head");
191
+ expect(recovered.isMounted("session-1")).toBe(true);
192
+ });
193
+
194
+ it("should not recover closed sessions", () => {
195
+ const original = new SessionMapper(eventStore);
196
+ original.createMapping("session-1", "agent-1");
197
+ original.createMapping("session-2", "agent-2");
198
+ original.removeMapping("session-1");
199
+
200
+ const recovered = new SessionMapper(eventStore);
201
+ const count = recovered.recoverFromStore();
202
+
203
+ expect(count).toBe(1);
204
+ expect(recovered.getAgentId("session-1")).toBeUndefined();
205
+ expect(recovered.getAgentId("session-2")).toBe("agent-2");
206
+ });
207
+
208
+ it("should recover after unmount returns to active state", () => {
209
+ const original = new SessionMapper(eventStore);
210
+ original.createMapping("session-1", "agent-head");
211
+ original.mount("session-1", "agent-child");
212
+ original.unmount("session-1");
213
+
214
+ const recovered = new SessionMapper(eventStore);
215
+ const count = recovered.recoverFromStore();
216
+
217
+ expect(count).toBe(1);
218
+ expect(recovered.getAgentId("session-1")).toBe("agent-head");
219
+ expect(recovered.isMounted("session-1")).toBe(false);
220
+ });
221
+
222
+ it("should reset isProcessing to false on recovery", () => {
223
+ const original = new SessionMapper(eventStore);
224
+ original.createMapping("session-1", "agent-1");
225
+ original.setProcessing("session-1", true);
226
+
227
+ const recovered = new SessionMapper(eventStore);
228
+ recovered.recoverFromStore();
229
+
230
+ const status = recovered.getSessionStatus("agent-1");
231
+ expect(status).toBeDefined();
232
+ expect(status!.isProcessing).toBe(false);
233
+ });
234
+
235
+ it("should return 0 when no EventStore is configured", () => {
236
+ const mapper = new SessionMapper();
237
+ const count = mapper.recoverFromStore();
238
+ expect(count).toBe(0);
239
+ });
240
+
241
+ it("should survive view rebuild", () => {
242
+ const original = new SessionMapper(eventStore);
243
+ original.createMapping("session-1", "agent-1");
244
+ original.createMapping("session-2", "agent-2");
245
+ original.mount("session-1", "agent-child");
246
+ original.removeMapping("session-2");
247
+
248
+ // Simulate reload (which rebuilds views from events)
249
+ // We don't need to call reload() since in-memory; just verify
250
+ // the view state matches after rebuilding
251
+ const session1 = eventStore.getSession("session-1");
252
+ const session2 = eventStore.getSession("session-2");
253
+
254
+ expect(session1!.state).toBe("mounted");
255
+ expect(session1!.current_agent_id).toBe("agent-child");
256
+ expect(session2!.state).toBe("closed");
257
+ });
258
+ });
259
+
260
+ describe("SessionMapper backward compatibility", () => {
261
+ it("should work without EventStore (original behavior)", () => {
262
+ const mapper = new SessionMapper();
263
+
264
+ const mapping = mapper.createMapping("session-1", "agent-head");
265
+ expect(mapping.agentId).toBe("agent-head");
266
+
267
+ mapper.mount("session-1", "agent-child");
268
+ expect(mapper.getAgentId("session-1")).toBe("agent-child");
269
+
270
+ mapper.unmount("session-1");
271
+ expect(mapper.getAgentId("session-1")).toBe("agent-head");
272
+
273
+ mapper.removeMapping("session-1");
274
+ expect(mapper.getMapping("session-1")).toBeUndefined();
275
+ });
276
+ });
@@ -61,6 +61,8 @@ import type {
61
61
  RespondToPermissionResponse,
62
62
  CancelPermissionRequest,
63
63
  CancelPermissionResponse,
64
+ ResumeAgentRequest,
65
+ ResumeAgentResponse,
64
66
  } from "./types.js";
65
67
  import { ACPError } from "./types.js";
66
68
  import type { PeerManager } from "../peer/peer-manager.js";
@@ -92,6 +94,7 @@ const SUPPORTED_EXTENSIONS: ACPExtensionMethod[] = [
92
94
  "_macro/checkCapability",
93
95
  "_macro/respondToPermission",
94
96
  "_macro/cancelPermission",
97
+ "_macro/resume",
95
98
  ];
96
99
 
97
100
  // ─────────────────────────────────────────────────────────────────
@@ -155,8 +158,16 @@ export class MacroAgent implements Agent {
155
158
  this.peerManager = config.peerManager;
156
159
  this.capabilityManager = config.capabilityManager;
157
160
  this.roleRegistry = config.roleRegistry ?? new DefaultRoleRegistry();
158
- this.sessionMapper = new SessionMapper();
161
+ this.sessionMapper = new SessionMapper(config.eventStore);
159
162
  this.defaultCwd = config.defaultCwd ?? process.cwd();
163
+
164
+ // Recover persisted sessions from the EventStore
165
+ const recovered = this.sessionMapper.recoverFromStore();
166
+ if (recovered > 0) {
167
+ console.log(
168
+ `[MacroAgent] Recovered ${recovered} session(s) from EventStore`
169
+ );
170
+ }
160
171
  }
161
172
 
162
173
  // ─────────────────────────────────────────────────────────────────
@@ -229,9 +240,25 @@ export class MacroAgent implements Agent {
229
240
  * Load an existing session from EventStore
230
241
  */
231
242
  async loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse> {
232
- const acpSessionId = params.sessionId;
243
+ let acpSessionId = params.sessionId;
233
244
  const cwd = params.cwd ?? this.defaultCwd;
234
245
 
246
+ // Extension: If _meta.agentId provided, look up session from agent record
247
+ // This allows resuming a stopped head manager by MAP agent ID
248
+ // when the TUI doesn't know the ACP session ID
249
+ const metaAgentId = (params as { _meta?: Record<string, unknown> })._meta
250
+ ?.agentId as string | undefined;
251
+ if (metaAgentId) {
252
+ const agent = this.eventStore.getAgent(metaAgentId as AgentId);
253
+ if (!agent) {
254
+ throw new Error(`Agent not found: ${metaAgentId}`);
255
+ }
256
+ acpSessionId = agent.session_id;
257
+ console.log(
258
+ `[MacroAgent] loadSession: Resolved agentId ${metaAgentId} to session ${acpSessionId}`
259
+ );
260
+ }
261
+
235
262
  // Try to find an existing head manager with this session ID
236
263
  const headManagers = this.agentManager.listHeadManagers();
237
264
  const existing = headManagers.find((hm) => hm.session_id === acpSessionId);
@@ -340,8 +367,8 @@ export class MacroAgent implements Agent {
340
367
  await this.connection.sessionUpdate({
341
368
  sessionId: acpSessionId,
342
369
  update: {
343
- type: "agent_message_chunk",
344
- textChunk: `Error: ${errorMessage}`,
370
+ sessionUpdate: "agent_message_chunk",
371
+ content: { type: "text", text: `Error: ${errorMessage}` },
345
372
  },
346
373
  });
347
374
 
@@ -481,6 +508,11 @@ export class MacroAgent implements Agent {
481
508
  params as unknown as CancelPermissionRequest
482
509
  ) as unknown as Record<string, unknown>;
483
510
 
511
+ case "_macro/resume":
512
+ return this.handleResumeAgent(
513
+ params as unknown as ResumeAgentRequest
514
+ ) as unknown as Record<string, unknown>;
515
+
484
516
  default:
485
517
  throw new ACPError(
486
518
  `Unknown extension method: ${method}`,
@@ -1089,6 +1121,42 @@ export class MacroAgent implements Agent {
1089
1121
  }
1090
1122
  }
1091
1123
 
1124
+ /**
1125
+ * Resume a stopped/failed agent
1126
+ */
1127
+ private async handleResumeAgent(
1128
+ params: ResumeAgentRequest
1129
+ ): Promise<ResumeAgentResponse> {
1130
+ const { agentId } = params;
1131
+
1132
+ if (!agentId) {
1133
+ throw new ACPError("agentId is required", "INVALID_EXTENSION");
1134
+ }
1135
+
1136
+ // Verify agent exists
1137
+ const agent = this.eventStore.getAgent(agentId);
1138
+ if (!agent) {
1139
+ throw new ACPError(`Agent not found: ${agentId}`, "AGENT_NOT_FOUND");
1140
+ }
1141
+
1142
+ // Only resume stopped/failed agents
1143
+ if (agent.state !== "stopped" && agent.state !== "failed") {
1144
+ throw new ACPError(
1145
+ `Agent ${agentId} is ${agent.state} — only stopped or failed agents can be resumed`,
1146
+ "INVALID_EXTENSION"
1147
+ );
1148
+ }
1149
+
1150
+ console.log(`[MacroAgent] Resuming agent ${agentId}`);
1151
+ const spawned = await this.agentManager.resume(agentId);
1152
+
1153
+ return {
1154
+ success: true,
1155
+ agentId: spawned.id,
1156
+ sessionId: spawned.session_id,
1157
+ };
1158
+ }
1159
+
1092
1160
  // ─────────────────────────────────────────────────────────────────
1093
1161
  // Helper Methods
1094
1162
  // ─────────────────────────────────────────────────────────────────
@@ -1221,10 +1289,14 @@ export class MacroAgent implements Agent {
1221
1289
  toolCall: {
1222
1290
  toolCallId: permReq.toolCall.toolCallId,
1223
1291
  title: permReq.toolCall.title,
1224
- status: permReq.toolCall.status,
1292
+ status: permReq.toolCall.status as "pending" | "in_progress" | "completed" | "failed" | undefined,
1225
1293
  rawInput: permReq.toolCall.rawInput,
1226
1294
  },
1227
- options: permReq.options,
1295
+ options: permReq.options as Array<{
1296
+ kind: "allow_once" | "allow_always" | "reject_once" | "reject_always";
1297
+ name: string;
1298
+ optionId: string;
1299
+ }>,
1228
1300
  });
1229
1301
 
1230
1302
  // Forward the response back to the sub-agent via agentManager
@@ -1280,7 +1352,7 @@ export class MacroAgent implements Agent {
1280
1352
  try {
1281
1353
  await this.connection.sessionUpdate({
1282
1354
  sessionId: acpSessionId,
1283
- update: sessionUpdate,
1355
+ update: sessionUpdate as Parameters<AgentSideConnection["sessionUpdate"]>[0]["update"],
1284
1356
  });
1285
1357
  } catch (err) {
1286
1358
  console.error(
@@ -6,9 +6,12 @@
6
6
  * - Default mapping to head manager on session creation
7
7
  * - Remapping via mount to control different agents
8
8
  * - Multiple concurrent sessions with independent mappings
9
+ * - Persistent session lifecycle events via EventStore
10
+ * - Recovery of session state from EventStore after restart
9
11
  */
10
12
 
11
13
  import type { AgentId } from "../store/types/index.js";
14
+ import type { EventStore } from "../store/event-store.js";
12
15
  import type { ACPSessionId, SessionMapping } from "./types.js";
13
16
  import { ACPError } from "./types.js";
14
17
 
@@ -16,6 +19,13 @@ export class SessionMapper {
16
19
  /** Map of ACP session ID to mapping info */
17
20
  private mappings: Map<ACPSessionId, SessionMapping> = new Map();
18
21
 
22
+ /** Optional EventStore for persisting session lifecycle events */
23
+ private eventStore: EventStore | null;
24
+
25
+ constructor(eventStore?: EventStore) {
26
+ this.eventStore = eventStore ?? null;
27
+ }
28
+
19
29
  /**
20
30
  * Register a new ACP session with its head manager
21
31
  *
@@ -40,6 +50,12 @@ export class SessionMapper {
40
50
  };
41
51
 
42
52
  this.mappings.set(acpSessionId, mapping);
53
+
54
+ // Persist session creation event
55
+ this.emitSessionEvent("created", acpSessionId, {
56
+ head_manager_id: headManagerId,
57
+ });
58
+
43
59
  return mapping;
44
60
  }
45
61
 
@@ -123,6 +139,19 @@ export class SessionMapper {
123
139
  mapping.isMounted = agentId !== mapping.headManagerId;
124
140
  mapping.updatedAt = Date.now();
125
141
 
142
+ // Persist mount event
143
+ if (mapping.isMounted) {
144
+ this.emitSessionEvent("mounted", acpSessionId, {
145
+ target_agent_id: agentId,
146
+ previous_agent_id: previousAgentId,
147
+ });
148
+ } else {
149
+ // Mounting back to head manager is effectively an unmount
150
+ this.emitSessionEvent("unmounted", acpSessionId, {
151
+ previous_agent_id: previousAgentId,
152
+ });
153
+ }
154
+
126
155
  return previousAgentId;
127
156
  }
128
157
 
@@ -141,6 +170,11 @@ export class SessionMapper {
141
170
  mapping.isMounted = false;
142
171
  mapping.updatedAt = Date.now();
143
172
 
173
+ // Persist unmount event
174
+ this.emitSessionEvent("unmounted", acpSessionId, {
175
+ previous_agent_id: previousAgentId,
176
+ });
177
+
144
178
  return previousAgentId;
145
179
  }
146
180
 
@@ -155,12 +189,17 @@ export class SessionMapper {
155
189
  }
156
190
 
157
191
  /**
158
- * Remove a session mapping
192
+ * Remove a session mapping and emit a close event
159
193
  *
160
194
  * @param acpSessionId - The ACP session ID
161
195
  * @returns True if removed, false if not found
162
196
  */
163
197
  removeMapping(acpSessionId: ACPSessionId): boolean {
198
+ const existed = this.mappings.has(acpSessionId);
199
+ if (existed) {
200
+ // Persist close event before removing
201
+ this.emitSessionEvent("closed", acpSessionId, {});
202
+ }
164
203
  return this.mappings.delete(acpSessionId);
165
204
  }
166
205
 
@@ -226,6 +265,43 @@ export class SessionMapper {
226
265
  return undefined;
227
266
  }
228
267
 
268
+ /**
269
+ * Recover session mappings from the EventStore.
270
+ *
271
+ * Loads all non-closed sessions and rebuilds the in-memory mapping state.
272
+ * Called during initialization to restore sessions after a restart.
273
+ *
274
+ * @returns Number of sessions recovered
275
+ */
276
+ recoverFromStore(): number {
277
+ if (!this.eventStore || typeof this.eventStore.listSessions !== "function") {
278
+ return 0;
279
+ }
280
+
281
+ const activeSessions = this.eventStore.listSessions({ state: "active" });
282
+ const mountedSessions = this.eventStore.listSessions({ state: "mounted" });
283
+ const allSessions = [...activeSessions, ...mountedSessions];
284
+
285
+ let recovered = 0;
286
+ for (const session of allSessions) {
287
+ const now = Date.now();
288
+ const mapping: SessionMapping = {
289
+ acpSessionId: session.id,
290
+ agentId: session.current_agent_id,
291
+ headManagerId: session.head_manager_id,
292
+ isMounted: session.state === "mounted",
293
+ createdAt: session.created_at,
294
+ updatedAt: now,
295
+ isProcessing: false,
296
+ lastProcessingChangeAt: now,
297
+ };
298
+ this.mappings.set(session.id, mapping);
299
+ recovered++;
300
+ }
301
+
302
+ return recovered;
303
+ }
304
+
229
305
  /**
230
306
  * Get the number of active session mappings
231
307
  */
@@ -239,4 +315,35 @@ export class SessionMapper {
239
315
  clear(): void {
240
316
  this.mappings.clear();
241
317
  }
318
+
319
+ /**
320
+ * Emit a session lifecycle event to the EventStore
321
+ */
322
+ private emitSessionEvent(
323
+ action: string,
324
+ sessionId: ACPSessionId,
325
+ details: Record<string, unknown>
326
+ ): void {
327
+ if (!this.eventStore || typeof this.eventStore.emit !== "function") {
328
+ return;
329
+ }
330
+
331
+ try {
332
+ this.eventStore.emit({
333
+ type: "session",
334
+ source: {},
335
+ payload: {
336
+ action,
337
+ session_id: sessionId,
338
+ ...details,
339
+ },
340
+ });
341
+ } catch (error) {
342
+ // Log but don't fail — session events are supplementary
343
+ console.warn(
344
+ `[SessionMapper] Failed to emit session ${action} event:`,
345
+ error instanceof Error ? error.message : String(error)
346
+ );
347
+ }
348
+ }
242
349
  }
package/src/acp/types.ts CHANGED
@@ -605,6 +605,35 @@ export interface CancelPermissionResponse {
605
605
  error?: string;
606
606
  }
607
607
 
608
+ // ─────────────────────────────────────────────────────────────────
609
+ // ACP Extension: _macro/resume
610
+ // ─────────────────────────────────────────────────────────────────
611
+
612
+ /**
613
+ * Request for _macro/resume extension
614
+ *
615
+ * Resumes a stopped/failed agent by spawning a new process and
616
+ * loading the existing session. Called on the head manager's ACP stream.
617
+ */
618
+ export interface ResumeAgentRequest {
619
+ /** Agent ID to resume */
620
+ agentId: AgentId;
621
+ }
622
+
623
+ /**
624
+ * Response for _macro/resume extension
625
+ */
626
+ export interface ResumeAgentResponse {
627
+ /** Whether the resume was successful */
628
+ success: boolean;
629
+
630
+ /** The resumed agent's ID */
631
+ agentId: AgentId;
632
+
633
+ /** The agent's session ID */
634
+ sessionId: string;
635
+ }
636
+
608
637
  // ─────────────────────────────────────────────────────────────────
609
638
  // Extension Method Types (Union)
610
639
  // ─────────────────────────────────────────────────────────────────
@@ -627,7 +656,8 @@ export type ACPExtensionMethod =
627
656
  | "_macro/getCapabilities"
628
657
  | "_macro/checkCapability"
629
658
  | "_macro/respondToPermission"
630
- | "_macro/cancelPermission";
659
+ | "_macro/cancelPermission"
660
+ | "_macro/resume";
631
661
 
632
662
  /**
633
663
  * Map of extension methods to their request types
@@ -648,6 +678,7 @@ export interface ACPExtensionRequests {
648
678
  "_macro/checkCapability": CheckCapabilityRequest;
649
679
  "_macro/respondToPermission": RespondToPermissionRequest;
650
680
  "_macro/cancelPermission": CancelPermissionRequest;
681
+ "_macro/resume": ResumeAgentRequest;
651
682
  }
652
683
 
653
684
  /**
@@ -669,6 +700,7 @@ export interface ACPExtensionResponses {
669
700
  "_macro/checkCapability": CheckCapabilityResponse;
670
701
  "_macro/respondToPermission": RespondToPermissionResponse;
671
702
  "_macro/cancelPermission": CancelPermissionResponse;
703
+ "_macro/resume": ResumeAgentResponse;
672
704
  }
673
705
 
674
706
  // ─────────────────────────────────────────────────────────────────