macro-agent 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/.sudocode/specs.jsonl +4 -0
  3. package/CLAUDE.md +16 -14
  4. package/README.md +11 -29
  5. package/dist/acp/macro-agent.d.ts +15 -0
  6. package/dist/acp/macro-agent.d.ts.map +1 -1
  7. package/dist/acp/macro-agent.js +131 -35
  8. package/dist/acp/macro-agent.js.map +1 -1
  9. package/dist/acp/types.d.ts +32 -1
  10. package/dist/acp/types.d.ts.map +1 -1
  11. package/dist/acp/types.js.map +1 -1
  12. package/dist/agent/agent-manager.d.ts +65 -1
  13. package/dist/agent/agent-manager.d.ts.map +1 -1
  14. package/dist/agent/agent-manager.js +464 -183
  15. package/dist/agent/agent-manager.js.map +1 -1
  16. package/dist/agent/types.d.ts +1 -1
  17. package/dist/agent/types.d.ts.map +1 -1
  18. package/dist/api/server.d.ts +3 -0
  19. package/dist/api/server.d.ts.map +1 -1
  20. package/dist/api/server.js +37 -6
  21. package/dist/api/server.js.map +1 -1
  22. package/dist/auth/index.d.ts +2 -0
  23. package/dist/auth/index.d.ts.map +1 -0
  24. package/dist/auth/index.js +2 -0
  25. package/dist/auth/index.js.map +1 -0
  26. package/dist/auth/token.d.ts +41 -0
  27. package/dist/auth/token.d.ts.map +1 -0
  28. package/dist/auth/token.js +73 -0
  29. package/dist/auth/token.js.map +1 -0
  30. package/dist/cli/acp.d.ts +2 -23
  31. package/dist/cli/acp.d.ts.map +1 -1
  32. package/dist/cli/acp.js +127 -61
  33. package/dist/cli/acp.js.map +1 -1
  34. package/dist/cli/index.js +147 -15
  35. package/dist/cli/index.js.map +1 -1
  36. package/dist/cli/mcp.d.ts +6 -0
  37. package/dist/cli/mcp.d.ts.map +1 -1
  38. package/dist/cli/mcp.js +268 -181
  39. package/dist/cli/mcp.js.map +1 -1
  40. package/dist/cli/parse-args.d.ts +20 -0
  41. package/dist/cli/parse-args.d.ts.map +1 -0
  42. package/dist/cli/parse-args.js +43 -0
  43. package/dist/cli/parse-args.js.map +1 -0
  44. package/dist/cli/stable-instance-id.d.ts +8 -0
  45. package/dist/cli/stable-instance-id.d.ts.map +1 -0
  46. package/dist/cli/stable-instance-id.js +14 -0
  47. package/dist/cli/stable-instance-id.js.map +1 -0
  48. package/dist/config/project-config.d.ts +74 -7
  49. package/dist/config/project-config.d.ts.map +1 -1
  50. package/dist/config/project-config.js +123 -20
  51. package/dist/config/project-config.js.map +1 -1
  52. package/dist/map/adapter/acp-over-map.d.ts +17 -0
  53. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  54. package/dist/map/adapter/acp-over-map.js +384 -23
  55. package/dist/map/adapter/acp-over-map.js.map +1 -1
  56. package/dist/map/adapter/connection-manager.d.ts.map +1 -1
  57. package/dist/map/adapter/connection-manager.js +3 -0
  58. package/dist/map/adapter/connection-manager.js.map +1 -1
  59. package/dist/map/adapter/event-log.d.ts +87 -0
  60. package/dist/map/adapter/event-log.d.ts.map +1 -0
  61. package/dist/map/adapter/event-log.js +122 -0
  62. package/dist/map/adapter/event-log.js.map +1 -0
  63. package/dist/map/adapter/event-translator.js +6 -6
  64. package/dist/map/adapter/event-translator.js.map +1 -1
  65. package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
  66. package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
  67. package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
  68. package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
  69. package/dist/map/adapter/extensions/index.d.ts +10 -1
  70. package/dist/map/adapter/extensions/index.d.ts.map +1 -1
  71. package/dist/map/adapter/extensions/index.js +34 -0
  72. package/dist/map/adapter/extensions/index.js.map +1 -1
  73. package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
  74. package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
  75. package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
  76. package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
  77. package/dist/map/adapter/extensions/rename.d.ts +29 -0
  78. package/dist/map/adapter/extensions/rename.d.ts.map +1 -0
  79. package/dist/map/adapter/extensions/rename.js +49 -0
  80. package/dist/map/adapter/extensions/rename.js.map +1 -0
  81. package/dist/map/adapter/extensions/task.d.ts.map +1 -1
  82. package/dist/map/adapter/extensions/task.js +10 -0
  83. package/dist/map/adapter/extensions/task.js.map +1 -1
  84. package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
  85. package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
  86. package/dist/map/adapter/extensions/update-metadata.js +67 -0
  87. package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
  88. package/dist/map/adapter/index.d.ts +2 -1
  89. package/dist/map/adapter/index.d.ts.map +1 -1
  90. package/dist/map/adapter/index.js +8 -2
  91. package/dist/map/adapter/index.js.map +1 -1
  92. package/dist/map/adapter/interface.d.ts +2 -0
  93. package/dist/map/adapter/interface.d.ts.map +1 -1
  94. package/dist/map/adapter/map-adapter.d.ts +3 -0
  95. package/dist/map/adapter/map-adapter.d.ts.map +1 -1
  96. package/dist/map/adapter/map-adapter.js +258 -35
  97. package/dist/map/adapter/map-adapter.js.map +1 -1
  98. package/dist/map/adapter/subscription-manager.d.ts.map +1 -1
  99. package/dist/map/adapter/subscription-manager.js +5 -1
  100. package/dist/map/adapter/subscription-manager.js.map +1 -1
  101. package/dist/map/adapter/types.d.ts +2 -0
  102. package/dist/map/adapter/types.d.ts.map +1 -1
  103. package/dist/mcp/map-client.d.ts +39 -0
  104. package/dist/mcp/map-client.d.ts.map +1 -0
  105. package/dist/mcp/map-client.js +129 -0
  106. package/dist/mcp/map-client.js.map +1 -0
  107. package/dist/mcp/mcp-server.d.ts +14 -0
  108. package/dist/mcp/mcp-server.d.ts.map +1 -1
  109. package/dist/mcp/mcp-server.js +113 -85
  110. package/dist/mcp/mcp-server.js.map +1 -1
  111. package/dist/mcp/types.d.ts +9 -1
  112. package/dist/mcp/types.d.ts.map +1 -1
  113. package/dist/mcp/types.js.map +1 -1
  114. package/dist/metrics/metrics.js +1 -1
  115. package/dist/metrics/metrics.js.map +1 -1
  116. package/dist/roles/capabilities.d.ts +3 -1
  117. package/dist/roles/capabilities.d.ts.map +1 -1
  118. package/dist/roles/capabilities.js +17 -7
  119. package/dist/roles/capabilities.js.map +1 -1
  120. package/dist/roles/config-loader.d.ts +6 -6
  121. package/dist/roles/config-loader.d.ts.map +1 -1
  122. package/dist/roles/config-loader.js +6 -6
  123. package/dist/roles/config-loader.js.map +1 -1
  124. package/dist/roles/registry.d.ts +2 -2
  125. package/dist/roles/registry.js +2 -2
  126. package/dist/server/combined-server.d.ts +20 -0
  127. package/dist/server/combined-server.d.ts.map +1 -1
  128. package/dist/server/combined-server.js +107 -8
  129. package/dist/server/combined-server.js.map +1 -1
  130. package/dist/store/event-store.d.ts +2 -1
  131. package/dist/store/event-store.d.ts.map +1 -1
  132. package/dist/store/event-store.js +69 -20
  133. package/dist/store/event-store.js.map +1 -1
  134. package/dist/store/types/agents.d.ts +18 -0
  135. package/dist/store/types/agents.d.ts.map +1 -1
  136. package/dist/store/types/events.d.ts +1 -1
  137. package/dist/store/types/events.d.ts.map +1 -1
  138. package/dist/task/backend/index.d.ts +47 -29
  139. package/dist/task/backend/index.d.ts.map +1 -1
  140. package/dist/task/backend/index.js +109 -71
  141. package/dist/task/backend/index.js.map +1 -1
  142. package/dist/task/backend/memory.d.ts +1 -0
  143. package/dist/task/backend/memory.d.ts.map +1 -1
  144. package/dist/task/backend/memory.js +3 -0
  145. package/dist/task/backend/memory.js.map +1 -1
  146. package/dist/task/backend/opentasks/backend.d.ts +140 -0
  147. package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
  148. package/dist/task/backend/opentasks/backend.js +1023 -0
  149. package/dist/task/backend/opentasks/backend.js.map +1 -0
  150. package/dist/task/backend/opentasks/client.d.ts +337 -0
  151. package/dist/task/backend/opentasks/client.d.ts.map +1 -0
  152. package/dist/task/backend/opentasks/client.js +225 -0
  153. package/dist/task/backend/opentasks/client.js.map +1 -0
  154. package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
  155. package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
  156. package/dist/task/backend/opentasks/daemon-manager.js +195 -0
  157. package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
  158. package/dist/task/backend/opentasks/index.d.ts +21 -0
  159. package/dist/task/backend/opentasks/index.d.ts.map +1 -0
  160. package/dist/task/backend/opentasks/index.js +21 -0
  161. package/dist/task/backend/opentasks/index.js.map +1 -0
  162. package/dist/task/backend/opentasks/mapping.d.ts +48 -0
  163. package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
  164. package/dist/task/backend/opentasks/mapping.js +77 -0
  165. package/dist/task/backend/opentasks/mapping.js.map +1 -0
  166. package/dist/task/backend/types.d.ts +33 -53
  167. package/dist/task/backend/types.d.ts.map +1 -1
  168. package/dist/task/backend/types.js +7 -11
  169. package/dist/task/backend/types.js.map +1 -1
  170. package/dist/task/backend/unified-tool-provider.d.ts +57 -0
  171. package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
  172. package/dist/task/backend/unified-tool-provider.js +623 -0
  173. package/dist/task/backend/unified-tool-provider.js.map +1 -0
  174. package/dist/teams/team-loader.d.ts +2 -2
  175. package/dist/teams/team-loader.js +3 -3
  176. package/dist/teams/team-loader.js.map +1 -1
  177. package/dist/teams/team-runtime.d.ts.map +1 -1
  178. package/dist/teams/team-runtime.js +2 -0
  179. package/dist/teams/team-runtime.js.map +1 -1
  180. package/docs/architecture.md +7 -6
  181. package/docs/configuration.md +26 -62
  182. package/docs/implementation-details.md +5 -5
  183. package/docs/implementation-summary.md +17 -17
  184. package/docs/plan-self-driving-support.md +4 -4
  185. package/docs/spec-self-driving-support.md +10 -10
  186. package/docs/team-templates.md +2 -2
  187. package/docs/teams.md +3 -3
  188. package/docs/troubleshooting.md +10 -11
  189. package/package.json +6 -4
  190. package/src/__tests__/e2e/agent-spawn-visibility.e2e.test.ts +761 -0
  191. package/src/__tests__/e2e/full-agent-conflict-resolution.e2e.test.ts +2 -2
  192. package/src/__tests__/e2e/mcp-thin-client-bridge.e2e.test.ts +304 -0
  193. package/src/__tests__/e2e/mcp-tools-available.e2e.test.ts +324 -0
  194. package/src/__tests__/e2e/multi-agent.e2e.test.ts +5 -5
  195. package/src/__tests__/e2e/spawn-session-streaming.e2e.test.ts +563 -0
  196. package/src/acp/__tests__/integration.test.ts +56 -31
  197. package/src/acp/__tests__/macro-agent.test.ts +16 -7
  198. package/src/acp/macro-agent.ts +170 -36
  199. package/src/acp/types.ts +46 -1
  200. package/src/agent/__tests__/agent-manager.test.ts +228 -2
  201. package/src/agent/agent-manager.ts +714 -261
  202. package/src/agent/types.ts +3 -1
  203. package/src/api/server.ts +41 -7
  204. package/src/auth/__tests__/token.test.ts +100 -0
  205. package/src/auth/index.ts +1 -0
  206. package/src/auth/token.ts +82 -0
  207. package/src/cli/__tests__/acp.test.ts +1 -1
  208. package/src/cli/__tests__/stable-instance-id.test.ts +1 -1
  209. package/src/cli/acp.ts +130 -72
  210. package/src/cli/index.ts +120 -14
  211. package/src/cli/mcp.ts +311 -207
  212. package/src/cli/parse-args.ts +54 -0
  213. package/src/cli/stable-instance-id.ts +14 -0
  214. package/src/config/project-config.ts +190 -27
  215. package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
  216. package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +22 -4
  217. package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
  218. package/src/map/adapter/__tests__/acp-over-map-history.test.ts +263 -0
  219. package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +1 -1
  220. package/src/map/adapter/__tests__/event-broadcast.test.ts +420 -0
  221. package/src/map/adapter/__tests__/event-log.test.ts +527 -0
  222. package/src/map/adapter/__tests__/event-translator.test.ts +3 -3
  223. package/src/map/adapter/__tests__/extensions.test.ts +408 -0
  224. package/src/map/adapter/__tests__/map-adapter.test.ts +99 -0
  225. package/src/map/adapter/__tests__/mcp-bridge.test.ts +1187 -0
  226. package/src/map/adapter/__tests__/multi-client-broadcast.test.ts +711 -0
  227. package/src/map/adapter/__tests__/websocket-integration.test.ts +218 -0
  228. package/src/map/adapter/acp-over-map.ts +678 -66
  229. package/src/map/adapter/connection-manager.ts +3 -0
  230. package/src/map/adapter/event-log.ts +208 -0
  231. package/src/map/adapter/event-translator.ts +6 -6
  232. package/src/map/adapter/extensions/agent-lifecycle.ts +267 -0
  233. package/src/map/adapter/extensions/index.ts +60 -0
  234. package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
  235. package/src/map/adapter/extensions/task.ts +11 -0
  236. package/src/map/adapter/extensions/update-metadata.ts +126 -0
  237. package/src/map/adapter/index.ts +28 -0
  238. package/src/map/adapter/interface.ts +2 -0
  239. package/src/map/adapter/map-adapter.ts +312 -47
  240. package/src/map/adapter/subscription-manager.ts +5 -1
  241. package/src/map/adapter/types.ts +2 -0
  242. package/src/mcp/__tests__/map-client.test.ts +386 -0
  243. package/src/mcp/__tests__/mcp-server-thin-client.test.ts +368 -0
  244. package/src/mcp/__tests__/mcp-server.test.ts +100 -1
  245. package/src/mcp/map-client.ts +177 -0
  246. package/src/mcp/mcp-server.ts +191 -100
  247. package/src/mcp/types.ts +6 -1
  248. package/src/metrics/metrics.ts +1 -1
  249. package/src/monitor/__tests__/stale-agent-flow.integration.test.ts +1 -1
  250. package/src/roles/__tests__/config-loader.test.ts +7 -7
  251. package/src/roles/capabilities.ts +17 -7
  252. package/src/roles/config-loader.ts +6 -6
  253. package/src/roles/registry.ts +2 -2
  254. package/src/server/__tests__/combined-server.test.ts +94 -21
  255. package/src/server/combined-server.ts +189 -33
  256. package/src/steering/__tests__/steering-integration.test.ts +1 -1
  257. package/src/store/__tests__/event-store.test.ts +196 -1
  258. package/src/store/__tests__/instance.test.ts +3 -3
  259. package/src/store/event-store.ts +80 -21
  260. package/src/store/types/agents.ts +15 -0
  261. package/src/store/types/events.ts +1 -1
  262. package/src/task/backend/__tests__/create-task-backend.test.ts +225 -0
  263. package/src/task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test.ts +524 -0
  264. package/src/task/backend/__tests__/unified-tool-provider.test.ts +579 -0
  265. package/src/task/backend/index.ts +156 -106
  266. package/src/task/backend/memory.ts +4 -0
  267. package/src/task/backend/opentasks/__tests__/backend.test.ts +968 -0
  268. package/src/task/backend/opentasks/__tests__/daemon-manager.test.ts +406 -0
  269. package/src/task/backend/opentasks/__tests__/mapping.test.ts +84 -0
  270. package/src/task/backend/opentasks/__tests__/opentasks-backend.e2e.test.ts +1338 -0
  271. package/src/task/backend/opentasks/backend.ts +1323 -0
  272. package/src/task/backend/opentasks/client.ts +652 -0
  273. package/src/task/backend/opentasks/daemon-manager.ts +253 -0
  274. package/src/task/backend/opentasks/index.ts +69 -0
  275. package/src/task/backend/opentasks/mapping.ts +94 -0
  276. package/src/task/backend/types.ts +42 -66
  277. package/src/task/backend/unified-tool-provider.ts +779 -0
  278. package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
  279. package/src/teams/team-loader.ts +3 -3
  280. package/src/teams/team-runtime.ts +2 -0
  281. package/test_fixtures/README.md +2 -3
  282. package/test_fixtures/fixtures/index.ts +0 -3
  283. package/test_fixtures/fixtures/projects/project-with-specs.ts +7 -149
  284. package/test_fixtures/fixtures/repos/index.ts +1 -3
  285. package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -116
  286. package/test_fixtures/fixtures/repos/types.ts +0 -11
  287. package/test_fixtures/harness/__tests__/fixtures.test.ts +10 -102
  288. package/test_fixtures/harness/__tests__/temp-repo-and-simulator.test.ts +0 -33
  289. package/test_fixtures/harness/simulator/agent-simulator.ts +4 -4
  290. package/vitest.config.ts +1 -1
  291. package/vitest.e2e.config.ts +1 -1
  292. package/vitest.setup.ts +1 -30
  293. package/.macro-agent/teams/self-driving/prompts/grinder.md +0 -27
  294. package/.macro-agent/teams/self-driving/prompts/judge.md +0 -27
  295. package/.macro-agent/teams/self-driving/prompts/planner.md +0 -33
  296. package/.macro-agent/teams/self-driving/roles/grinder.yaml +0 -17
  297. package/.macro-agent/teams/self-driving/roles/judge.yaml +0 -24
  298. package/.macro-agent/teams/self-driving/roles/planner.yaml +0 -18
  299. package/.macro-agent/teams/self-driving/team.yaml +0 -103
  300. package/.macro-agent/teams/structured/prompts/developer.md +0 -26
  301. package/.macro-agent/teams/structured/prompts/lead.md +0 -25
  302. package/.macro-agent/teams/structured/prompts/reviewer.md +0 -24
  303. package/.macro-agent/teams/structured/roles/developer.yaml +0 -12
  304. package/.macro-agent/teams/structured/roles/lead.yaml +0 -11
  305. package/.macro-agent/teams/structured/roles/reviewer.yaml +0 -19
  306. package/.macro-agent/teams/structured/team.yaml +0 -89
  307. package/docs/sudocode-integration.md +0 -383
  308. package/src/task/backend/__tests__/backend-parity.test.ts +0 -451
  309. package/src/task/backend/__tests__/tool-provider-edge-cases.test.ts +0 -430
  310. package/src/task/backend/__tests__/tool-provider.test.ts +0 -983
  311. package/src/task/backend/sudocode/__tests__/backend-edge-cases.test.ts +0 -575
  312. package/src/task/backend/sudocode/__tests__/backend.test.ts +0 -1194
  313. package/src/task/backend/sudocode/__tests__/client-integration.test.ts +0 -418
  314. package/src/task/backend/sudocode/__tests__/client.test.ts +0 -345
  315. package/src/task/backend/sudocode/__tests__/e2e/backend.e2e.test.ts +0 -753
  316. package/src/task/backend/sudocode/__tests__/e2e/server-client.e2e.test.ts +0 -680
  317. package/src/task/backend/sudocode/__tests__/e2e-workflow.test.ts +0 -666
  318. package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts +0 -396
  319. package/src/task/backend/sudocode/__tests__/integration/sudocode-cli.integration.test.ts +0 -328
  320. package/src/task/backend/sudocode/__tests__/integration/test-utils.ts +0 -175
  321. package/src/task/backend/sudocode/__tests__/mapping-edge-cases.test.ts +0 -265
  322. package/src/task/backend/sudocode/__tests__/server-client.test.ts +0 -675
  323. package/src/task/backend/sudocode/__tests__/sync-policy-edge-cases.test.ts +0 -521
  324. package/src/task/backend/sudocode/__tests__/sync-policy.test.ts +0 -519
  325. package/src/task/backend/sudocode/__tests__/tools.test.ts +0 -471
  326. package/src/task/backend/sudocode/backend.ts +0 -1237
  327. package/src/task/backend/sudocode/client.ts +0 -515
  328. package/src/task/backend/sudocode/index.ts +0 -120
  329. package/src/task/backend/sudocode/mapping.ts +0 -93
  330. package/src/task/backend/sudocode/server-client.ts +0 -522
  331. package/src/task/backend/sudocode/standalone-client.ts +0 -623
  332. package/src/task/backend/sudocode/sync-policy.ts +0 -387
  333. package/src/task/backend/sudocode/tools.ts +0 -896
  334. package/src/task/backend/tool-provider.ts +0 -506
  335. package/test_fixtures/fixtures/sudocode/index.ts +0 -29
  336. package/test_fixtures/fixtures/sudocode/issues.ts +0 -185
  337. package/test_fixtures/fixtures/sudocode/specs.ts +0 -159
@@ -80,6 +80,7 @@ const DEFAULT_ANONYMOUS_CAPABILITIES: ParticipantCapabilities = {
80
80
  canManageScopes: false,
81
81
  canUpdatePermissions: false,
82
82
  canManageTasks: false,
83
+ canManageLifecycle: false,
83
84
  };
84
85
 
85
86
  /**
@@ -95,6 +96,7 @@ const DEFAULT_CLIENT_CAPABILITIES: ParticipantCapabilities = {
95
96
  canUpdatePermissions: false,
96
97
  canManageTasks: false,
97
98
  canManageFederation: false,
99
+ canManageLifecycle: false,
98
100
  };
99
101
 
100
102
  /**
@@ -110,6 +112,7 @@ const DEFAULT_AGENT_CAPABILITIES: ParticipantCapabilities = {
110
112
  canUpdatePermissions: false,
111
113
  canManageTasks: true,
112
114
  canManageFederation: true,
115
+ canManageLifecycle: true,
113
116
  };
114
117
 
115
118
  // =============================================================================
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Event Log - In-memory ring buffer for MAP event replay
3
+ *
4
+ * Stores emitted MAP events for replay by newly connected clients.
5
+ * Events are stored in chronological order with ULID-based event IDs
6
+ * for keyset pagination.
7
+ *
8
+ * Event type normalization:
9
+ * - Server emits dot format: "agent.registered", "message.sent"
10
+ * - SDK sends underscore format: "agent_registered", "message_sent"
11
+ * - ACP-over-MAP emits underscore format: "message_delivered"
12
+ * - Both formats are normalized to dot format for filter comparison
13
+ * - Response events are converted to underscore format for the SDK
14
+ */
15
+
16
+ // =============================================================================
17
+ // Types
18
+ // =============================================================================
19
+
20
+ /** Configuration for the event log */
21
+ export interface EventLogConfig {
22
+ /** Maximum number of events to retain. Default: 10000 */
23
+ maxSize?: number;
24
+ }
25
+
26
+ /** A logged event entry */
27
+ export interface LoggedEvent {
28
+ /** ULID event ID — stable, lexicographically sortable */
29
+ eventId: string;
30
+ /** Event timestamp (ms since epoch) */
31
+ timestamp: number;
32
+ /** Event type (dot or underscore format, as emitted) */
33
+ type: string;
34
+ /** Event-specific data payload */
35
+ data: unknown;
36
+ /** Parent event IDs for causal ordering */
37
+ causedBy?: string[];
38
+ /** Related agent ID (for filter matching) */
39
+ agentId?: string;
40
+ /** Related scope ID (for filter matching) */
41
+ scopeId?: string;
42
+ }
43
+
44
+ /** Filter for event log queries */
45
+ export interface EventLogFilter {
46
+ /** Event types (can be underscore or dot format — normalized during comparison) */
47
+ eventTypes?: string[];
48
+ /** Agent IDs (OR within array) */
49
+ agents?: string[];
50
+ /** Scope IDs (OR within array) */
51
+ scopes?: string[];
52
+ }
53
+
54
+ /** Query parameters for replay */
55
+ export interface EventLogQueryParams {
56
+ /** Keyset pagination cursor — start after this event ID */
57
+ afterEventId?: string;
58
+ /** Include events from this timestamp (inclusive) */
59
+ fromTimestamp?: number;
60
+ /** Include events up to this timestamp (inclusive) */
61
+ toTimestamp?: number;
62
+ /** Event filter */
63
+ filter?: EventLogFilter;
64
+ /** Maximum events to return (capped at 1000) */
65
+ limit?: number;
66
+ }
67
+
68
+ /** Result of an event log query */
69
+ export interface EventLogQueryResult {
70
+ /** Matching events in chronological order */
71
+ events: LoggedEvent[];
72
+ /** Whether more events exist beyond this page */
73
+ hasMore: boolean;
74
+ }
75
+
76
+ // =============================================================================
77
+ // Format Normalization
78
+ // =============================================================================
79
+
80
+ /** Convert underscore format to dot format: "agent_registered" → "agent.registered" */
81
+ export function underscoreToDot(type: string): string {
82
+ return type.replace(/_/g, ".");
83
+ }
84
+
85
+ /** Convert dot format to underscore format: "agent.registered" → "agent_registered" */
86
+ export function dotToUnderscore(type: string): string {
87
+ return type.replace(/\./g, "_");
88
+ }
89
+
90
+ // =============================================================================
91
+ // EventLog
92
+ // =============================================================================
93
+
94
+ const DEFAULT_MAX_SIZE = 10_000;
95
+ const MAX_QUERY_LIMIT = 1000;
96
+ const DEFAULT_QUERY_LIMIT = 100;
97
+
98
+ /**
99
+ * In-memory ring buffer for MAP event replay.
100
+ *
101
+ * Events are appended in emission order and oldest are evicted
102
+ * when the buffer exceeds maxSize.
103
+ */
104
+ export class EventLog {
105
+ private readonly buffer: LoggedEvent[] = [];
106
+ private readonly maxSize: number;
107
+
108
+ constructor(config: EventLogConfig = {}) {
109
+ this.maxSize = config.maxSize ?? DEFAULT_MAX_SIZE;
110
+ }
111
+
112
+ /** Append an event to the log. O(1) amortized. */
113
+ append(event: LoggedEvent): void {
114
+ this.buffer.push(event);
115
+
116
+ // Evict oldest events if over capacity
117
+ if (this.buffer.length > this.maxSize) {
118
+ const overflow = this.buffer.length - this.maxSize;
119
+ this.buffer.splice(0, overflow);
120
+ }
121
+ }
122
+
123
+ /** Query events with filter and pagination. */
124
+ query(params: EventLogQueryParams = {}): EventLogQueryResult {
125
+ const limit = Math.min(params.limit ?? DEFAULT_QUERY_LIMIT, MAX_QUERY_LIMIT);
126
+
127
+ // Normalize filter event types to dot format for comparison
128
+ const normalizedFilterTypes = params.filter?.eventTypes?.map(underscoreToDot);
129
+
130
+ let startIndex = 0;
131
+
132
+ // Handle afterEventId (keyset pagination)
133
+ if (params.afterEventId) {
134
+ const idx = this.buffer.findIndex(
135
+ (e) => e.eventId === params.afterEventId,
136
+ );
137
+ if (idx >= 0) {
138
+ startIndex = idx + 1;
139
+ }
140
+ // If not found (evicted), start from beginning
141
+ }
142
+
143
+ // Handle fromTimestamp (only if no afterEventId)
144
+ if (params.fromTimestamp != null && !params.afterEventId) {
145
+ const idx = this.buffer.findIndex(
146
+ (e) => e.timestamp >= params.fromTimestamp!,
147
+ );
148
+ if (idx >= 0) {
149
+ startIndex = idx;
150
+ } else {
151
+ // All events are before fromTimestamp
152
+ return { events: [], hasMore: false };
153
+ }
154
+ }
155
+
156
+ const results: LoggedEvent[] = [];
157
+
158
+ for (let i = startIndex; i < this.buffer.length && results.length < limit; i++) {
159
+ const event = this.buffer[i];
160
+
161
+ // Apply toTimestamp filter
162
+ if (params.toTimestamp != null && event.timestamp > params.toTimestamp) {
163
+ break;
164
+ }
165
+
166
+ // Apply event type filter (normalize stored type for comparison)
167
+ if (normalizedFilterTypes && normalizedFilterTypes.length > 0) {
168
+ const normalizedStoredType = underscoreToDot(event.type);
169
+ if (!normalizedFilterTypes.includes(normalizedStoredType)) {
170
+ continue;
171
+ }
172
+ }
173
+
174
+ // Apply agent filter (OR within array)
175
+ if (params.filter?.agents && params.filter.agents.length > 0) {
176
+ if (!event.agentId || !params.filter.agents.includes(event.agentId)) {
177
+ continue;
178
+ }
179
+ }
180
+
181
+ // Apply scope filter (OR within array)
182
+ if (params.filter?.scopes && params.filter.scopes.length > 0) {
183
+ if (!event.scopeId || !params.filter.scopes.includes(event.scopeId)) {
184
+ continue;
185
+ }
186
+ }
187
+
188
+ results.push(event);
189
+ }
190
+
191
+ // Determine hasMore: check if there are more matching events beyond our limit
192
+ let hasMore = false;
193
+ if (results.length === limit) {
194
+ // Check if there's at least one more event in the buffer after our results
195
+ const lastResultIndex = this.buffer.indexOf(results[results.length - 1]);
196
+ if (lastResultIndex >= 0 && lastResultIndex < this.buffer.length - 1) {
197
+ hasMore = true;
198
+ }
199
+ }
200
+
201
+ return { events: results, hasMore };
202
+ }
203
+
204
+ /** Number of events currently in the buffer. */
205
+ get size(): number {
206
+ return this.buffer.length;
207
+ }
208
+ }
@@ -47,7 +47,7 @@ export interface TranslationContext {
47
47
  */
48
48
  const EVENT_TYPE_MAP: Record<EventType, MAPEventType | MAPEventType[] | null> = {
49
49
  spawn: "agent.registered",
50
- terminate: "agent.unregistered",
50
+ stop: "agent.unregistered",
51
51
  status: "agent.state.changed",
52
52
  message: ["message.sent", "message.delivered"], // Two events for message
53
53
  task: null, // Handled specially based on payload
@@ -105,8 +105,8 @@ export function translateEvent(
105
105
  case "spawn":
106
106
  return translateSpawnEvent(event, generateEventId);
107
107
 
108
- case "terminate":
109
- return translateTerminateEvent(event, generateEventId);
108
+ case "stop":
109
+ return translateStopEvent(event, generateEventId);
110
110
 
111
111
  case "status":
112
112
  return translateStatusEvent(event, generateEventId);
@@ -157,15 +157,15 @@ function translateSpawnEvent(
157
157
  }
158
158
 
159
159
  /**
160
- * Translate terminate event to agent.unregistered.
160
+ * Translate stop event to agent.unregistered.
161
161
  */
162
- function translateTerminateEvent(
162
+ function translateStopEvent(
163
163
  event: Event,
164
164
  generateEventId: () => string
165
165
  ): TranslationResult {
166
166
  const agentId = event.source.agent_id;
167
167
  if (!agentId) {
168
- return { translated: false, reason: "Terminate event missing agent_id" };
168
+ return { translated: false, reason: "Stop event missing agent_id" };
169
169
  }
170
170
 
171
171
  const notification: EventNotification = {
@@ -0,0 +1,267 @@
1
+ /**
2
+ * Agent Lifecycle Extension Methods (_macro/spawnAgent, _macro/forkAgent, etc.)
3
+ *
4
+ * Exposes agent lifecycle management to external MAP clients via direct
5
+ * JSON-RPC extension calls, replacing the need for ACP-over-MAP streams.
6
+ *
7
+ * Methods:
8
+ * - _macro/spawnAgent - Spawn a child agent
9
+ * - _macro/forkAgent - Fork an agent's session
10
+ * - _macro/setPermissionMode - Change an agent's permission mode
11
+ * - _macro/respondToPermission - Respond to a pending permission request
12
+ */
13
+
14
+ import type { MAPAdapter, ExtensionHandler, ExtensionContext } from "../interface.js";
15
+ import type { AgentId } from "../../../store/types/index.js";
16
+ import { RPCError } from "../rpc-handler.js";
17
+
18
+ // =============================================================================
19
+ // Extension Services
20
+ // =============================================================================
21
+
22
+ /**
23
+ * Services required for agent lifecycle extensions
24
+ */
25
+ export interface AgentLifecycleExtensionServices {
26
+ /** Get agent by ID */
27
+ getAgent: (id: AgentId) => { id: AgentId; state: string; session_id?: string; cwd?: string | null } | null;
28
+
29
+ /** Spawn a child agent under a parent */
30
+ spawn: (opts: {
31
+ parent: AgentId;
32
+ task: string;
33
+ cwd?: string;
34
+ role?: string;
35
+ topics?: string[];
36
+ config?: Record<string, unknown>;
37
+ }) => Promise<{ id: AgentId; session_id: string }>;
38
+
39
+ /** Fork an agent's session */
40
+ forkAgent: (agentId: AgentId, opts: {
41
+ name?: string;
42
+ prompt?: string;
43
+ cwd?: string;
44
+ }) => Promise<{ id: AgentId; session_id: string; session?: { id: string } }>;
45
+
46
+ /** Send a prompt to an agent (for fire-and-forget initial prompt on fork) */
47
+ prompt: (agentId: AgentId, message: string) => AsyncIterable<unknown>;
48
+
49
+ /** Set the permission mode for an agent's session */
50
+ setPermissionMode: (agentId: AgentId, mode: string) => boolean;
51
+
52
+ /** Get the current permission mode for an agent */
53
+ getPermissionMode: (agentId: AgentId) => string | null;
54
+
55
+ /** Respond to a pending permission request */
56
+ respondToPermission: (agentId: AgentId, requestId: string, optionId: string) => boolean;
57
+
58
+ /** Callback to notify subscribers that a new agent was registered */
59
+ onAgentRegistered?: (agent: { id: string; name?: string; role?: string; parent?: string }) => void;
60
+
61
+ /** List head manager agents (fallback parent for spawn) */
62
+ listHeadManagers: () => Array<{ id: AgentId }>;
63
+
64
+ /** Default working directory */
65
+ defaultCwd?: string;
66
+ }
67
+
68
+ // =============================================================================
69
+ // Handler Implementations
70
+ // =============================================================================
71
+
72
+ function createSpawnHandler(services: AgentLifecycleExtensionServices): ExtensionHandler {
73
+ return async (_context: ExtensionContext, params: unknown) => {
74
+ const { task, cwd, topics, config, parentId } = (params ?? {}) as {
75
+ task: string;
76
+ cwd?: string;
77
+ topics?: string[];
78
+ config?: Record<string, unknown>;
79
+ parentId?: string;
80
+ };
81
+
82
+ if (!task) {
83
+ throw RPCError.invalidParams("task is required");
84
+ }
85
+
86
+ // Determine parent: explicit parentId, or fall back to head manager
87
+ let parent: AgentId | undefined;
88
+ if (parentId) {
89
+ parent = parentId as AgentId;
90
+ } else {
91
+ const headManagers = services.listHeadManagers();
92
+ if (headManagers.length > 0) {
93
+ parent = headManagers[0].id;
94
+ }
95
+ }
96
+
97
+ if (!parent) {
98
+ throw RPCError.invalidParams("No parent agent available for spawning");
99
+ }
100
+
101
+ const spawned = await services.spawn({
102
+ parent,
103
+ task,
104
+ cwd: cwd ?? services.defaultCwd,
105
+ role: "worker",
106
+ topics,
107
+ config,
108
+ });
109
+
110
+ // Notify subscribers that a new agent was registered
111
+ if (services.onAgentRegistered) {
112
+ const agent = services.getAgent(spawned.id);
113
+ services.onAgentRegistered({
114
+ id: spawned.id as string,
115
+ name: agent?.id as string,
116
+ role: "worker",
117
+ parent: parent as string,
118
+ });
119
+ }
120
+
121
+ return {
122
+ agentId: spawned.id,
123
+ sessionId: spawned.session_id,
124
+ };
125
+ };
126
+ }
127
+
128
+ function createForkHandler(services: AgentLifecycleExtensionServices): ExtensionHandler {
129
+ return async (_context: ExtensionContext, params: unknown) => {
130
+ const { agentId, name, prompt, cwd } = (params ?? {}) as {
131
+ agentId: string;
132
+ name?: string;
133
+ prompt?: string;
134
+ cwd?: string;
135
+ };
136
+
137
+ if (!agentId) {
138
+ throw RPCError.invalidParams("agentId is required");
139
+ }
140
+
141
+ const sourceAgent = services.getAgent(agentId as AgentId);
142
+ if (!sourceAgent) {
143
+ throw RPCError.notFound("agent", agentId);
144
+ }
145
+
146
+ const forked = await services.forkAgent(agentId as AgentId, {
147
+ name,
148
+ prompt,
149
+ cwd: cwd ?? sourceAgent.cwd ?? services.defaultCwd,
150
+ });
151
+
152
+ // Notify subscribers
153
+ if (services.onAgentRegistered) {
154
+ services.onAgentRegistered({
155
+ id: forked.id as string,
156
+ name,
157
+ parent: sourceAgent.id as string,
158
+ });
159
+ }
160
+
161
+ // Fire-and-forget initial prompt if provided
162
+ if (prompt && forked.id) {
163
+ (async () => {
164
+ try {
165
+ for await (const _chunk of services.prompt(forked.id, prompt)) {
166
+ // drain iterator
167
+ }
168
+ } catch {
169
+ // best-effort
170
+ }
171
+ })();
172
+ }
173
+
174
+ return {
175
+ newAgentId: forked.id,
176
+ newSessionId: forked.session_id,
177
+ originalAgentId: agentId,
178
+ providerSessionId: forked.session?.id,
179
+ };
180
+ };
181
+ }
182
+
183
+ function createSetPermissionModeHandler(services: AgentLifecycleExtensionServices): ExtensionHandler {
184
+ return async (_context: ExtensionContext, params: unknown) => {
185
+ const { agentId, permissionMode } = (params ?? {}) as {
186
+ agentId: string;
187
+ permissionMode: string;
188
+ };
189
+
190
+ if (!agentId || !permissionMode) {
191
+ throw RPCError.invalidParams("agentId and permissionMode are required");
192
+ }
193
+
194
+ const previousMode = services.getPermissionMode(agentId as AgentId);
195
+ const success = services.setPermissionMode(agentId as AgentId, permissionMode);
196
+
197
+ if (!success) {
198
+ return {
199
+ success: false,
200
+ error: `No active session found for agent ${agentId}`,
201
+ };
202
+ }
203
+
204
+ return {
205
+ success: true,
206
+ agentId,
207
+ previousMode,
208
+ newMode: permissionMode,
209
+ };
210
+ };
211
+ }
212
+
213
+ function createRespondToPermissionHandler(services: AgentLifecycleExtensionServices): ExtensionHandler {
214
+ return async (_context: ExtensionContext, params: unknown) => {
215
+ const { agentId, requestId, optionId } = (params ?? {}) as {
216
+ agentId: string;
217
+ requestId: string;
218
+ optionId: string;
219
+ };
220
+
221
+ if (!agentId || !requestId || !optionId) {
222
+ throw RPCError.invalidParams("agentId, requestId, and optionId are required");
223
+ }
224
+
225
+ const success = services.respondToPermission(
226
+ agentId as AgentId,
227
+ requestId,
228
+ optionId,
229
+ );
230
+
231
+ return { success };
232
+ };
233
+ }
234
+
235
+ // =============================================================================
236
+ // Registration
237
+ // =============================================================================
238
+
239
+ /** All agent lifecycle extension method names */
240
+ export const AGENT_LIFECYCLE_METHODS = [
241
+ "_macro/spawnAgent",
242
+ "_macro/forkAgent",
243
+ "_macro/setPermissionMode",
244
+ "_macro/respondToPermission",
245
+ ] as const;
246
+
247
+ /**
248
+ * Register agent lifecycle extension methods with the MAPAdapter.
249
+ */
250
+ export function registerAgentLifecycleExtensions(
251
+ adapter: MAPAdapter,
252
+ services: AgentLifecycleExtensionServices,
253
+ ): void {
254
+ adapter.registerExtension("_macro/spawnAgent", createSpawnHandler(services));
255
+ adapter.registerExtension("_macro/forkAgent", createForkHandler(services));
256
+ adapter.registerExtension("_macro/setPermissionMode", createSetPermissionModeHandler(services));
257
+ adapter.registerExtension("_macro/respondToPermission", createRespondToPermissionHandler(services));
258
+ }
259
+
260
+ /**
261
+ * Unregister agent lifecycle extension methods.
262
+ */
263
+ export function unregisterAgentLifecycleExtensions(adapter: MAPAdapter): void {
264
+ for (const method of AGENT_LIFECYCLE_METHODS) {
265
+ adapter.unregisterExtension(method);
266
+ }
267
+ }
@@ -52,6 +52,29 @@ export {
52
52
  type AgentDetectionExtensionServices,
53
53
  } from "./agent-detection.js";
54
54
 
55
+ // Update metadata extension
56
+ export {
57
+ registerUpdateMetadataExtension,
58
+ unregisterUpdateMetadataExtension,
59
+ type UpdateMetadataExtensionServices,
60
+ } from "./update-metadata.js";
61
+
62
+ // MCP bridge extensions
63
+ export {
64
+ registerMCPBridgeExtensions,
65
+ unregisterMCPBridgeExtensions,
66
+ MCP_BRIDGE_METHODS,
67
+ type MCPBridgeServices,
68
+ } from "./mcp-bridge.js";
69
+
70
+ // Agent lifecycle extensions
71
+ export {
72
+ registerAgentLifecycleExtensions,
73
+ unregisterAgentLifecycleExtensions,
74
+ AGENT_LIFECYCLE_METHODS,
75
+ type AgentLifecycleExtensionServices,
76
+ } from "./agent-lifecycle.js";
77
+
55
78
  import type { MAPAdapter } from "../interface.js";
56
79
  import type { TaskExtensionServices } from "./task.js";
57
80
  import type { WakeExtensionServices } from "./wake.js";
@@ -59,12 +82,18 @@ import type { WorkspaceExtensionServices } from "./workspace.js";
59
82
  import type { WorkspaceFileServices } from "./workspace-files.js";
60
83
  import type { ResumeExtensionServices } from "./resume.js";
61
84
  import type { AgentDetectionExtensionServices } from "./agent-detection.js";
85
+ import type { UpdateMetadataExtensionServices } from "./update-metadata.js";
86
+ import type { MCPBridgeServices } from "./mcp-bridge.js";
87
+ import type { AgentLifecycleExtensionServices } from "./agent-lifecycle.js";
62
88
  import { registerTaskExtensions } from "./task.js";
63
89
  import { registerWakeExtension } from "./wake.js";
64
90
  import { registerWorkspaceExtension } from "./workspace.js";
65
91
  import { registerWorkspaceFileExtensions } from "./workspace-files.js";
66
92
  import { registerResumeExtension } from "./resume.js";
67
93
  import { registerAgentDetectionExtensions } from "./agent-detection.js";
94
+ import { registerUpdateMetadataExtension } from "./update-metadata.js";
95
+ import { registerMCPBridgeExtensions, unregisterMCPBridgeExtensions, MCP_BRIDGE_METHODS } from "./mcp-bridge.js";
96
+ import { registerAgentLifecycleExtensions, unregisterAgentLifecycleExtensions, AGENT_LIFECYCLE_METHODS } from "./agent-lifecycle.js";
68
97
 
69
98
  // =============================================================================
70
99
  // Combined Registration
@@ -80,6 +109,9 @@ export interface MacroExtensionServices {
80
109
  workspaceFiles?: WorkspaceFileServices;
81
110
  resume?: ResumeExtensionServices;
82
111
  agentDetection?: AgentDetectionExtensionServices;
112
+ updateMetadata?: UpdateMetadataExtensionServices;
113
+ mcpBridge?: MCPBridgeServices;
114
+ agentLifecycle?: AgentLifecycleExtensionServices;
83
115
  }
84
116
 
85
117
  /**
@@ -140,6 +172,18 @@ export function registerMacroExtensions(
140
172
  if (services.agentDetection) {
141
173
  registerAgentDetectionExtensions(adapter, services.agentDetection);
142
174
  }
175
+
176
+ if (services.updateMetadata) {
177
+ registerUpdateMetadataExtension(adapter, services.updateMetadata);
178
+ }
179
+
180
+ if (services.mcpBridge) {
181
+ registerMCPBridgeExtensions(adapter, services.mcpBridge);
182
+ }
183
+
184
+ if (services.agentLifecycle) {
185
+ registerAgentLifecycleExtensions(adapter, services.agentLifecycle);
186
+ }
143
187
  }
144
188
 
145
189
  /**
@@ -164,9 +208,14 @@ export function unregisterMacroExtensions(adapter: MAPAdapter): void {
164
208
  adapter.unregisterExtension("_macro/resume");
165
209
  adapter.unregisterExtension("_macro/agents/available");
166
210
  adapter.unregisterExtension("_macro/agents/refresh");
211
+ adapter.unregisterExtension("_macro/agents/update");
167
212
  } catch {
168
213
  // Ignore errors from unregistering non-existent extensions
169
214
  }
215
+ // Also unregister MCP bridge extensions
216
+ unregisterMCPBridgeExtensions(adapter);
217
+ // Also unregister agent lifecycle extensions
218
+ unregisterAgentLifecycleExtensions(adapter);
170
219
  }
171
220
 
172
221
  // =============================================================================
@@ -197,6 +246,12 @@ export const MACRO_EXTENSION_METHODS = [
197
246
  // Agent detection extensions
198
247
  "_macro/agents/available",
199
248
  "_macro/agents/refresh",
249
+ // Update metadata extension
250
+ "_macro/agents/update",
251
+ // MCP bridge extensions
252
+ ...MCP_BRIDGE_METHODS,
253
+ // Agent lifecycle extensions
254
+ ...AGENT_LIFECYCLE_METHODS,
200
255
  ] as const;
201
256
 
202
257
  /**
@@ -217,4 +272,9 @@ export const EXTENSION_CAPABILITIES: Record<string, string> = {
217
272
  "_macro/resume": "canManageLifecycle",
218
273
  "_macro/agents/available": "canQuery",
219
274
  "_macro/agents/refresh": "canQuery",
275
+ "_macro/agents/update": "canQuery",
276
+ "_macro/spawnAgent": "canManageLifecycle",
277
+ "_macro/forkAgent": "canManageLifecycle",
278
+ "_macro/setPermissionMode": "canManageLifecycle",
279
+ "_macro/respondToPermission": "canManageLifecycle",
220
280
  };