macro-agent 0.1.0 → 0.1.2

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 (660) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/.sudocode/issues.jsonl +28 -0
  3. package/.sudocode/specs.jsonl +8 -0
  4. package/CLAUDE.md +25 -17
  5. package/README.md +11 -29
  6. package/dist/acp/macro-agent.d.ts +15 -0
  7. package/dist/acp/macro-agent.d.ts.map +1 -1
  8. package/dist/acp/macro-agent.js +131 -35
  9. package/dist/acp/macro-agent.js.map +1 -1
  10. package/dist/acp/types.d.ts +32 -1
  11. package/dist/acp/types.d.ts.map +1 -1
  12. package/dist/acp/types.js.map +1 -1
  13. package/dist/agent/agent-manager.d.ts +65 -1
  14. package/dist/agent/agent-manager.d.ts.map +1 -1
  15. package/dist/agent/agent-manager.js +544 -200
  16. package/dist/agent/agent-manager.js.map +1 -1
  17. package/dist/agent/types.d.ts +8 -1
  18. package/dist/agent/types.d.ts.map +1 -1
  19. package/dist/agent/types.js.map +1 -1
  20. package/dist/api/server.d.ts +8 -1
  21. package/dist/api/server.d.ts.map +1 -1
  22. package/dist/api/server.js +136 -8
  23. package/dist/api/server.js.map +1 -1
  24. package/dist/api/types.d.ts +1 -1
  25. package/dist/api/types.d.ts.map +1 -1
  26. package/dist/auth/index.d.ts +2 -0
  27. package/dist/auth/index.d.ts.map +1 -0
  28. package/dist/auth/index.js +2 -0
  29. package/dist/auth/index.js.map +1 -0
  30. package/dist/auth/token.d.ts +41 -0
  31. package/dist/auth/token.d.ts.map +1 -0
  32. package/dist/auth/token.js +73 -0
  33. package/dist/auth/token.js.map +1 -0
  34. package/dist/cli/acp.d.ts +2 -23
  35. package/dist/cli/acp.d.ts.map +1 -1
  36. package/dist/cli/acp.js +197 -61
  37. package/dist/cli/acp.js.map +1 -1
  38. package/dist/cli/index.js +152 -16
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/cli/mcp.d.ts +6 -0
  41. package/dist/cli/mcp.d.ts.map +1 -1
  42. package/dist/cli/mcp.js +279 -173
  43. package/dist/cli/mcp.js.map +1 -1
  44. package/dist/cli/parse-args.d.ts +20 -0
  45. package/dist/cli/parse-args.d.ts.map +1 -0
  46. package/dist/cli/parse-args.js +43 -0
  47. package/dist/cli/parse-args.js.map +1 -0
  48. package/dist/cli/stable-instance-id.d.ts +8 -0
  49. package/dist/cli/stable-instance-id.d.ts.map +1 -0
  50. package/dist/cli/stable-instance-id.js +14 -0
  51. package/dist/cli/stable-instance-id.js.map +1 -0
  52. package/dist/config/project-config.d.ts +85 -7
  53. package/dist/config/project-config.d.ts.map +1 -1
  54. package/dist/config/project-config.js +133 -20
  55. package/dist/config/project-config.js.map +1 -1
  56. package/dist/index.d.ts +1 -0
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +2 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/lifecycle/handlers/index.d.ts +7 -3
  61. package/dist/lifecycle/handlers/index.d.ts.map +1 -1
  62. package/dist/lifecycle/handlers/index.js +25 -8
  63. package/dist/lifecycle/handlers/index.js.map +1 -1
  64. package/dist/lifecycle/types.d.ts +2 -0
  65. package/dist/lifecycle/types.d.ts.map +1 -1
  66. package/dist/lifecycle/types.js.map +1 -1
  67. package/dist/map/adapter/acp-over-map.d.ts +17 -0
  68. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  69. package/dist/map/adapter/acp-over-map.js +384 -23
  70. package/dist/map/adapter/acp-over-map.js.map +1 -1
  71. package/dist/map/adapter/connection-manager.d.ts.map +1 -1
  72. package/dist/map/adapter/connection-manager.js +3 -0
  73. package/dist/map/adapter/connection-manager.js.map +1 -1
  74. package/dist/map/adapter/event-log.d.ts +87 -0
  75. package/dist/map/adapter/event-log.d.ts.map +1 -0
  76. package/dist/map/adapter/event-log.js +122 -0
  77. package/dist/map/adapter/event-log.js.map +1 -0
  78. package/dist/map/adapter/event-translator.js +6 -6
  79. package/dist/map/adapter/event-translator.js.map +1 -1
  80. package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
  81. package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
  82. package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
  83. package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
  84. package/dist/map/adapter/extensions/index.d.ts +13 -1
  85. package/dist/map/adapter/extensions/index.d.ts.map +1 -1
  86. package/dist/map/adapter/extensions/index.js +61 -0
  87. package/dist/map/adapter/extensions/index.js.map +1 -1
  88. package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
  89. package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
  90. package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
  91. package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
  92. package/dist/map/adapter/extensions/rename.d.ts +29 -0
  93. package/dist/map/adapter/extensions/rename.d.ts.map +1 -0
  94. package/dist/map/adapter/extensions/rename.js +49 -0
  95. package/dist/map/adapter/extensions/rename.js.map +1 -0
  96. package/dist/map/adapter/extensions/streams.d.ts +95 -0
  97. package/dist/map/adapter/extensions/streams.d.ts.map +1 -0
  98. package/dist/map/adapter/extensions/streams.js +515 -0
  99. package/dist/map/adapter/extensions/streams.js.map +1 -0
  100. package/dist/map/adapter/extensions/task.d.ts.map +1 -1
  101. package/dist/map/adapter/extensions/task.js +10 -0
  102. package/dist/map/adapter/extensions/task.js.map +1 -1
  103. package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
  104. package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
  105. package/dist/map/adapter/extensions/update-metadata.js +67 -0
  106. package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
  107. package/dist/map/adapter/index.d.ts +2 -1
  108. package/dist/map/adapter/index.d.ts.map +1 -1
  109. package/dist/map/adapter/index.js +10 -2
  110. package/dist/map/adapter/index.js.map +1 -1
  111. package/dist/map/adapter/interface.d.ts +2 -0
  112. package/dist/map/adapter/interface.d.ts.map +1 -1
  113. package/dist/map/adapter/map-adapter.d.ts +3 -0
  114. package/dist/map/adapter/map-adapter.d.ts.map +1 -1
  115. package/dist/map/adapter/map-adapter.js +258 -35
  116. package/dist/map/adapter/map-adapter.js.map +1 -1
  117. package/dist/map/adapter/subscription-manager.d.ts.map +1 -1
  118. package/dist/map/adapter/subscription-manager.js +5 -1
  119. package/dist/map/adapter/subscription-manager.js.map +1 -1
  120. package/dist/map/adapter/types.d.ts +3 -1
  121. package/dist/map/adapter/types.d.ts.map +1 -1
  122. package/dist/mcp/map-client.d.ts +39 -0
  123. package/dist/mcp/map-client.d.ts.map +1 -0
  124. package/dist/mcp/map-client.js +129 -0
  125. package/dist/mcp/map-client.js.map +1 -0
  126. package/dist/mcp/mcp-server.d.ts +16 -0
  127. package/dist/mcp/mcp-server.d.ts.map +1 -1
  128. package/dist/mcp/mcp-server.js +125 -88
  129. package/dist/mcp/mcp-server.js.map +1 -1
  130. package/dist/mcp/tools/done.d.ts.map +1 -1
  131. package/dist/mcp/tools/done.js +18 -0
  132. package/dist/mcp/tools/done.js.map +1 -1
  133. package/dist/mcp/types.d.ts +9 -1
  134. package/dist/mcp/types.d.ts.map +1 -1
  135. package/dist/mcp/types.js.map +1 -1
  136. package/dist/metrics/metrics.js +1 -1
  137. package/dist/metrics/metrics.js.map +1 -1
  138. package/dist/roles/builtin/coordinator.d.ts.map +1 -1
  139. package/dist/roles/builtin/coordinator.js +2 -1
  140. package/dist/roles/builtin/coordinator.js.map +1 -1
  141. package/dist/roles/builtin/integrator.d.ts.map +1 -1
  142. package/dist/roles/builtin/integrator.js +2 -1
  143. package/dist/roles/builtin/integrator.js.map +1 -1
  144. package/dist/roles/builtin/worker.d.ts.map +1 -1
  145. package/dist/roles/builtin/worker.js +3 -1
  146. package/dist/roles/builtin/worker.js.map +1 -1
  147. package/dist/roles/capabilities.d.ts +9 -1
  148. package/dist/roles/capabilities.d.ts.map +1 -1
  149. package/dist/roles/capabilities.js +27 -7
  150. package/dist/roles/capabilities.js.map +1 -1
  151. package/dist/roles/config-loader.d.ts +6 -6
  152. package/dist/roles/config-loader.d.ts.map +1 -1
  153. package/dist/roles/config-loader.js +8 -7
  154. package/dist/roles/config-loader.js.map +1 -1
  155. package/dist/roles/registry.d.ts +2 -2
  156. package/dist/roles/registry.js +2 -2
  157. package/dist/roles/types.d.ts +3 -1
  158. package/dist/roles/types.d.ts.map +1 -1
  159. package/dist/server/combined-server.d.ts +28 -1
  160. package/dist/server/combined-server.d.ts.map +1 -1
  161. package/dist/server/combined-server.js +111 -8
  162. package/dist/server/combined-server.js.map +1 -1
  163. package/dist/store/event-store.d.ts +2 -1
  164. package/dist/store/event-store.d.ts.map +1 -1
  165. package/dist/store/event-store.js +80 -24
  166. package/dist/store/event-store.js.map +1 -1
  167. package/dist/store/instance.d.ts +1 -1
  168. package/dist/store/instance.d.ts.map +1 -1
  169. package/dist/store/instance.js +2 -2
  170. package/dist/store/instance.js.map +1 -1
  171. package/dist/store/types/agents.d.ts +23 -0
  172. package/dist/store/types/agents.d.ts.map +1 -1
  173. package/dist/store/types/events.d.ts +1 -1
  174. package/dist/store/types/events.d.ts.map +1 -1
  175. package/dist/task/backend/index.d.ts +47 -29
  176. package/dist/task/backend/index.d.ts.map +1 -1
  177. package/dist/task/backend/index.js +109 -71
  178. package/dist/task/backend/index.js.map +1 -1
  179. package/dist/task/backend/memory.d.ts +1 -0
  180. package/dist/task/backend/memory.d.ts.map +1 -1
  181. package/dist/task/backend/memory.js +3 -0
  182. package/dist/task/backend/memory.js.map +1 -1
  183. package/dist/task/backend/opentasks/backend.d.ts +140 -0
  184. package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
  185. package/dist/task/backend/opentasks/backend.js +1023 -0
  186. package/dist/task/backend/opentasks/backend.js.map +1 -0
  187. package/dist/task/backend/opentasks/client.d.ts +337 -0
  188. package/dist/task/backend/opentasks/client.d.ts.map +1 -0
  189. package/dist/task/backend/opentasks/client.js +225 -0
  190. package/dist/task/backend/opentasks/client.js.map +1 -0
  191. package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
  192. package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
  193. package/dist/task/backend/opentasks/daemon-manager.js +195 -0
  194. package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
  195. package/dist/task/backend/opentasks/index.d.ts +21 -0
  196. package/dist/task/backend/opentasks/index.d.ts.map +1 -0
  197. package/dist/task/backend/opentasks/index.js +21 -0
  198. package/dist/task/backend/opentasks/index.js.map +1 -0
  199. package/dist/task/backend/opentasks/mapping.d.ts +48 -0
  200. package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
  201. package/dist/task/backend/opentasks/mapping.js +77 -0
  202. package/dist/task/backend/opentasks/mapping.js.map +1 -0
  203. package/dist/task/backend/types.d.ts +33 -53
  204. package/dist/task/backend/types.d.ts.map +1 -1
  205. package/dist/task/backend/types.js +7 -11
  206. package/dist/task/backend/types.js.map +1 -1
  207. package/dist/task/backend/unified-tool-provider.d.ts +57 -0
  208. package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
  209. package/dist/task/backend/unified-tool-provider.js +623 -0
  210. package/dist/task/backend/unified-tool-provider.js.map +1 -0
  211. package/dist/teams/index.d.ts +3 -1
  212. package/dist/teams/index.d.ts.map +1 -1
  213. package/dist/teams/index.js +2 -0
  214. package/dist/teams/index.js.map +1 -1
  215. package/dist/teams/seed-defaults.d.ts +20 -0
  216. package/dist/teams/seed-defaults.d.ts.map +1 -0
  217. package/dist/teams/seed-defaults.js +71 -0
  218. package/dist/teams/seed-defaults.js.map +1 -0
  219. package/dist/teams/team-loader.d.ts +7 -3
  220. package/dist/teams/team-loader.d.ts.map +1 -1
  221. package/dist/teams/team-loader.js +156 -164
  222. package/dist/teams/team-loader.js.map +1 -1
  223. package/dist/teams/team-manager.d.ts +112 -0
  224. package/dist/teams/team-manager.d.ts.map +1 -0
  225. package/dist/teams/team-manager.js +305 -0
  226. package/dist/teams/team-manager.js.map +1 -0
  227. package/dist/teams/team-runtime.d.ts +125 -19
  228. package/dist/teams/team-runtime.d.ts.map +1 -1
  229. package/dist/teams/team-runtime.js +529 -119
  230. package/dist/teams/team-runtime.js.map +1 -1
  231. package/dist/teams/types.d.ts +41 -151
  232. package/dist/teams/types.d.ts.map +1 -1
  233. package/dist/teams/types.js +2 -3
  234. package/dist/teams/types.js.map +1 -1
  235. package/docs/architecture.md +7 -6
  236. package/docs/configuration.md +26 -62
  237. package/docs/implementation-details.md +5 -5
  238. package/docs/implementation-summary.md +17 -17
  239. package/docs/plan-self-driving-support.md +4 -4
  240. package/docs/spec-self-driving-support.md +10 -10
  241. package/docs/team-templates.md +2 -2
  242. package/docs/teams.md +76 -3
  243. package/docs/troubleshooting.md +10 -11
  244. package/package.json +7 -4
  245. package/references/minimem/.claude/settings.json +7 -0
  246. package/references/minimem/.sudocode/issues.jsonl +18 -0
  247. package/references/minimem/.sudocode/specs.jsonl +1 -0
  248. package/references/minimem/CLAUDE.md +310 -0
  249. package/references/minimem/README.md +562 -0
  250. package/references/minimem/claude-plugin/.claude-plugin/plugin.json +10 -0
  251. package/references/minimem/claude-plugin/.mcp.json +7 -0
  252. package/references/minimem/claude-plugin/README.md +158 -0
  253. package/references/minimem/claude-plugin/commands/recall.md +47 -0
  254. package/references/minimem/claude-plugin/commands/remember.md +41 -0
  255. package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +272 -0
  256. package/references/minimem/claude-plugin/hooks/hooks.json +27 -0
  257. package/references/minimem/claude-plugin/hooks/session-end.sh +86 -0
  258. package/references/minimem/claude-plugin/hooks/session-start.sh +85 -0
  259. package/references/minimem/claude-plugin/skills/memory/SKILL.md +108 -0
  260. package/references/minimem/media/banner.png +0 -0
  261. package/references/minimem/package-lock.json +5373 -0
  262. package/references/minimem/package.json +72 -0
  263. package/references/minimem/scripts/postbuild.js +35 -0
  264. package/references/minimem/src/__tests__/edge-cases.test.ts +371 -0
  265. package/references/minimem/src/__tests__/errors.test.ts +265 -0
  266. package/references/minimem/src/__tests__/helpers.ts +199 -0
  267. package/references/minimem/src/__tests__/internal.test.ts +407 -0
  268. package/references/minimem/src/__tests__/knowledge.test.ts +287 -0
  269. package/references/minimem/src/__tests__/minimem.integration.test.ts +1127 -0
  270. package/references/minimem/src/__tests__/session.test.ts +190 -0
  271. package/references/minimem/src/cli/__tests__/commands.test.ts +759 -0
  272. package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +141 -0
  273. package/references/minimem/src/cli/commands/append.ts +76 -0
  274. package/references/minimem/src/cli/commands/config.ts +262 -0
  275. package/references/minimem/src/cli/commands/conflicts.ts +413 -0
  276. package/references/minimem/src/cli/commands/daemon.ts +169 -0
  277. package/references/minimem/src/cli/commands/index.ts +12 -0
  278. package/references/minimem/src/cli/commands/init.ts +88 -0
  279. package/references/minimem/src/cli/commands/mcp.ts +177 -0
  280. package/references/minimem/src/cli/commands/push-pull.ts +213 -0
  281. package/references/minimem/src/cli/commands/search.ts +158 -0
  282. package/references/minimem/src/cli/commands/status.ts +84 -0
  283. package/references/minimem/src/cli/commands/sync-init.ts +290 -0
  284. package/references/minimem/src/cli/commands/sync.ts +70 -0
  285. package/references/minimem/src/cli/commands/upsert.ts +197 -0
  286. package/references/minimem/src/cli/config.ts +584 -0
  287. package/references/minimem/src/cli/index.ts +264 -0
  288. package/references/minimem/src/cli/shared.ts +161 -0
  289. package/references/minimem/src/cli/sync/__tests__/central.test.ts +152 -0
  290. package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +209 -0
  291. package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +118 -0
  292. package/references/minimem/src/cli/sync/__tests__/detection.test.ts +207 -0
  293. package/references/minimem/src/cli/sync/__tests__/integration.test.ts +476 -0
  294. package/references/minimem/src/cli/sync/__tests__/registry.test.ts +363 -0
  295. package/references/minimem/src/cli/sync/__tests__/state.test.ts +255 -0
  296. package/references/minimem/src/cli/sync/__tests__/validation.test.ts +193 -0
  297. package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +178 -0
  298. package/references/minimem/src/cli/sync/central.ts +292 -0
  299. package/references/minimem/src/cli/sync/conflicts.ts +204 -0
  300. package/references/minimem/src/cli/sync/daemon.ts +407 -0
  301. package/references/minimem/src/cli/sync/detection.ts +138 -0
  302. package/references/minimem/src/cli/sync/index.ts +107 -0
  303. package/references/minimem/src/cli/sync/operations.ts +373 -0
  304. package/references/minimem/src/cli/sync/registry.ts +279 -0
  305. package/references/minimem/src/cli/sync/state.ts +355 -0
  306. package/references/minimem/src/cli/sync/validation.ts +206 -0
  307. package/references/minimem/src/cli/sync/watcher.ts +234 -0
  308. package/references/minimem/src/cli/version.ts +34 -0
  309. package/references/minimem/src/core/index.ts +9 -0
  310. package/references/minimem/src/core/indexer.ts +628 -0
  311. package/references/minimem/src/core/searcher.ts +221 -0
  312. package/references/minimem/src/db/schema.ts +183 -0
  313. package/references/minimem/src/db/sqlite-vec.ts +24 -0
  314. package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +431 -0
  315. package/references/minimem/src/embeddings/batch-gemini.ts +392 -0
  316. package/references/minimem/src/embeddings/batch-openai.ts +409 -0
  317. package/references/minimem/src/embeddings/embeddings.ts +434 -0
  318. package/references/minimem/src/index.ts +109 -0
  319. package/references/minimem/src/internal.ts +299 -0
  320. package/references/minimem/src/minimem.ts +1276 -0
  321. package/references/minimem/src/search/__tests__/hybrid.test.ts +247 -0
  322. package/references/minimem/src/search/graph.ts +234 -0
  323. package/references/minimem/src/search/hybrid.ts +151 -0
  324. package/references/minimem/src/search/search.ts +256 -0
  325. package/references/minimem/src/server/__tests__/mcp.test.ts +341 -0
  326. package/references/minimem/src/server/__tests__/tools.test.ts +364 -0
  327. package/references/minimem/src/server/mcp.ts +326 -0
  328. package/references/minimem/src/server/tools.ts +720 -0
  329. package/references/minimem/src/session.ts +460 -0
  330. package/references/minimem/tsconfig.json +19 -0
  331. package/references/minimem/tsup.config.ts +26 -0
  332. package/references/minimem/vitest.config.ts +24 -0
  333. package/references/openteams/.claude/settings.json +6 -0
  334. package/references/openteams/README.md +1 -0
  335. package/references/openteams/SKILL.md +341 -0
  336. package/references/openteams/design.md +411 -0
  337. package/references/openteams/examples/bmad-method/prompts/analyst/ROLE.md +16 -0
  338. package/references/openteams/examples/bmad-method/prompts/analyst/SOUL.md +5 -0
  339. package/references/openteams/examples/bmad-method/prompts/architect/ROLE.md +24 -0
  340. package/references/openteams/examples/bmad-method/prompts/architect/SOUL.md +5 -0
  341. package/references/openteams/examples/bmad-method/prompts/developer/ROLE.md +25 -0
  342. package/references/openteams/examples/bmad-method/prompts/developer/SOUL.md +5 -0
  343. package/references/openteams/examples/bmad-method/prompts/master/ROLE.md +21 -0
  344. package/references/openteams/examples/bmad-method/prompts/master/SOUL.md +5 -0
  345. package/references/openteams/examples/bmad-method/prompts/pm/ROLE.md +20 -0
  346. package/references/openteams/examples/bmad-method/prompts/pm/SOUL.md +5 -0
  347. package/references/openteams/examples/bmad-method/prompts/qa/ROLE.md +17 -0
  348. package/references/openteams/examples/bmad-method/prompts/qa/SOUL.md +5 -0
  349. package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/ROLE.md +23 -0
  350. package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/SOUL.md +5 -0
  351. package/references/openteams/examples/bmad-method/prompts/scrum-master/ROLE.md +27 -0
  352. package/references/openteams/examples/bmad-method/prompts/scrum-master/SOUL.md +5 -0
  353. package/references/openteams/examples/bmad-method/prompts/tech-writer/ROLE.md +21 -0
  354. package/references/openteams/examples/bmad-method/prompts/tech-writer/SOUL.md +5 -0
  355. package/references/openteams/examples/bmad-method/prompts/ux-designer/ROLE.md +16 -0
  356. package/references/openteams/examples/bmad-method/prompts/ux-designer/SOUL.md +5 -0
  357. package/references/openteams/examples/bmad-method/roles/analyst.yaml +9 -0
  358. package/references/openteams/examples/bmad-method/roles/architect.yaml +9 -0
  359. package/references/openteams/examples/bmad-method/roles/developer.yaml +8 -0
  360. package/references/openteams/examples/bmad-method/roles/master.yaml +8 -0
  361. package/references/openteams/examples/bmad-method/roles/pm.yaml +9 -0
  362. package/references/openteams/examples/bmad-method/roles/qa.yaml +8 -0
  363. package/references/openteams/examples/bmad-method/roles/quick-flow-dev.yaml +8 -0
  364. package/references/openteams/examples/bmad-method/roles/scrum-master.yaml +9 -0
  365. package/references/openteams/examples/bmad-method/roles/tech-writer.yaml +8 -0
  366. package/references/openteams/examples/bmad-method/roles/ux-designer.yaml +8 -0
  367. package/references/openteams/examples/bmad-method/team.yaml +161 -0
  368. package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/ROLE.md +17 -0
  369. package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/SOUL.md +5 -0
  370. package/references/openteams/examples/get-shit-done/prompts/debugger/ROLE.md +25 -0
  371. package/references/openteams/examples/get-shit-done/prompts/debugger/SOUL.md +5 -0
  372. package/references/openteams/examples/get-shit-done/prompts/executor/ROLE.md +34 -0
  373. package/references/openteams/examples/get-shit-done/prompts/executor/SOUL.md +5 -0
  374. package/references/openteams/examples/get-shit-done/prompts/integration-checker/ROLE.md +18 -0
  375. package/references/openteams/examples/get-shit-done/prompts/integration-checker/SOUL.md +3 -0
  376. package/references/openteams/examples/get-shit-done/prompts/orchestrator/ROLE.md +42 -0
  377. package/references/openteams/examples/get-shit-done/prompts/orchestrator/SOUL.md +5 -0
  378. package/references/openteams/examples/get-shit-done/prompts/phase-researcher/ROLE.md +15 -0
  379. package/references/openteams/examples/get-shit-done/prompts/phase-researcher/SOUL.md +3 -0
  380. package/references/openteams/examples/get-shit-done/prompts/plan-checker/ROLE.md +17 -0
  381. package/references/openteams/examples/get-shit-done/prompts/plan-checker/SOUL.md +3 -0
  382. package/references/openteams/examples/get-shit-done/prompts/planner/ROLE.md +28 -0
  383. package/references/openteams/examples/get-shit-done/prompts/planner/SOUL.md +5 -0
  384. package/references/openteams/examples/get-shit-done/prompts/project-researcher/ROLE.md +16 -0
  385. package/references/openteams/examples/get-shit-done/prompts/project-researcher/SOUL.md +3 -0
  386. package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/ROLE.md +13 -0
  387. package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/SOUL.md +3 -0
  388. package/references/openteams/examples/get-shit-done/prompts/roadmapper/ROLE.md +14 -0
  389. package/references/openteams/examples/get-shit-done/prompts/roadmapper/SOUL.md +3 -0
  390. package/references/openteams/examples/get-shit-done/prompts/verifier/ROLE.md +19 -0
  391. package/references/openteams/examples/get-shit-done/prompts/verifier/SOUL.md +5 -0
  392. package/references/openteams/examples/get-shit-done/roles/codebase-mapper.yaml +8 -0
  393. package/references/openteams/examples/get-shit-done/roles/debugger.yaml +8 -0
  394. package/references/openteams/examples/get-shit-done/roles/executor.yaml +8 -0
  395. package/references/openteams/examples/get-shit-done/roles/integration-checker.yaml +8 -0
  396. package/references/openteams/examples/get-shit-done/roles/orchestrator.yaml +9 -0
  397. package/references/openteams/examples/get-shit-done/roles/phase-researcher.yaml +7 -0
  398. package/references/openteams/examples/get-shit-done/roles/plan-checker.yaml +8 -0
  399. package/references/openteams/examples/get-shit-done/roles/planner.yaml +8 -0
  400. package/references/openteams/examples/get-shit-done/roles/project-researcher.yaml +8 -0
  401. package/references/openteams/examples/get-shit-done/roles/research-synthesizer.yaml +7 -0
  402. package/references/openteams/examples/get-shit-done/roles/roadmapper.yaml +7 -0
  403. package/references/openteams/examples/get-shit-done/roles/verifier.yaml +8 -0
  404. package/references/openteams/examples/get-shit-done/team.yaml +154 -0
  405. package/references/openteams/package-lock.json +2181 -0
  406. package/references/openteams/package.json +48 -0
  407. package/references/openteams/schema/role.schema.json +125 -0
  408. package/references/openteams/schema/team.schema.json +284 -0
  409. package/references/openteams/src/cli/agent.ts +104 -0
  410. package/references/openteams/src/cli/cli.test.ts +381 -0
  411. package/references/openteams/src/cli/generate.ts +220 -0
  412. package/references/openteams/src/cli/message.ts +241 -0
  413. package/references/openteams/src/cli/task.ts +154 -0
  414. package/references/openteams/src/cli/team.ts +104 -0
  415. package/references/openteams/src/cli/template.ts +207 -0
  416. package/references/openteams/src/cli.ts +45 -0
  417. package/references/openteams/src/db/database.test.ts +185 -0
  418. package/references/openteams/src/db/database.ts +240 -0
  419. package/references/openteams/src/generators/agent-prompt-generator.test.ts +332 -0
  420. package/references/openteams/src/generators/agent-prompt-generator.ts +521 -0
  421. package/references/openteams/src/generators/package-generator.test.ts +129 -0
  422. package/references/openteams/src/generators/package-generator.ts +102 -0
  423. package/references/openteams/src/generators/skill-generator.test.ts +246 -0
  424. package/references/openteams/src/generators/skill-generator.ts +374 -0
  425. package/references/openteams/src/index.ts +104 -0
  426. package/references/openteams/src/services/agent-service.test.ts +158 -0
  427. package/references/openteams/src/services/agent-service.ts +84 -0
  428. package/references/openteams/src/services/communication-service.test.ts +455 -0
  429. package/references/openteams/src/services/communication-service.ts +371 -0
  430. package/references/openteams/src/services/message-service.test.ts +342 -0
  431. package/references/openteams/src/services/message-service.ts +203 -0
  432. package/references/openteams/src/services/task-service.test.ts +434 -0
  433. package/references/openteams/src/services/task-service.ts +239 -0
  434. package/references/openteams/src/services/team-service.test.ts +181 -0
  435. package/references/openteams/src/services/team-service.ts +139 -0
  436. package/references/openteams/src/services/template-service.test.ts +306 -0
  437. package/references/openteams/src/services/template-service.ts +182 -0
  438. package/references/openteams/src/spawner/acp-factory.ts +96 -0
  439. package/references/openteams/src/spawner/interface.ts +31 -0
  440. package/references/openteams/src/spawner/mock.test.ts +93 -0
  441. package/references/openteams/src/spawner/mock.ts +59 -0
  442. package/references/openteams/src/template/loader.test.ts +1319 -0
  443. package/references/openteams/src/template/loader.ts +698 -0
  444. package/references/openteams/src/template/types.ts +200 -0
  445. package/references/openteams/src/types.ts +205 -0
  446. package/references/openteams/tsconfig.json +18 -0
  447. package/references/openteams/vitest.config.ts +9 -0
  448. package/references/skill-tree/.claude/settings.json +6 -0
  449. package/references/skill-tree/.sudocode/issues.jsonl +11 -0
  450. package/references/skill-tree/.sudocode/specs.jsonl +1 -0
  451. package/references/skill-tree/CLAUDE.md +150 -0
  452. package/references/skill-tree/README.md +324 -0
  453. package/references/skill-tree/docs/GAPS_v1.md +221 -0
  454. package/references/skill-tree/docs/INTEGRATION_PLAN.md +467 -0
  455. package/references/skill-tree/docs/TODOS.md +91 -0
  456. package/references/skill-tree/docs/anthropic_skill_guide.md +1364 -0
  457. package/references/skill-tree/docs/design/federated-skill-trees.md +524 -0
  458. package/references/skill-tree/docs/design/multi-agent-sync.md +759 -0
  459. package/references/skill-tree/docs/scraper/BRAINSTORM.md +583 -0
  460. package/references/skill-tree/docs/scraper/POC_PLAN.md +420 -0
  461. package/references/skill-tree/docs/scraper/README.md +170 -0
  462. package/references/skill-tree/examples/basic-usage.ts +190 -0
  463. package/references/skill-tree/package-lock.json +1509 -0
  464. package/references/skill-tree/package.json +66 -0
  465. package/references/skill-tree/scraper/README.md +123 -0
  466. package/references/skill-tree/scraper/docs/DESIGN.md +683 -0
  467. package/references/skill-tree/scraper/docs/PLAN.md +336 -0
  468. package/references/skill-tree/scraper/drizzle.config.ts +10 -0
  469. package/references/skill-tree/scraper/package-lock.json +6329 -0
  470. package/references/skill-tree/scraper/package.json +68 -0
  471. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +7 -0
  472. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +7 -0
  473. package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +27 -0
  474. package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +21 -0
  475. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +54 -0
  476. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +24 -0
  477. package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +93 -0
  478. package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +22 -0
  479. package/references/skill-tree/scraper/tsup.config.ts +14 -0
  480. package/references/skill-tree/scraper/vitest.config.ts +17 -0
  481. package/references/skill-tree/scripts/convert-to-vitest.ts +166 -0
  482. package/references/skill-tree/skills/skill-writer/SKILL.md +339 -0
  483. package/references/skill-tree/skills/skill-writer/references/examples.md +326 -0
  484. package/references/skill-tree/skills/skill-writer/references/patterns.md +210 -0
  485. package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +123 -0
  486. package/references/skill-tree/test/run-all.ts +106 -0
  487. package/references/skill-tree/test/utils.ts +128 -0
  488. package/references/skill-tree/vitest.config.ts +16 -0
  489. package/src/__tests__/e2e/agent-spawn-visibility.e2e.test.ts +761 -0
  490. package/src/__tests__/e2e/full-agent-conflict-resolution.e2e.test.ts +2 -2
  491. package/src/__tests__/e2e/mcp-thin-client-bridge.e2e.test.ts +304 -0
  492. package/src/__tests__/e2e/mcp-tools-available.e2e.test.ts +324 -0
  493. package/src/__tests__/e2e/multi-agent.e2e.test.ts +5 -5
  494. package/src/__tests__/e2e/spawn-session-streaming.e2e.test.ts +563 -0
  495. package/src/acp/__tests__/integration.test.ts +56 -31
  496. package/src/acp/__tests__/macro-agent.test.ts +16 -7
  497. package/src/acp/macro-agent.ts +170 -36
  498. package/src/acp/types.ts +46 -1
  499. package/src/agent/__tests__/agent-manager.test.ts +228 -2
  500. package/src/agent/agent-manager.ts +809 -285
  501. package/src/agent/types.ts +12 -1
  502. package/src/api/__tests__/server.test.ts +203 -4
  503. package/src/api/server.ts +169 -10
  504. package/src/api/types.ts +3 -1
  505. package/src/auth/__tests__/token.test.ts +100 -0
  506. package/src/auth/index.ts +1 -0
  507. package/src/auth/token.ts +82 -0
  508. package/src/cli/__tests__/acp.test.ts +1 -1
  509. package/src/cli/__tests__/stable-instance-id.test.ts +1 -1
  510. package/src/cli/acp.ts +197 -72
  511. package/src/cli/index.ts +125 -15
  512. package/src/cli/mcp.ts +315 -197
  513. package/src/cli/parse-args.ts +54 -0
  514. package/src/cli/stable-instance-id.ts +14 -0
  515. package/src/config/project-config.ts +214 -27
  516. package/src/index.ts +3 -0
  517. package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
  518. package/src/lifecycle/__tests__/handlers.test.ts +53 -0
  519. package/src/lifecycle/handlers/index.ts +25 -8
  520. package/src/lifecycle/types.ts +3 -0
  521. package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +22 -4
  522. package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
  523. package/src/map/adapter/__tests__/acp-over-map-history.test.ts +263 -0
  524. package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +1 -1
  525. package/src/map/adapter/__tests__/event-broadcast.test.ts +420 -0
  526. package/src/map/adapter/__tests__/event-log.test.ts +527 -0
  527. package/src/map/adapter/__tests__/event-translator.test.ts +3 -3
  528. package/src/map/adapter/__tests__/extensions.test.ts +408 -0
  529. package/src/map/adapter/__tests__/map-adapter.test.ts +99 -0
  530. package/src/map/adapter/__tests__/mcp-bridge.test.ts +1187 -0
  531. package/src/map/adapter/__tests__/multi-client-broadcast.test.ts +711 -0
  532. package/src/map/adapter/__tests__/stream-extensions.test.ts +494 -0
  533. package/src/map/adapter/__tests__/websocket-integration.test.ts +218 -0
  534. package/src/map/adapter/acp-over-map.ts +678 -66
  535. package/src/map/adapter/connection-manager.ts +3 -0
  536. package/src/map/adapter/event-log.ts +208 -0
  537. package/src/map/adapter/event-translator.ts +6 -6
  538. package/src/map/adapter/extensions/agent-lifecycle.ts +267 -0
  539. package/src/map/adapter/extensions/index.ts +96 -0
  540. package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
  541. package/src/map/adapter/extensions/streams.ts +839 -0
  542. package/src/map/adapter/extensions/task.ts +11 -0
  543. package/src/map/adapter/extensions/update-metadata.ts +126 -0
  544. package/src/map/adapter/index.ts +33 -0
  545. package/src/map/adapter/interface.ts +2 -0
  546. package/src/map/adapter/map-adapter.ts +312 -47
  547. package/src/map/adapter/subscription-manager.ts +5 -1
  548. package/src/map/adapter/types.ts +10 -1
  549. package/src/mcp/__tests__/map-client.test.ts +386 -0
  550. package/src/mcp/__tests__/mcp-server-thin-client.test.ts +368 -0
  551. package/src/mcp/__tests__/mcp-server.test.ts +100 -1
  552. package/src/mcp/map-client.ts +177 -0
  553. package/src/mcp/mcp-server.ts +205 -103
  554. package/src/mcp/tools/done.ts +19 -0
  555. package/src/mcp/types.ts +6 -1
  556. package/src/metrics/metrics.ts +1 -1
  557. package/src/monitor/__tests__/stale-agent-flow.integration.test.ts +1 -1
  558. package/src/roles/__tests__/config-loader.test.ts +7 -7
  559. package/src/roles/builtin/coordinator.ts +2 -0
  560. package/src/roles/builtin/integrator.ts +2 -0
  561. package/src/roles/builtin/worker.ts +3 -0
  562. package/src/roles/capabilities.ts +28 -7
  563. package/src/roles/config-loader.ts +8 -7
  564. package/src/roles/registry.ts +2 -2
  565. package/src/roles/types.ts +7 -0
  566. package/src/server/__tests__/combined-server.test.ts +94 -21
  567. package/src/server/combined-server.ts +203 -33
  568. package/src/steering/__tests__/steering-integration.test.ts +1 -1
  569. package/src/store/__tests__/event-store-oob.test.ts +109 -0
  570. package/src/store/__tests__/event-store.test.ts +196 -1
  571. package/src/store/__tests__/instance.test.ts +3 -3
  572. package/src/store/event-store.ts +92 -23
  573. package/src/store/instance.ts +2 -2
  574. package/src/store/types/agents.ts +20 -0
  575. package/src/store/types/events.ts +1 -1
  576. package/src/task/backend/__tests__/create-task-backend.test.ts +225 -0
  577. package/src/task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test.ts +524 -0
  578. package/src/task/backend/__tests__/memory-pull-mode.test.ts +153 -0
  579. package/src/task/backend/__tests__/unified-tool-provider.test.ts +579 -0
  580. package/src/task/backend/index.ts +156 -106
  581. package/src/task/backend/memory.ts +4 -0
  582. package/src/task/backend/opentasks/__tests__/backend.test.ts +968 -0
  583. package/src/task/backend/opentasks/__tests__/daemon-manager.test.ts +406 -0
  584. package/src/task/backend/opentasks/__tests__/mapping.test.ts +84 -0
  585. package/src/task/backend/opentasks/__tests__/opentasks-backend.e2e.test.ts +1338 -0
  586. package/src/task/backend/opentasks/backend.ts +1323 -0
  587. package/src/task/backend/opentasks/client.ts +652 -0
  588. package/src/task/backend/opentasks/daemon-manager.ts +256 -0
  589. package/src/task/backend/opentasks/index.ts +69 -0
  590. package/src/task/backend/opentasks/mapping.ts +94 -0
  591. package/src/task/backend/types.ts +42 -66
  592. package/src/task/backend/unified-tool-provider.ts +779 -0
  593. package/src/teams/CLAUDE.md +180 -0
  594. package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
  595. package/src/teams/__tests__/e2e/workspace-isolation.e2e.test.ts +1263 -0
  596. package/src/teams/__tests__/team-manager.test.ts +814 -0
  597. package/src/teams/__tests__/team-system.test.ts +1291 -8
  598. package/src/teams/index.ts +21 -3
  599. package/src/teams/seed-defaults.ts +79 -0
  600. package/src/teams/team-loader.ts +202 -236
  601. package/src/teams/team-manager.ts +387 -0
  602. package/src/teams/team-runtime.ts +592 -121
  603. package/src/teams/types.ts +99 -200
  604. package/test_fixtures/README.md +2 -3
  605. package/test_fixtures/fixtures/index.ts +0 -3
  606. package/test_fixtures/fixtures/projects/project-with-specs.ts +7 -149
  607. package/test_fixtures/fixtures/repos/index.ts +1 -3
  608. package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -116
  609. package/test_fixtures/fixtures/repos/types.ts +0 -11
  610. package/test_fixtures/harness/__tests__/fixtures.test.ts +10 -102
  611. package/test_fixtures/harness/__tests__/temp-repo-and-simulator.test.ts +0 -33
  612. package/test_fixtures/harness/simulator/agent-simulator.ts +4 -4
  613. package/vitest.config.ts +1 -1
  614. package/vitest.e2e.config.ts +1 -1
  615. package/vitest.setup.ts +1 -30
  616. package/.macro-agent/teams/self-driving/prompts/grinder.md +0 -27
  617. package/.macro-agent/teams/self-driving/prompts/judge.md +0 -27
  618. package/.macro-agent/teams/self-driving/prompts/planner.md +0 -33
  619. package/.macro-agent/teams/self-driving/roles/grinder.yaml +0 -17
  620. package/.macro-agent/teams/self-driving/roles/judge.yaml +0 -24
  621. package/.macro-agent/teams/self-driving/roles/planner.yaml +0 -18
  622. package/.macro-agent/teams/self-driving/team.yaml +0 -103
  623. package/.macro-agent/teams/structured/prompts/developer.md +0 -26
  624. package/.macro-agent/teams/structured/prompts/lead.md +0 -25
  625. package/.macro-agent/teams/structured/prompts/reviewer.md +0 -24
  626. package/.macro-agent/teams/structured/roles/developer.yaml +0 -12
  627. package/.macro-agent/teams/structured/roles/lead.yaml +0 -11
  628. package/.macro-agent/teams/structured/roles/reviewer.yaml +0 -19
  629. package/.macro-agent/teams/structured/team.yaml +0 -89
  630. package/docs/sudocode-integration.md +0 -383
  631. package/src/task/backend/__tests__/backend-parity.test.ts +0 -451
  632. package/src/task/backend/__tests__/tool-provider-edge-cases.test.ts +0 -430
  633. package/src/task/backend/__tests__/tool-provider.test.ts +0 -983
  634. package/src/task/backend/sudocode/__tests__/backend-edge-cases.test.ts +0 -575
  635. package/src/task/backend/sudocode/__tests__/backend.test.ts +0 -1194
  636. package/src/task/backend/sudocode/__tests__/client-integration.test.ts +0 -418
  637. package/src/task/backend/sudocode/__tests__/client.test.ts +0 -345
  638. package/src/task/backend/sudocode/__tests__/e2e/backend.e2e.test.ts +0 -753
  639. package/src/task/backend/sudocode/__tests__/e2e/server-client.e2e.test.ts +0 -680
  640. package/src/task/backend/sudocode/__tests__/e2e-workflow.test.ts +0 -666
  641. package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts +0 -396
  642. package/src/task/backend/sudocode/__tests__/integration/sudocode-cli.integration.test.ts +0 -328
  643. package/src/task/backend/sudocode/__tests__/integration/test-utils.ts +0 -175
  644. package/src/task/backend/sudocode/__tests__/mapping-edge-cases.test.ts +0 -265
  645. package/src/task/backend/sudocode/__tests__/server-client.test.ts +0 -675
  646. package/src/task/backend/sudocode/__tests__/sync-policy-edge-cases.test.ts +0 -521
  647. package/src/task/backend/sudocode/__tests__/sync-policy.test.ts +0 -519
  648. package/src/task/backend/sudocode/__tests__/tools.test.ts +0 -471
  649. package/src/task/backend/sudocode/backend.ts +0 -1237
  650. package/src/task/backend/sudocode/client.ts +0 -515
  651. package/src/task/backend/sudocode/index.ts +0 -120
  652. package/src/task/backend/sudocode/mapping.ts +0 -93
  653. package/src/task/backend/sudocode/server-client.ts +0 -522
  654. package/src/task/backend/sudocode/standalone-client.ts +0 -623
  655. package/src/task/backend/sudocode/sync-policy.ts +0 -387
  656. package/src/task/backend/sudocode/tools.ts +0 -896
  657. package/src/task/backend/tool-provider.ts +0 -506
  658. package/test_fixtures/fixtures/sudocode/index.ts +0 -29
  659. package/test_fixtures/fixtures/sudocode/issues.ts +0 -185
  660. package/test_fixtures/fixtures/sudocode/specs.ts +0 -159
@@ -7,6 +7,7 @@
7
7
  * - MessageRouter for subscription setup
8
8
  */
9
9
  import { nanoid } from "nanoid";
10
+ import { uniqueNamesGenerator, adjectives, animals, } from "unique-names-generator";
10
11
  import { AgentFactory, } from "acp-factory";
11
12
  import { AgentManagerError } from "./types.js";
12
13
  import { AGENT_CAPABILITIES } from "../roles/capabilities.js";
@@ -45,7 +46,9 @@ function getSpawnCapability(childRole) {
45
46
  // AgentManager Implementation
46
47
  // ─────────────────────────────────────────────────────────────────
47
48
  export function createAgentManager(eventStore, messageRouter, config = {}) {
48
- const { defaultPermissionMode = "auto-approve", defaultAgentType = "claude-code", defaultCwd = process.cwd(), workspaceManager, roleRegistry = new DefaultRoleRegistry(), healthCheckService, mailService: initialMailService, conversationMap: initialConversationMap, } = config;
49
+ const { defaultPermissionMode = "auto-approve", defaultAgentType = "claude-code", defaultCwd = process.cwd(), workspaceManager, roleRegistry = new DefaultRoleRegistry(), healthCheckService, mailService: initialMailService, conversationMap: initialConversationMap, serverUrl, serverToken, agentTokenManager, taskBackend: configTaskBackend, openTasksSocketPath: initialOpenTasksSocketPath, } = config;
50
+ // Mutable OpenTasks socket path (support late binding via setOpenTasksSocketPath)
51
+ let configOpenTasksSocketPath = initialOpenTasksSocketPath;
49
52
  // Mutable mail services (support late binding via setMailServices)
50
53
  let mailService = initialMailService;
51
54
  let conversationMap = initialConversationMap;
@@ -57,17 +60,76 @@ export function createAgentManager(eventStore, messageRouter, config = {}) {
57
60
  const agentWorkspaces = new Map();
58
61
  // Lifecycle event listeners
59
62
  const lifecycleListeners = new Set();
63
+ // Shutdown guard — prevents spawns during close()
64
+ let isShuttingDown = false;
65
+ // ─────────────────────────────────────────────────────────────────
66
+ // MCP Server Config
67
+ // ─────────────────────────────────────────────────────────────────
68
+ /**
69
+ * Build the macro-agent MCP server config for a Claude Code agent session.
70
+ * Used by spawn(), resume(), and forkAgent() to ensure every agent gets
71
+ * access to the macro-agent coordination tools.
72
+ */
73
+ function buildMacroAgentMcp(opts) {
74
+ // Common env vars for both thin-client and legacy modes
75
+ const env = [
76
+ { name: "MACRO_AGENT_ID", value: opts.agentId },
77
+ { name: "MACRO_PARENT_ID", value: opts.parentId },
78
+ { name: "MACRO_TASK_ID", value: opts.taskId },
79
+ { name: "MACRO_AGENT_CWD", value: opts.cwd },
80
+ { name: "MACRO_PERMISSION_MODE", value: opts.permissionMode },
81
+ {
82
+ name: "MACRO_TASK_BACKEND",
83
+ value: configTaskBackend ?? process.env.MACRO_TASK_BACKEND ?? "",
84
+ },
85
+ {
86
+ name: "OPENTASKS_SOCKET_PATH",
87
+ value: configOpenTasksSocketPath ?? process.env.OPENTASKS_SOCKET_PATH ?? "",
88
+ },
89
+ // Pass streamId so MCP subprocess can include it in lifecycle context
90
+ // (WorkspaceManager is not available in subprocess)
91
+ { name: "MACRO_STREAM_ID", value: opts.streamId ?? "" },
92
+ ];
93
+ if (serverUrl) {
94
+ // Thin-client mode: forward tool calls to main server via MAP WebSocket
95
+ env.push({ name: "MACRO_SERVER_URL", value: serverUrl }, {
96
+ name: "MACRO_AGENT_LINEAGE",
97
+ value: JSON.stringify(opts.lineage ?? []),
98
+ }, { name: "MACRO_SESSION_ID", value: opts.sessionId ?? "" });
99
+ // Auth tokens for thin-client connections
100
+ if (serverToken) {
101
+ env.push({ name: "MACRO_SERVER_TOKEN", value: serverToken });
102
+ }
103
+ if (agentTokenManager) {
104
+ const agentToken = agentTokenManager.createToken(opts.agentId);
105
+ env.push({ name: "MACRO_AGENT_TOKEN", value: agentToken });
106
+ }
107
+ }
108
+ else {
109
+ // Legacy mode: create local service stack with shared SQLite
110
+ env.push({ name: "MACRO_INSTANCE_ID", value: eventStore.instanceId }, { name: "MACRO_BASE_DIR", value: eventStore.baseDir });
111
+ }
112
+ return {
113
+ name: "macro-agent",
114
+ command: "npx",
115
+ args: ["multiagent-mcp"],
116
+ env,
117
+ };
118
+ }
60
119
  // ─────────────────────────────────────────────────────────────────
61
120
  // Lifecycle
62
121
  // ─────────────────────────────────────────────────────────────────
63
122
  async function spawn(rawOptions) {
123
+ if (isShuttingDown) {
124
+ throw new AgentManagerError("Cannot spawn agent during shutdown", "SHUTDOWN_IN_PROGRESS");
125
+ }
64
126
  // Apply spawn interceptor if set (used by TeamRuntime for team context injection)
65
127
  const options = spawnInterceptor
66
128
  ? await spawnInterceptor(rawOptions)
67
129
  : rawOptions;
68
130
  const { task, task_id, parent, cwd = defaultCwd, permissionMode = defaultPermissionMode, subscribeParent = true, topics = [], config: agentConfig, agentType = defaultAgentType, customPrompt, interactionPatterns,
69
131
  // Workspace-related fields (Phase 2)
70
- role, streamId, streamConfig, dataplaneTaskId, } = options;
132
+ role, team_instance, streamId, streamConfig, dataplaneTaskId, capabilities, } = options;
71
133
  // Generate IDs upfront (including session_id so we can persist before starting MCP)
72
134
  const agentId = `agent_${nanoid(12)}`;
73
135
  const taskId = task_id ?? `task_${nanoid(12)}`;
@@ -140,10 +202,18 @@ export function createAgentManager(eventStore, messageRouter, config = {}) {
140
202
  task_id: taskId,
141
203
  parent: parent ?? null,
142
204
  role: role ?? undefined,
205
+ team_instance: team_instance ?? undefined,
143
206
  config: agentConfig ?? {},
144
207
  cwd,
145
208
  },
146
209
  });
210
+ // Generate a human-readable default name
211
+ const generatedName = uniqueNamesGenerator({
212
+ dictionaries: [adjectives, animals],
213
+ separator: "-",
214
+ length: 2,
215
+ });
216
+ eventStore.updateAgentMetadata(agentId, { name: generatedName });
147
217
  // Persist immediately so MCP server subprocess can read the agent
148
218
  await eventStore.persist();
149
219
  // Verify the agent is now in the store
@@ -157,162 +227,204 @@ export function createAgentManager(eventStore, messageRouter, config = {}) {
157
227
  permissionMode,
158
228
  env: agentConfig?.env,
159
229
  });
160
- // Build MCP server configuration for the macro-agent MCP server
161
- // Note: McpServerStdio doesn't have a 'type' field - stdio is the implicit default
162
- // when neither 'type: http' nor 'type: sse' is specified
163
- const macroAgentMcp = {
164
- name: "macro-agent",
165
- command: "npx",
166
- args: ["multiagent-mcp"],
167
- env: [
168
- { name: "MACRO_AGENT_ID", value: agentId },
169
- { name: "MACRO_PARENT_ID", value: parent ?? "" },
170
- { name: "MACRO_TASK_ID", value: taskId },
171
- { name: "MACRO_AGENT_CWD", value: cwd },
172
- { name: "MACRO_INSTANCE_ID", value: eventStore.instanceId },
173
- { name: "MACRO_BASE_DIR", value: eventStore.baseDir },
174
- ],
175
- };
176
- // Combine with any user-provided MCP servers
177
- // Note: Like macroAgentMcp, user MCP servers use stdio (no 'type' field)
178
- const userMcpServers = agentConfig?.mcpServers?.map((s) => ({
179
- name: s.name,
180
- command: s.command,
181
- args: s.args ?? [],
182
- env: s.env
183
- ? Object.entries(s.env).map(([name, value]) => ({ name, value }))
184
- : [],
185
- })) ?? [];
186
- // Create session with MCP servers
187
- // Note: The MCP server subprocess will start here and look for the agent
188
- // in EventStore. We already persisted the spawn event above.
189
- const session = await handle.createSession(cwd, {
190
- mcpServers: [macroAgentMcp, ...userMcpServers],
191
- });
192
- // Emit started status (session is ready)
193
- // Include the provider's session ID (e.g., Claude Code UUID) so
194
- // it can be used for handle.loadSession() during resume
195
- eventStore.emit({
196
- type: "status",
197
- source: { agent_id: agentId },
198
- payload: {
199
- status_type: "started",
200
- summary: "Agent session started",
201
- provider_session_id: session.id,
202
- },
203
- });
204
- // Persist the status event
205
- await eventStore.persist();
206
- // Set up default subscriptions via MessageRouter
207
- messageRouter.setupDefaultSubscriptions({
208
- agent_id: agentId,
209
- parent_id: parent ?? undefined,
210
- task_id: taskId,
211
- subscribe_parent: subscribeParent,
212
- additional_topics: topics,
213
- role: role ?? undefined,
214
- });
215
- // ─────────────────────────────────────────────────────────────────
216
- // Mail: Create task conversation for this agent
217
- // ─────────────────────────────────────────────────────────────────
218
- if (mailService && conversationMap) {
219
- try {
220
- const parentConversationId = parent
221
- ? conversationMap.getAgentConversation(parent) ??
222
- conversationMap.getSessionConversation(parent)
223
- : undefined;
224
- const { conversationId: taskConvId } = mailService.createConversation({
225
- type: "task",
226
- subject: task?.slice(0, 80),
227
- createdBy: parent ?? agentId,
228
- parentConversationId: parentConversationId,
229
- });
230
- // Join parent and child as participants
231
- if (parent) {
230
+ try {
231
+ // ─────────────────────────────────────────────────────────────────
232
+ // Workspace Creation (before session, so cwd reflects worktree)
233
+ // ─────────────────────────────────────────────────────────────────
234
+ let workspace;
235
+ let resolvedStreamId = streamId;
236
+ if (workspaceManager && role) {
237
+ try {
238
+ workspace = await createWorkspaceForRole(workspaceManager, agentId, role, {
239
+ streamId,
240
+ streamConfig,
241
+ dataplaneTaskId,
242
+ capabilities,
243
+ cwd,
244
+ });
245
+ if (workspace) {
246
+ agentWorkspaces.set(agentId, workspace);
247
+ resolvedStreamId = workspace.streamId;
248
+ // Create and claim a dataplane task so the worktree gets a real
249
+ // worker branch. Without this, the worktree stays in detached
250
+ // HEAD and done() would detect "HEAD" instead of the actual
251
+ // worker branch name (e.g. worker/<agentId>/<taskId>).
252
+ if (workspace.role === "worker" && workspace.streamId) {
253
+ try {
254
+ const dpTaskId = workspaceManager.createTask(workspace.streamId, { title: task ?? `Task for ${agentId}` });
255
+ workspaceManager.claimTask(dpTaskId, agentId, workspace.path);
256
+ }
257
+ catch (claimErr) {
258
+ console.error(`[AgentManager] Failed to create/claim dataplane task for ${agentId}:`, claimErr);
259
+ // Continue without a branch — worktree stays in detached HEAD
260
+ }
261
+ }
262
+ // Register with parent coordinator if applicable
263
+ const isChildRole = role === "worker" || role === "integrator" ||
264
+ (capabilities && (capabilities.includes("workspace.worktree") || capabilities.includes("workspace.integrate")));
265
+ if (parent && isChildRole) {
266
+ const parentWorkspace = agentWorkspaces.get(parent);
267
+ if (parentWorkspace?.role === "coordinator") {
268
+ workspaceManager.registerChildWorkspace(parent, agentId, workspace.path);
269
+ }
270
+ }
271
+ }
272
+ }
273
+ catch (wsError) {
274
+ console.error(`[AgentManager] Failed to create workspace for ${agentId}: ${wsError}`);
275
+ // Continue without workspace — don't fail the spawn
276
+ }
277
+ }
278
+ // Use workspace path as the agent's working directory when available.
279
+ // This ensures the agent process, MCP subprocess (MACRO_AGENT_CWD), and
280
+ // done handler all use the worktree path instead of the repo root.
281
+ const effectiveCwd = workspace?.path ?? cwd;
282
+ // Update agent's cwd in EventStore so resume() also uses workspace path
283
+ if (workspace) {
284
+ eventStore.updateAgentMetadata(agentId, { cwd: effectiveCwd });
285
+ await eventStore.persist();
286
+ }
287
+ const macroAgentMcp = buildMacroAgentMcp({
288
+ agentId,
289
+ parentId: parent ?? "",
290
+ taskId,
291
+ cwd: effectiveCwd,
292
+ permissionMode,
293
+ lineage: parentAgent?.lineage
294
+ ? [...parentAgent.lineage, parent]
295
+ : [],
296
+ sessionId,
297
+ streamId,
298
+ });
299
+ // Combine with any user-provided MCP servers
300
+ // Note: Like macroAgentMcp, user MCP servers use stdio (no 'type' field)
301
+ const userMcpServers = agentConfig?.mcpServers?.map((s) => ({
302
+ name: s.name,
303
+ command: s.command,
304
+ args: s.args ?? [],
305
+ env: s.env
306
+ ? Object.entries(s.env).map(([name, value]) => ({ name, value }))
307
+ : [],
308
+ })) ?? [];
309
+ // Create session with MCP servers
310
+ // Note: The MCP server subprocess will start here and look for the agent
311
+ // in EventStore. We already persisted the spawn event above.
312
+ //
313
+ // When permissionMode is "interactive", we strip settingSources so that
314
+ // the Claude Code subprocess doesn't read pre-approved tool rules from
315
+ // the user's ~/.claude/settings.local.json. This ensures ALL tool calls
316
+ // go through the canUseTool → requestPermission ACP flow.
317
+ const agentMeta = permissionMode === "interactive"
318
+ ? { claudeCode: { options: { settingSources: [] } } }
319
+ : undefined;
320
+ const session = await handle.createSession(effectiveCwd, {
321
+ mcpServers: [macroAgentMcp, ...userMcpServers],
322
+ ...(agentMeta && { agentMeta }),
323
+ });
324
+ // Emit started status (session is ready)
325
+ // Include the provider's session ID (e.g., Claude Code UUID) so
326
+ // it can be used for handle.loadSession() during resume
327
+ eventStore.emit({
328
+ type: "status",
329
+ source: { agent_id: agentId },
330
+ payload: {
331
+ status_type: "started",
332
+ summary: "Agent session started",
333
+ provider_session_id: session.id,
334
+ },
335
+ });
336
+ // Persist the status event
337
+ await eventStore.persist();
338
+ // Set up default subscriptions via MessageRouter
339
+ messageRouter.setupDefaultSubscriptions({
340
+ agent_id: agentId,
341
+ parent_id: parent ?? undefined,
342
+ task_id: taskId,
343
+ subscribe_parent: subscribeParent,
344
+ additional_topics: topics,
345
+ role: role ?? undefined,
346
+ });
347
+ // ─────────────────────────────────────────────────────────────────
348
+ // Mail: Create task conversation for this agent
349
+ // ─────────────────────────────────────────────────────────────────
350
+ if (mailService && conversationMap) {
351
+ try {
352
+ const parentConversationId = parent
353
+ ? (conversationMap.getAgentConversation(parent) ??
354
+ conversationMap.getSessionConversation(parent))
355
+ : undefined;
356
+ const { conversationId: taskConvId } = mailService.createConversation({
357
+ type: "task",
358
+ subject: task?.slice(0, 80),
359
+ createdBy: parent ?? agentId,
360
+ parentConversationId: parentConversationId,
361
+ });
362
+ // Join parent and child as participants
363
+ if (parent) {
364
+ mailService.joinConversation({
365
+ conversationId: taskConvId,
366
+ participantId: parent,
367
+ participantType: "agent",
368
+ role: "initiator",
369
+ agentId: parent,
370
+ });
371
+ }
232
372
  mailService.joinConversation({
233
373
  conversationId: taskConvId,
234
- participantId: parent,
374
+ participantId: agentId,
235
375
  participantType: "agent",
236
- role: "initiator",
237
- agentId: parent,
376
+ role: "worker",
377
+ agentId,
238
378
  });
379
+ conversationMap.setAgentConversation(agentId, taskConvId);
380
+ }
381
+ catch (err) {
382
+ // Never fail spawn due to mail errors
383
+ console.warn(`[AgentManager] Failed to create task conversation for ${agentId}:`, err);
239
384
  }
240
- mailService.joinConversation({
241
- conversationId: taskConvId,
242
- participantId: agentId,
243
- participantType: "agent",
244
- role: "worker",
245
- agentId,
246
- });
247
- conversationMap.setAgentConversation(agentId, taskConvId);
248
385
  }
249
- catch (err) {
250
- // Never fail spawn due to mail errors
251
- console.warn(`[AgentManager] Failed to create task conversation for ${agentId}:`, err);
386
+ // Track active session
387
+ const activeSession = {
388
+ agentId,
389
+ handle,
390
+ session,
391
+ createdAt: Date.now(),
392
+ isPrompting: false,
393
+ };
394
+ activeSessions.set(agentId, activeSession);
395
+ // Get the agent from materialized view
396
+ const agent = eventStore.getAgent(agentId);
397
+ // Notify lifecycle listeners
398
+ notifyLifecycle({ type: "spawned", agent });
399
+ notifyLifecycle({ type: "started", agent });
400
+ // Start health monitoring for coordinators
401
+ if (healthCheckService && role === "coordinator") {
402
+ healthCheckService.startForCoordinator(agentId);
252
403
  }
404
+ return {
405
+ id: agentId,
406
+ session_id: sessionId, // Macro-agent's own session ID for ACP protocol mapping
407
+ agent,
408
+ session,
409
+ workspace,
410
+ streamId: resolvedStreamId,
411
+ };
253
412
  }
254
- // Track active session
255
- const activeSession = {
256
- agentId,
257
- handle,
258
- session,
259
- createdAt: Date.now(),
260
- isPrompting: false,
261
- };
262
- activeSessions.set(agentId, activeSession);
263
- // Get the agent from materialized view
264
- const agent = eventStore.getAgent(agentId);
265
- // ─────────────────────────────────────────────────────────────────
266
- // Workspace Creation (Phase 2)
267
- // ─────────────────────────────────────────────────────────────────
268
- let workspace;
269
- let resolvedStreamId = streamId;
270
- if (workspaceManager && role) {
413
+ catch (handleError) {
414
+ // Close the spawned process to prevent orphaning
271
415
  try {
272
- workspace = await createWorkspaceForRole(workspaceManager, agentId, role, {
273
- streamId,
274
- streamConfig,
275
- dataplaneTaskId,
276
- cwd,
277
- });
278
- if (workspace) {
279
- agentWorkspaces.set(agentId, workspace);
280
- resolvedStreamId = workspace.streamId;
281
- // Register with parent coordinator if applicable
282
- if (parent &&
283
- (role === "worker" || role === "integrator")) {
284
- const parentWorkspace = agentWorkspaces.get(parent);
285
- if (parentWorkspace?.role === "coordinator") {
286
- workspaceManager.registerChildWorkspace(parent, agentId, workspace.path);
287
- }
288
- }
289
- }
416
+ await handle.close();
290
417
  }
291
- catch (wsError) {
292
- console.error(`[AgentManager] Failed to create workspace for ${agentId}: ${wsError}`);
293
- // Continue without workspace - don't fail the spawn
418
+ catch {
419
+ // Ignore errors during cleanup
294
420
  }
421
+ throw handleError;
295
422
  }
296
- // Notify lifecycle listeners
297
- notifyLifecycle({ type: "spawned", agent });
298
- notifyLifecycle({ type: "started", agent });
299
- // Start health monitoring for coordinators
300
- if (healthCheckService && role === "coordinator") {
301
- healthCheckService.startForCoordinator(agentId);
302
- }
303
- return {
304
- id: agentId,
305
- session_id: sessionId, // Macro-agent's own session ID for ACP protocol mapping
306
- agent,
307
- session,
308
- workspace,
309
- streamId: resolvedStreamId,
310
- };
311
423
  }
312
424
  catch (error) {
313
425
  // Clean up the spawn event we already emitted
314
426
  eventStore.emit({
315
- type: "terminate",
427
+ type: "stop",
316
428
  source: { agent_id: agentId },
317
429
  payload: {
318
430
  reason: "failed",
@@ -355,6 +467,10 @@ export function createAgentManager(eventStore, messageRouter, config = {}) {
355
467
  // Continue with termination even if workspace cleanup fails
356
468
  }
357
469
  }
470
+ // Revoke agent authentication token
471
+ if (agentTokenManager) {
472
+ agentTokenManager.revokeToken(agentId);
473
+ }
358
474
  // ─────────────────────────────────────────────────────────────────
359
475
  // Mail: Close task conversation on terminate
360
476
  // ─────────────────────────────────────────────────────────────────
@@ -383,9 +499,9 @@ export function createAgentManager(eventStore, messageRouter, config = {}) {
383
499
  console.warn(`[AgentManager] Failed to close conversation for ${agentId}:`, err);
384
500
  }
385
501
  }
386
- // Emit terminate event
502
+ // Emit stop event
387
503
  eventStore.emit({
388
- type: "terminate",
504
+ type: "stop",
389
505
  source: { agent_id: agentId },
390
506
  payload: {
391
507
  agent_id: agentId,
@@ -442,7 +558,10 @@ export function createAgentManager(eventStore, messageRouter, config = {}) {
442
558
  }
443
559
  }
444
560
  }
445
- async function resume(agentId) {
561
+ async function resume(agentId, overridePermissionMode) {
562
+ if (isShuttingDown) {
563
+ throw new AgentManagerError("Cannot resume agent during shutdown", "SHUTDOWN_IN_PROGRESS", agentId);
564
+ }
446
565
  const agent = eventStore.getAgent(agentId);
447
566
  if (!agent) {
448
567
  throw new AgentManagerError(`Agent not found: ${agentId}`, "AGENT_NOT_FOUND", agentId);
@@ -451,57 +570,217 @@ export function createAgentManager(eventStore, messageRouter, config = {}) {
451
570
  if (activeSessions.has(agentId)) {
452
571
  throw new AgentManagerError(`Agent already has active session: ${agentId}`, "ALREADY_RUNNING", agentId);
453
572
  }
573
+ const permissionMode = overridePermissionMode ?? defaultPermissionMode;
454
574
  // Spawn new process
455
575
  const handle = await AgentFactory.spawn(defaultAgentType, {
456
- permissionMode: defaultPermissionMode,
576
+ permissionMode,
457
577
  });
458
- const agentCwd = agent.cwd ?? defaultCwd;
459
- let session;
460
- if (agent.provider_session_id) {
461
- // Load existing session using the provider's session ID (e.g., Claude Code UUID)
462
- session = await handle.loadSession(agent.provider_session_id, agentCwd);
463
- }
464
- else {
465
- // No provider session ID available (agent predates this feature or wasn't persisted).
466
- // Create a new session instead of loading with the macro-agent session_id
467
- // which is not a valid provider session ID (e.g., Claude Code expects UUIDs).
468
- session = await handle.createSession(agentCwd);
469
- // Store the provider session ID for future resumes
578
+ try {
579
+ const agentCwd = agent.cwd ?? defaultCwd;
580
+ let session;
581
+ // When interactive mode, strip settings to prevent auto-approval
582
+ const resumeAgentMeta = permissionMode === "interactive"
583
+ ? { claudeCode: { options: { settingSources: [] } } }
584
+ : undefined;
585
+ const macroAgentMcp = buildMacroAgentMcp({
586
+ agentId,
587
+ parentId: agent.parent ?? "",
588
+ taskId: agent.task_id ?? "",
589
+ cwd: agentCwd,
590
+ permissionMode,
591
+ lineage: agent.lineage ?? [],
592
+ sessionId: agent.session_id ?? "",
593
+ });
594
+ const mcpServers = [macroAgentMcp];
595
+ if (agent.provider_session_id) {
596
+ // Load existing session using the provider's session ID (e.g., Claude Code UUID)
597
+ // Note: loadSession's TS type for mcpServers is { name, uri }[] but
598
+ // the underlying ACP protocol accepts full McpServerStdio. The JS
599
+ // implementation passes mcpServers through to the connection unchanged.
600
+ session = await handle.loadSession(agent.provider_session_id, agentCwd, mcpServers, resumeAgentMeta ? { agentMeta: resumeAgentMeta } : undefined);
601
+ }
602
+ else {
603
+ // No provider session ID available (agent predates this feature or wasn't persisted).
604
+ // Create a new session instead of loading with the macro-agent session_id
605
+ // which is not a valid provider session ID (e.g., Claude Code expects UUIDs).
606
+ session = await handle.createSession(agentCwd, {
607
+ mcpServers,
608
+ ...(resumeAgentMeta && { agentMeta: resumeAgentMeta }),
609
+ });
610
+ // Store the provider session ID for future resumes
611
+ eventStore.emit({
612
+ type: "status",
613
+ source: { agent_id: agentId },
614
+ payload: {
615
+ status_type: "started",
616
+ summary: "Agent session created (no provider session to resume)",
617
+ provider_session_id: session.id,
618
+ },
619
+ });
620
+ }
621
+ // Track active session
622
+ const activeSession = {
623
+ agentId,
624
+ handle,
625
+ session,
626
+ createdAt: Date.now(),
627
+ isPrompting: false,
628
+ };
629
+ activeSessions.set(agentId, activeSession);
630
+ // Emit status event for resume
470
631
  eventStore.emit({
471
632
  type: "status",
472
633
  source: { agent_id: agentId },
473
634
  payload: {
474
635
  status_type: "started",
475
- summary: "Agent session created (no provider session to resume)",
636
+ summary: "Agent session resumed",
476
637
  provider_session_id: session.id,
477
638
  },
478
639
  });
640
+ return {
641
+ id: agentId,
642
+ session_id: agent.session_id, // Macro-agent's own session ID
643
+ agent: eventStore.getAgent(agentId),
644
+ session,
645
+ };
479
646
  }
480
- // Track active session
481
- const activeSession = {
482
- agentId,
483
- handle,
484
- session,
485
- createdAt: Date.now(),
486
- isPrompting: false,
487
- };
488
- activeSessions.set(agentId, activeSession);
489
- // Emit status event for resume
647
+ catch (handleError) {
648
+ // Close the spawned process to prevent orphaning
649
+ try {
650
+ await handle.close();
651
+ }
652
+ catch {
653
+ // Ignore errors during cleanup
654
+ }
655
+ throw handleError;
656
+ }
657
+ }
658
+ // ─────────────────────────────────────────────────────────────────
659
+ // Fork
660
+ // ─────────────────────────────────────────────────────────────────
661
+ async function forkAgent(sourceAgentId, options) {
662
+ if (isShuttingDown) {
663
+ throw new AgentManagerError("Cannot fork agent during shutdown", "SHUTDOWN_IN_PROGRESS", sourceAgentId);
664
+ }
665
+ const sourceAgent = eventStore.getAgent(sourceAgentId);
666
+ if (!sourceAgent) {
667
+ throw new AgentManagerError(`Agent not found: ${sourceAgentId}`, "AGENT_NOT_FOUND", sourceAgentId);
668
+ }
669
+ // Need either an active session or a persisted provider_session_id
670
+ const activeSession = activeSessions.get(sourceAgentId);
671
+ if (!activeSession && !sourceAgent.provider_session_id) {
672
+ throw new AgentManagerError(`Agent has no session to fork: ${sourceAgentId}`, "FORK_NOT_SUPPORTED", sourceAgentId);
673
+ }
674
+ // Generate new IDs
675
+ const agentId = `agent_${nanoid(12)}`;
676
+ const taskId = `task_${nanoid(12)}`;
677
+ const sessionId = `session_${nanoid(12)}`;
678
+ const cwd = options?.cwd ?? sourceAgent.cwd ?? defaultCwd;
679
+ // Emit spawn event with fork metadata
490
680
  eventStore.emit({
491
- type: "status",
492
- source: { agent_id: agentId },
681
+ type: "spawn",
682
+ source: { agent_id: sourceAgentId },
493
683
  payload: {
494
- status_type: "started",
495
- summary: "Agent session resumed",
496
- provider_session_id: session.id,
684
+ agent_id: agentId,
685
+ session_id: sessionId,
686
+ task: options?.name ?? `[Fork of ${sourceAgentId}]`,
687
+ task_id: taskId,
688
+ parent: sourceAgent.parent ?? null,
689
+ role: sourceAgent.role ?? undefined,
690
+ team_instance: sourceAgent.team_instance ?? undefined,
691
+ config: {},
692
+ cwd,
693
+ metadata: { fork_of: sourceAgentId },
497
694
  },
498
695
  });
499
- return {
500
- id: agentId,
501
- session_id: agent.session_id, // Macro-agent's own session ID
502
- agent: eventStore.getAgent(agentId),
503
- session,
504
- };
696
+ // Generate a human-readable name
697
+ const generatedName = uniqueNamesGenerator({
698
+ dictionaries: [adjectives, animals],
699
+ separator: "-",
700
+ length: 2,
701
+ });
702
+ eventStore.updateAgentMetadata(agentId, { name: generatedName });
703
+ await eventStore.persist();
704
+ // Get the provider session ID to fork from
705
+ let forkedProviderSessionId;
706
+ if (activeSession) {
707
+ // Active session: fork with flush to ensure data is persisted
708
+ const forkedSession = await activeSession.session.forkWithFlush();
709
+ forkedProviderSessionId = forkedSession.id;
710
+ }
711
+ else {
712
+ // Stopped agent: use the persisted provider session ID directly
713
+ forkedProviderSessionId = sourceAgent.provider_session_id;
714
+ }
715
+ // Spawn a new process
716
+ const handle = await AgentFactory.spawn(defaultAgentType, {
717
+ permissionMode: defaultPermissionMode,
718
+ });
719
+ try {
720
+ const macroAgentMcp = buildMacroAgentMcp({
721
+ agentId,
722
+ parentId: sourceAgent.parent ?? "",
723
+ taskId,
724
+ cwd,
725
+ permissionMode: defaultPermissionMode,
726
+ lineage: sourceAgent.lineage ?? [],
727
+ sessionId,
728
+ });
729
+ // Load the forked session on the new process with correct MCP config.
730
+ // Note: loadSession's TS type for mcpServers is { name, uri }[] but
731
+ // the underlying ACP protocol accepts full McpServerStdio. The JS
732
+ // implementation passes mcpServers through to the connection unchanged.
733
+ const session = await handle.loadSession(forkedProviderSessionId, cwd, [
734
+ macroAgentMcp,
735
+ ]);
736
+ // Emit started status with provider session ID
737
+ eventStore.emit({
738
+ type: "status",
739
+ source: { agent_id: agentId },
740
+ payload: {
741
+ status_type: "started",
742
+ summary: "Agent session started (forked)",
743
+ provider_session_id: session.id,
744
+ },
745
+ });
746
+ await eventStore.persist();
747
+ // Set up message router subscriptions
748
+ messageRouter.setupDefaultSubscriptions({
749
+ agent_id: agentId,
750
+ parent_id: sourceAgent.parent ?? undefined,
751
+ task_id: taskId,
752
+ subscribe_parent: false,
753
+ additional_topics: [],
754
+ role: sourceAgent.role ?? undefined,
755
+ });
756
+ // Track active session
757
+ const newActiveSession = {
758
+ agentId,
759
+ handle,
760
+ session,
761
+ createdAt: Date.now(),
762
+ isPrompting: false,
763
+ };
764
+ activeSessions.set(agentId, newActiveSession);
765
+ const agent = eventStore.getAgent(agentId);
766
+ notifyLifecycle({ type: "spawned", agent });
767
+ notifyLifecycle({ type: "started", agent });
768
+ return {
769
+ id: agentId,
770
+ session_id: sessionId,
771
+ agent,
772
+ session,
773
+ };
774
+ }
775
+ catch (handleError) {
776
+ try {
777
+ await handle.close();
778
+ }
779
+ catch {
780
+ // Ignore errors during cleanup
781
+ }
782
+ throw handleError;
783
+ }
505
784
  }
506
785
  // ─────────────────────────────────────────────────────────────────
507
786
  // Queries
@@ -654,11 +933,12 @@ export function createAgentManager(eventStore, messageRouter, config = {}) {
654
933
  const agentCompletedStatus = statusEvents.find((e) => e.source?.agent_id === agentId &&
655
934
  (e.payload?.status_type === "completed" ||
656
935
  e.payload?.status_type === "failed" ||
657
- e.payload?.details?.signal === "WORKER_DONE"));
936
+ e.payload?.details?.signal ===
937
+ "WORKER_DONE"));
658
938
  if (agentCompletedStatus) {
659
939
  return {
660
940
  called: true,
661
- status: agentCompletedStatus.payload?.status_type
941
+ status: agentCompletedStatus.payload?.status_type,
662
942
  };
663
943
  }
664
944
  return { called: false };
@@ -789,6 +1069,29 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
789
1069
  return false;
790
1070
  }
791
1071
  }
1072
+ function setPermissionMode(agentId, mode) {
1073
+ const activeSession = activeSessions.get(agentId);
1074
+ if (!activeSession) {
1075
+ console.warn(`[AgentManager] Cannot set permission mode: no active session for agent ${agentId}`);
1076
+ return false;
1077
+ }
1078
+ try {
1079
+ activeSession.handle.setPermissionMode(mode);
1080
+ console.log(`[AgentManager] Set permission mode for agent ${agentId} to ${mode}`);
1081
+ return true;
1082
+ }
1083
+ catch (err) {
1084
+ console.error(`[AgentManager] Error setting permission mode for agent ${agentId}:`, err);
1085
+ return false;
1086
+ }
1087
+ }
1088
+ function getPermissionMode(agentId) {
1089
+ const activeSession = activeSessions.get(agentId);
1090
+ if (!activeSession) {
1091
+ return null;
1092
+ }
1093
+ return activeSession.handle.getPermissionMode();
1094
+ }
792
1095
  // ─────────────────────────────────────────────────────────────────
793
1096
  // Lifecycle Callbacks
794
1097
  // ─────────────────────────────────────────────────────────────────
@@ -807,6 +1110,12 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
807
1110
  }
808
1111
  }
809
1112
  // ─────────────────────────────────────────────────────────────────
1113
+ // OpenTasks Socket Path (Late Binding)
1114
+ // ─────────────────────────────────────────────────────────────────
1115
+ function setOpenTasksSocketPath(socketPath) {
1116
+ configOpenTasksSocketPath = socketPath;
1117
+ }
1118
+ // ─────────────────────────────────────────────────────────────────
810
1119
  // Mail Services (Late Binding)
811
1120
  // ─────────────────────────────────────────────────────────────────
812
1121
  function setMailServices(ms, cm) {
@@ -817,6 +1126,8 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
817
1126
  // Cleanup
818
1127
  // ─────────────────────────────────────────────────────────────────
819
1128
  async function close() {
1129
+ // Prevent new spawns/resumes from racing with cleanup
1130
+ isShuttingDown = true;
820
1131
  // Stop all health checks
821
1132
  if (healthCheckService) {
822
1133
  healthCheckService.stopAll();
@@ -876,9 +1187,7 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
876
1187
  }
877
1188
  const resumeContext = contextLines.join("\n");
878
1189
  // Spawn a continuation agent with same role, task, and context
879
- const taskDescription = options?.task ??
880
- agent.task ??
881
- `Continue work from ${agentId}`;
1190
+ const taskDescription = options?.task ?? agent.task ?? `Continue work from ${agentId}`;
882
1191
  const newAgent = await spawn({
883
1192
  task: taskDescription,
884
1193
  role: agent.role,
@@ -903,6 +1212,7 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
903
1212
  terminate,
904
1213
  resume,
905
1214
  continueAgent,
1215
+ forkAgent,
906
1216
  get,
907
1217
  list,
908
1218
  getChildren,
@@ -918,27 +1228,70 @@ Call done() NOW with status "completed" if your work is finished, or "blocked" i
918
1228
  isProcessRunning,
919
1229
  respondToPermission,
920
1230
  cancelPermission,
1231
+ setPermissionMode,
1232
+ getPermissionMode,
921
1233
  onLifecycleEvent,
922
1234
  setSpawnInterceptor,
923
1235
  getRoleRegistry,
1236
+ setOpenTasksSocketPath,
924
1237
  setMailServices,
925
1238
  close,
926
1239
  };
927
1240
  }
928
1241
  /**
929
- * Create a workspace for an agent based on their role.
1242
+ * Create a workspace for an agent based on their capabilities.
1243
+ *
1244
+ * Dispatches on workspace capabilities (workspace.stream, workspace.integrate,
1245
+ * workspace.worktree) rather than role names. This allows team-defined roles
1246
+ * (e.g., "developer" extending "worker") to get proper workspace allocation
1247
+ * by inheriting workspace capabilities from their base role.
1248
+ *
1249
+ * Falls back to role-name matching for backward compatibility when no
1250
+ * capabilities are provided.
930
1251
  *
931
1252
  * @param workspaceManager - WorkspaceManager instance
932
1253
  * @param agentId - Agent ID
933
- * @param role - Agent role (e.g., 'worker', 'coordinator', 'integrator')
934
- * @param options - Additional options
1254
+ * @param role - Agent role name (used for logging and fallback)
1255
+ * @param options - Workspace options including capabilities
935
1256
  * @returns Created workspace or undefined
936
1257
  */
937
1258
  async function createWorkspaceForRole(workspaceManager, agentId, role, options) {
938
- const { streamId, streamConfig, dataplaneTaskId } = options;
1259
+ const { streamId, streamConfig, dataplaneTaskId, capabilities } = options;
1260
+ // Capability-based dispatch (preferred — works for team-defined roles)
1261
+ if (capabilities && capabilities.length > 0) {
1262
+ if (capabilities.includes("workspace.stream")) {
1263
+ // Coordinator pattern: create integration stream.
1264
+ // In team mode, stream is managed by TeamRuntime.setupWorkspaceIntegration(),
1265
+ // so missing streamConfig is expected — return silently.
1266
+ if (!streamConfig) {
1267
+ return undefined;
1268
+ }
1269
+ const newStreamId = workspaceManager.createIntegrationStream(agentId, streamConfig);
1270
+ return workspaceManager.createCoordinatorWorkspace(agentId, newStreamId);
1271
+ }
1272
+ else if (capabilities.includes("workspace.integrate")) {
1273
+ // Integrator pattern: join existing stream
1274
+ if (!streamId) {
1275
+ console.warn(`[AgentManager] ${role} ${agentId} has workspace.integrate but no streamId, skipping workspace`);
1276
+ return undefined;
1277
+ }
1278
+ return workspaceManager.createIntegratorWorkspace(agentId, streamId);
1279
+ }
1280
+ else if (capabilities.includes("workspace.worktree")) {
1281
+ // Worker pattern: create worktree in stream
1282
+ if (!streamId) {
1283
+ console.warn(`[AgentManager] ${role} ${agentId} has workspace.worktree but no streamId, skipping workspace`);
1284
+ return undefined;
1285
+ }
1286
+ const taskId = dataplaneTaskId ?? agentId;
1287
+ return workspaceManager.createWorkerWorkspace(agentId, taskId, streamId);
1288
+ }
1289
+ // Has capabilities but no workspace capability — no workspace needed
1290
+ return undefined;
1291
+ }
1292
+ // Fallback: role-name dispatch (backward compatibility for non-team spawns)
939
1293
  switch (role) {
940
1294
  case "coordinator": {
941
- // Coordinators create a new integration stream
942
1295
  if (!streamConfig) {
943
1296
  console.warn(`[AgentManager] Coordinator ${agentId} spawn missing streamConfig, skipping workspace`);
944
1297
  return undefined;
@@ -947,7 +1300,6 @@ async function createWorkspaceForRole(workspaceManager, agentId, role, options)
947
1300
  return workspaceManager.createCoordinatorWorkspace(agentId, newStreamId);
948
1301
  }
949
1302
  case "integrator": {
950
- // Integrators join an existing stream
951
1303
  if (!streamId) {
952
1304
  console.warn(`[AgentManager] Integrator ${agentId} spawn missing streamId, skipping workspace`);
953
1305
  return undefined;
@@ -956,24 +1308,16 @@ async function createWorkspaceForRole(workspaceManager, agentId, role, options)
956
1308
  }
957
1309
  case "worker":
958
1310
  case "worker.resolver": {
959
- // Workers need streamId and either dataplaneTaskId or create a new task
960
1311
  if (!streamId) {
961
1312
  console.warn(`[AgentManager] Worker ${agentId} spawn missing streamId, skipping workspace`);
962
1313
  return undefined;
963
1314
  }
964
- // Use provided task ID or skip (task should be created separately)
965
- const taskId = dataplaneTaskId;
966
- if (!taskId) {
967
- console.warn(`[AgentManager] Worker ${agentId} spawn missing dataplaneTaskId, skipping workspace`);
968
- return undefined;
969
- }
1315
+ const taskId = dataplaneTaskId ?? agentId;
970
1316
  return workspaceManager.createWorkerWorkspace(agentId, taskId, streamId);
971
1317
  }
972
1318
  case "monitor":
973
- // Monitors don't need workspaces
974
1319
  return undefined;
975
1320
  default:
976
- // Unknown role - no workspace
977
1321
  return undefined;
978
1322
  }
979
1323
  }