macro-agent 0.2.5 → 0.2.6

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 (992) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +30 -56
  3. package/dist/acp/websocket-server.d.ts +6 -0
  4. package/dist/acp/websocket-server.d.ts.map +1 -1
  5. package/dist/acp/websocket-server.js +13 -0
  6. package/dist/acp/websocket-server.js.map +1 -1
  7. package/dist/acp/websocket-stream.d.ts +30 -0
  8. package/dist/acp/websocket-stream.d.ts.map +1 -0
  9. package/dist/acp/websocket-stream.js +118 -0
  10. package/dist/acp/websocket-stream.js.map +1 -0
  11. package/dist/activity/deduplication.d.ts +85 -0
  12. package/dist/activity/deduplication.d.ts.map +1 -0
  13. package/dist/activity/deduplication.js +149 -0
  14. package/dist/activity/deduplication.js.map +1 -0
  15. package/dist/activity/index.d.ts +16 -0
  16. package/dist/activity/index.d.ts.map +1 -0
  17. package/dist/activity/index.js +17 -0
  18. package/dist/activity/index.js.map +1 -0
  19. package/dist/activity/relevance.d.ts +81 -0
  20. package/dist/activity/relevance.d.ts.map +1 -0
  21. package/dist/activity/relevance.js +161 -0
  22. package/dist/activity/relevance.js.map +1 -0
  23. package/dist/activity/types.d.ts +169 -0
  24. package/dist/activity/types.d.ts.map +1 -0
  25. package/dist/activity/types.js +33 -0
  26. package/dist/activity/types.js.map +1 -0
  27. package/dist/activity/watcher.d.ts +64 -0
  28. package/dist/activity/watcher.d.ts.map +1 -0
  29. package/dist/activity/watcher.js +212 -0
  30. package/dist/activity/watcher.js.map +1 -0
  31. package/dist/adapters/federation.d.ts +8 -1
  32. package/dist/adapters/federation.d.ts.map +1 -1
  33. package/dist/adapters/federation.js +33 -2
  34. package/dist/adapters/federation.js.map +1 -1
  35. package/dist/agent/agent-manager-v2.d.ts.map +1 -1
  36. package/dist/agent/agent-manager-v2.js +7 -24
  37. package/dist/agent/agent-manager-v2.js.map +1 -1
  38. package/dist/agent/wake.d.ts +85 -0
  39. package/dist/agent/wake.d.ts.map +1 -0
  40. package/dist/agent/wake.js +278 -0
  41. package/dist/agent/wake.js.map +1 -0
  42. package/dist/api/server.d.ts.map +1 -1
  43. package/dist/api/server.js +41 -25
  44. package/dist/api/server.js.map +1 -1
  45. package/dist/api/types.d.ts +6 -0
  46. package/dist/api/types.d.ts.map +1 -1
  47. package/dist/auth/server-auth.d.ts +43 -0
  48. package/dist/auth/server-auth.d.ts.map +1 -0
  49. package/dist/auth/server-auth.js +80 -0
  50. package/dist/auth/server-auth.js.map +1 -0
  51. package/dist/auth/token.d.ts +4 -0
  52. package/dist/auth/token.d.ts.map +1 -1
  53. package/dist/auth/token.js +7 -6
  54. package/dist/auth/token.js.map +1 -1
  55. package/dist/boot-v2.d.ts +6 -3
  56. package/dist/boot-v2.d.ts.map +1 -1
  57. package/dist/boot-v2.js +44 -25
  58. package/dist/boot-v2.js.map +1 -1
  59. package/dist/cognitive/team-lifecycle.d.ts +82 -0
  60. package/dist/cognitive/team-lifecycle.d.ts.map +1 -0
  61. package/dist/cognitive/team-lifecycle.js +121 -0
  62. package/dist/cognitive/team-lifecycle.js.map +1 -0
  63. package/dist/cognitive/trajectory-extractor.d.ts +25 -0
  64. package/dist/cognitive/trajectory-extractor.d.ts.map +1 -0
  65. package/dist/cognitive/trajectory-extractor.js +134 -0
  66. package/dist/cognitive/trajectory-extractor.js.map +1 -0
  67. package/dist/control/control-server.d.ts.map +1 -1
  68. package/dist/control/control-server.js +10 -0
  69. package/dist/control/control-server.js.map +1 -1
  70. package/dist/dispatch/mail-inbound-consumer.d.ts.map +1 -1
  71. package/dist/dispatch/mail-inbound-consumer.js +43 -10
  72. package/dist/dispatch/mail-inbound-consumer.js.map +1 -1
  73. package/dist/index.d.ts +4 -0
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +6 -1
  76. package/dist/index.js.map +1 -1
  77. package/dist/lifecycle/handlers/generic.d.ts +27 -0
  78. package/dist/lifecycle/handlers/generic.d.ts.map +1 -0
  79. package/dist/lifecycle/handlers/generic.js +56 -0
  80. package/dist/lifecycle/handlers/generic.js.map +1 -0
  81. package/dist/lifecycle/handlers/index.d.ts +51 -0
  82. package/dist/lifecycle/handlers/index.d.ts.map +1 -0
  83. package/dist/lifecycle/handlers/index.js +110 -0
  84. package/dist/lifecycle/handlers/index.js.map +1 -0
  85. package/dist/lifecycle/handlers/integrator.d.ts +81 -0
  86. package/dist/lifecycle/handlers/integrator.d.ts.map +1 -0
  87. package/dist/lifecycle/handlers/integrator.js +451 -0
  88. package/dist/lifecycle/handlers/integrator.js.map +1 -0
  89. package/dist/lifecycle/handlers/monitor.d.ts +29 -0
  90. package/dist/lifecycle/handlers/monitor.d.ts.map +1 -0
  91. package/dist/lifecycle/handlers/monitor.js +79 -0
  92. package/dist/lifecycle/handlers/monitor.js.map +1 -0
  93. package/dist/lifecycle/handlers/worker.d.ts +56 -0
  94. package/dist/lifecycle/handlers/worker.d.ts.map +1 -0
  95. package/dist/lifecycle/handlers/worker.js +381 -0
  96. package/dist/lifecycle/handlers/worker.js.map +1 -0
  97. package/dist/lifecycle/handlers-v2.d.ts +0 -2
  98. package/dist/lifecycle/handlers-v2.d.ts.map +1 -1
  99. package/dist/lifecycle/handlers-v2.js +4 -55
  100. package/dist/lifecycle/handlers-v2.js.map +1 -1
  101. package/dist/mail/conversation-map.d.ts +33 -0
  102. package/dist/mail/conversation-map.d.ts.map +1 -0
  103. package/dist/mail/conversation-map.js +61 -0
  104. package/dist/mail/conversation-map.js.map +1 -0
  105. package/dist/mail/index.d.ts +11 -0
  106. package/dist/mail/index.d.ts.map +1 -0
  107. package/dist/mail/index.js +11 -0
  108. package/dist/mail/index.js.map +1 -0
  109. package/dist/mail/mail-service.d.ts +85 -0
  110. package/dist/mail/mail-service.d.ts.map +1 -0
  111. package/dist/mail/mail-service.js +121 -0
  112. package/dist/mail/mail-service.js.map +1 -0
  113. package/dist/mail/stores/eventstore-conversation-store.d.ts +40 -0
  114. package/dist/mail/stores/eventstore-conversation-store.d.ts.map +1 -0
  115. package/dist/mail/stores/eventstore-conversation-store.js +131 -0
  116. package/dist/mail/stores/eventstore-conversation-store.js.map +1 -0
  117. package/dist/mail/stores/eventstore-participant-store.d.ts +43 -0
  118. package/dist/mail/stores/eventstore-participant-store.d.ts.map +1 -0
  119. package/dist/mail/stores/eventstore-participant-store.js +145 -0
  120. package/dist/mail/stores/eventstore-participant-store.js.map +1 -0
  121. package/dist/mail/stores/eventstore-thread-store.d.ts +46 -0
  122. package/dist/mail/stores/eventstore-thread-store.d.ts.map +1 -0
  123. package/dist/mail/stores/eventstore-thread-store.js +118 -0
  124. package/dist/mail/stores/eventstore-thread-store.js.map +1 -0
  125. package/dist/mail/stores/eventstore-turn-store.d.ts +47 -0
  126. package/dist/mail/stores/eventstore-turn-store.d.ts.map +1 -0
  127. package/dist/mail/stores/eventstore-turn-store.js +153 -0
  128. package/dist/mail/stores/eventstore-turn-store.js.map +1 -0
  129. package/dist/mail/stores/index.d.ts +12 -0
  130. package/dist/mail/stores/index.d.ts.map +1 -0
  131. package/dist/mail/stores/index.js +12 -0
  132. package/dist/mail/stores/index.js.map +1 -0
  133. package/dist/mail/stores/types.d.ts +146 -0
  134. package/dist/mail/stores/types.d.ts.map +1 -0
  135. package/dist/mail/stores/types.js +13 -0
  136. package/dist/mail/stores/types.js.map +1 -0
  137. package/dist/mail/turn-recorder.d.ts +30 -0
  138. package/dist/mail/turn-recorder.d.ts.map +1 -0
  139. package/dist/mail/turn-recorder.js +98 -0
  140. package/dist/mail/turn-recorder.js.map +1 -0
  141. package/dist/map/adapter/acp-over-map.d.ts +115 -0
  142. package/dist/map/adapter/acp-over-map.d.ts.map +1 -0
  143. package/dist/map/adapter/acp-over-map.js +1024 -0
  144. package/dist/map/adapter/acp-over-map.js.map +1 -0
  145. package/dist/map/adapter/connection-manager.d.ts +150 -0
  146. package/dist/map/adapter/connection-manager.d.ts.map +1 -0
  147. package/dist/map/adapter/connection-manager.js +207 -0
  148. package/dist/map/adapter/connection-manager.js.map +1 -0
  149. package/dist/map/adapter/event-log.d.ts +87 -0
  150. package/dist/map/adapter/event-log.d.ts.map +1 -0
  151. package/dist/map/adapter/event-log.js +122 -0
  152. package/dist/map/adapter/event-log.js.map +1 -0
  153. package/dist/map/adapter/event-translator.d.ts +85 -0
  154. package/dist/map/adapter/event-translator.d.ts.map +1 -0
  155. package/dist/map/adapter/event-translator.js +295 -0
  156. package/dist/map/adapter/event-translator.js.map +1 -0
  157. package/dist/map/adapter/extensions/agent-detection.d.ts +49 -0
  158. package/dist/map/adapter/extensions/agent-detection.d.ts.map +1 -0
  159. package/dist/map/adapter/extensions/agent-detection.js +91 -0
  160. package/dist/map/adapter/extensions/agent-detection.js.map +1 -0
  161. package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
  162. package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
  163. package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
  164. package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
  165. package/dist/map/adapter/extensions/cognitive.d.ts +27 -0
  166. package/dist/map/adapter/extensions/cognitive.d.ts.map +1 -0
  167. package/dist/map/adapter/extensions/cognitive.js +158 -0
  168. package/dist/map/adapter/extensions/cognitive.js.map +1 -0
  169. package/dist/map/adapter/extensions/index.d.ts +95 -0
  170. package/dist/map/adapter/extensions/index.d.ts.map +1 -0
  171. package/dist/map/adapter/extensions/index.js +228 -0
  172. package/dist/map/adapter/extensions/index.js.map +1 -0
  173. package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
  174. package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
  175. package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
  176. package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
  177. package/dist/map/adapter/extensions/resume.d.ts +47 -0
  178. package/dist/map/adapter/extensions/resume.d.ts.map +1 -0
  179. package/dist/map/adapter/extensions/resume.js +59 -0
  180. package/dist/map/adapter/extensions/resume.js.map +1 -0
  181. package/dist/map/adapter/extensions/streams.d.ts +95 -0
  182. package/dist/map/adapter/extensions/streams.d.ts.map +1 -0
  183. package/dist/map/adapter/extensions/streams.js +515 -0
  184. package/dist/map/adapter/extensions/streams.js.map +1 -0
  185. package/dist/map/adapter/extensions/task.d.ts +40 -0
  186. package/dist/map/adapter/extensions/task.d.ts.map +1 -0
  187. package/dist/map/adapter/extensions/task.js +197 -0
  188. package/dist/map/adapter/extensions/task.js.map +1 -0
  189. package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
  190. package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
  191. package/dist/map/adapter/extensions/update-metadata.js +67 -0
  192. package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
  193. package/dist/map/adapter/extensions/wake.d.ts +60 -0
  194. package/dist/map/adapter/extensions/wake.d.ts.map +1 -0
  195. package/dist/map/adapter/extensions/wake.js +144 -0
  196. package/dist/map/adapter/extensions/wake.js.map +1 -0
  197. package/dist/map/adapter/extensions/workspace-files.d.ts +42 -0
  198. package/dist/map/adapter/extensions/workspace-files.d.ts.map +1 -0
  199. package/dist/map/adapter/extensions/workspace-files.js +338 -0
  200. package/dist/map/adapter/extensions/workspace-files.js.map +1 -0
  201. package/dist/map/adapter/extensions/workspace.d.ts +57 -0
  202. package/dist/map/adapter/extensions/workspace.d.ts.map +1 -0
  203. package/dist/map/adapter/extensions/workspace.js +81 -0
  204. package/dist/map/adapter/extensions/workspace.js.map +1 -0
  205. package/dist/map/adapter/index.d.ts +20 -0
  206. package/dist/map/adapter/index.d.ts.map +1 -0
  207. package/dist/map/adapter/index.js +40 -0
  208. package/dist/map/adapter/index.js.map +1 -0
  209. package/dist/map/adapter/interface.d.ts +450 -0
  210. package/dist/map/adapter/interface.d.ts.map +1 -0
  211. package/dist/map/adapter/interface.js +24 -0
  212. package/dist/map/adapter/interface.js.map +1 -0
  213. package/dist/map/adapter/mail-handler-adapter.d.ts +27 -0
  214. package/dist/map/adapter/mail-handler-adapter.d.ts.map +1 -0
  215. package/dist/map/adapter/mail-handler-adapter.js +292 -0
  216. package/dist/map/adapter/mail-handler-adapter.js.map +1 -0
  217. package/dist/map/adapter/map-adapter.d.ts +200 -0
  218. package/dist/map/adapter/map-adapter.d.ts.map +1 -0
  219. package/dist/map/adapter/map-adapter.js +1199 -0
  220. package/dist/map/adapter/map-adapter.js.map +1 -0
  221. package/dist/map/adapter/rpc-handler.d.ts +263 -0
  222. package/dist/map/adapter/rpc-handler.d.ts.map +1 -0
  223. package/dist/map/adapter/rpc-handler.js +365 -0
  224. package/dist/map/adapter/rpc-handler.js.map +1 -0
  225. package/dist/map/adapter/subscription-manager.d.ts +174 -0
  226. package/dist/map/adapter/subscription-manager.d.ts.map +1 -0
  227. package/dist/map/adapter/subscription-manager.js +248 -0
  228. package/dist/map/adapter/subscription-manager.js.map +1 -0
  229. package/dist/map/adapter/types.d.ts +194 -0
  230. package/dist/map/adapter/types.d.ts.map +1 -0
  231. package/dist/map/adapter/types.js +27 -0
  232. package/dist/map/adapter/types.js.map +1 -0
  233. package/dist/map/adapter/websocket-integration.d.ts +113 -0
  234. package/dist/map/adapter/websocket-integration.d.ts.map +1 -0
  235. package/dist/map/adapter/websocket-integration.js +134 -0
  236. package/dist/map/adapter/websocket-integration.js.map +1 -0
  237. package/dist/map/cascade-action-handler.d.ts.map +1 -1
  238. package/dist/map/cascade-action-handler.js +19 -5
  239. package/dist/map/cascade-action-handler.js.map +1 -1
  240. package/dist/map/federation/envelope.d.ts +98 -0
  241. package/dist/map/federation/envelope.d.ts.map +1 -0
  242. package/dist/map/federation/envelope.js +160 -0
  243. package/dist/map/federation/envelope.js.map +1 -0
  244. package/dist/map/federation/federation-handler.d.ts +50 -0
  245. package/dist/map/federation/federation-handler.d.ts.map +1 -0
  246. package/dist/map/federation/federation-handler.js +306 -0
  247. package/dist/map/federation/federation-handler.js.map +1 -0
  248. package/dist/map/federation/index.d.ts +14 -0
  249. package/dist/map/federation/index.d.ts.map +1 -0
  250. package/dist/map/federation/index.js +13 -0
  251. package/dist/map/federation/index.js.map +1 -0
  252. package/dist/map/federation/types.d.ts +239 -0
  253. package/dist/map/federation/types.d.ts.map +1 -0
  254. package/dist/map/federation/types.js +23 -0
  255. package/dist/map/federation/types.js.map +1 -0
  256. package/dist/map/server.d.ts.map +1 -1
  257. package/dist/map/server.js +17 -2
  258. package/dist/map/server.js.map +1 -1
  259. package/dist/map/types.d.ts +6 -0
  260. package/dist/map/types.d.ts.map +1 -1
  261. package/dist/mcp/map-client.d.ts +39 -0
  262. package/dist/mcp/map-client.d.ts.map +1 -0
  263. package/dist/mcp/map-client.js +129 -0
  264. package/dist/mcp/map-client.js.map +1 -0
  265. package/dist/mcp/mcp-server.d.ts +72 -0
  266. package/dist/mcp/mcp-server.d.ts.map +1 -0
  267. package/dist/mcp/mcp-server.js +1027 -0
  268. package/dist/mcp/mcp-server.js.map +1 -0
  269. package/dist/mcp/tools/claim_task.d.ts +35 -0
  270. package/dist/mcp/tools/claim_task.d.ts.map +1 -0
  271. package/dist/mcp/tools/claim_task.js +58 -0
  272. package/dist/mcp/tools/claim_task.js.map +1 -0
  273. package/dist/mcp/tools/done-v2.d.ts +0 -1
  274. package/dist/mcp/tools/done-v2.d.ts.map +1 -1
  275. package/dist/mcp/tools/done-v2.js +0 -1
  276. package/dist/mcp/tools/done-v2.js.map +1 -1
  277. package/dist/mcp/tools/done.d.ts +102 -0
  278. package/dist/mcp/tools/done.d.ts.map +1 -0
  279. package/dist/mcp/tools/done.js +253 -0
  280. package/dist/mcp/tools/done.js.map +1 -0
  281. package/dist/mcp/tools/inject_context.d.ts +61 -0
  282. package/dist/mcp/tools/inject_context.d.ts.map +1 -0
  283. package/dist/mcp/tools/inject_context.js +123 -0
  284. package/dist/mcp/tools/inject_context.js.map +1 -0
  285. package/dist/mcp/tools/list_claimable_tasks.d.ts +38 -0
  286. package/dist/mcp/tools/list_claimable_tasks.d.ts.map +1 -0
  287. package/dist/mcp/tools/list_claimable_tasks.js +63 -0
  288. package/dist/mcp/tools/list_claimable_tasks.js.map +1 -0
  289. package/dist/mcp/tools/unclaim_task.d.ts +31 -0
  290. package/dist/mcp/tools/unclaim_task.d.ts.map +1 -0
  291. package/dist/mcp/tools/unclaim_task.js +47 -0
  292. package/dist/mcp/tools/unclaim_task.js.map +1 -0
  293. package/dist/mcp/tools/wait_for_activity.d.ts +60 -0
  294. package/dist/mcp/tools/wait_for_activity.d.ts.map +1 -0
  295. package/dist/mcp/tools/wait_for_activity.js +135 -0
  296. package/dist/mcp/tools/wait_for_activity.js.map +1 -0
  297. package/dist/monitor/health-check-service.d.ts +143 -0
  298. package/dist/monitor/health-check-service.d.ts.map +1 -0
  299. package/dist/monitor/health-check-service.js +240 -0
  300. package/dist/monitor/health-check-service.js.map +1 -0
  301. package/dist/monitor/index.d.ts +14 -0
  302. package/dist/monitor/index.d.ts.map +1 -0
  303. package/dist/monitor/index.js +14 -0
  304. package/dist/monitor/index.js.map +1 -0
  305. package/dist/monitor/stall-detector.d.ts +109 -0
  306. package/dist/monitor/stall-detector.d.ts.map +1 -0
  307. package/dist/monitor/stall-detector.js +152 -0
  308. package/dist/monitor/stall-detector.js.map +1 -0
  309. package/dist/peer/capability-manager.d.ts +56 -0
  310. package/dist/peer/capability-manager.d.ts.map +1 -0
  311. package/dist/peer/capability-manager.js +186 -0
  312. package/dist/peer/capability-manager.js.map +1 -0
  313. package/dist/peer/encapsulation-manager.d.ts +190 -0
  314. package/dist/peer/encapsulation-manager.d.ts.map +1 -0
  315. package/dist/peer/encapsulation-manager.js +486 -0
  316. package/dist/peer/encapsulation-manager.js.map +1 -0
  317. package/dist/peer/federation-manager.d.ts +223 -0
  318. package/dist/peer/federation-manager.d.ts.map +1 -0
  319. package/dist/peer/federation-manager.js +528 -0
  320. package/dist/peer/federation-manager.js.map +1 -0
  321. package/dist/peer/hierarchy-errors.d.ts +208 -0
  322. package/dist/peer/hierarchy-errors.d.ts.map +1 -0
  323. package/dist/peer/hierarchy-errors.js +268 -0
  324. package/dist/peer/hierarchy-errors.js.map +1 -0
  325. package/dist/peer/hierarchy-protocol.d.ts +159 -0
  326. package/dist/peer/hierarchy-protocol.d.ts.map +1 -0
  327. package/dist/peer/hierarchy-protocol.js +142 -0
  328. package/dist/peer/hierarchy-protocol.js.map +1 -0
  329. package/dist/peer/index.d.ts +15 -0
  330. package/dist/peer/index.d.ts.map +1 -0
  331. package/dist/peer/index.js +15 -0
  332. package/dist/peer/index.js.map +1 -0
  333. package/dist/peer/peer-manager.d.ts +99 -0
  334. package/dist/peer/peer-manager.d.ts.map +1 -0
  335. package/dist/peer/peer-manager.js +333 -0
  336. package/dist/peer/peer-manager.js.map +1 -0
  337. package/dist/peer/task-delegation.d.ts +189 -0
  338. package/dist/peer/task-delegation.d.ts.map +1 -0
  339. package/dist/peer/task-delegation.js +303 -0
  340. package/dist/peer/task-delegation.js.map +1 -0
  341. package/dist/peer/transports/index.d.ts +8 -0
  342. package/dist/peer/transports/index.d.ts.map +1 -0
  343. package/dist/peer/transports/index.js +8 -0
  344. package/dist/peer/transports/index.js.map +1 -0
  345. package/dist/peer/transports/local-transport.d.ts +56 -0
  346. package/dist/peer/transports/local-transport.d.ts.map +1 -0
  347. package/dist/peer/transports/local-transport.js +263 -0
  348. package/dist/peer/transports/local-transport.js.map +1 -0
  349. package/dist/peer/transports/websocket-transport.d.ts +86 -0
  350. package/dist/peer/transports/websocket-transport.d.ts.map +1 -0
  351. package/dist/peer/transports/websocket-transport.js +338 -0
  352. package/dist/peer/transports/websocket-transport.js.map +1 -0
  353. package/dist/peer/types.d.ts +268 -0
  354. package/dist/peer/types.d.ts.map +1 -0
  355. package/dist/peer/types.js +36 -0
  356. package/dist/peer/types.js.map +1 -0
  357. package/dist/router/address-resolver.d.ts +102 -0
  358. package/dist/router/address-resolver.d.ts.map +1 -0
  359. package/dist/router/address-resolver.js +198 -0
  360. package/dist/router/address-resolver.js.map +1 -0
  361. package/dist/router/broadcast.d.ts +53 -0
  362. package/dist/router/broadcast.d.ts.map +1 -0
  363. package/dist/router/broadcast.js +75 -0
  364. package/dist/router/broadcast.js.map +1 -0
  365. package/dist/router/channels.d.ts +148 -0
  366. package/dist/router/channels.d.ts.map +1 -0
  367. package/dist/router/channels.js +126 -0
  368. package/dist/router/channels.js.map +1 -0
  369. package/dist/router/index.d.ts +21 -0
  370. package/dist/router/index.d.ts.map +1 -0
  371. package/dist/router/index.js +18 -0
  372. package/dist/router/index.js.map +1 -0
  373. package/dist/router/message-router.d.ts +197 -0
  374. package/dist/router/message-router.d.ts.map +1 -0
  375. package/dist/router/message-router.js +903 -0
  376. package/dist/router/message-router.js.map +1 -0
  377. package/dist/router/message-types.d.ts +183 -0
  378. package/dist/router/message-types.d.ts.map +1 -0
  379. package/dist/router/message-types.js +79 -0
  380. package/dist/router/message-types.js.map +1 -0
  381. package/dist/router/role-resolver.d.ts +67 -0
  382. package/dist/router/role-resolver.d.ts.map +1 -0
  383. package/dist/router/role-resolver.js +106 -0
  384. package/dist/router/role-resolver.js.map +1 -0
  385. package/dist/router/signals.d.ts +253 -0
  386. package/dist/router/signals.d.ts.map +1 -0
  387. package/dist/router/signals.js +53 -0
  388. package/dist/router/signals.js.map +1 -0
  389. package/dist/router/types.d.ts +191 -0
  390. package/dist/router/types.d.ts.map +1 -0
  391. package/dist/router/types.js +34 -0
  392. package/dist/router/types.js.map +1 -0
  393. package/dist/router/wake.d.ts +111 -0
  394. package/dist/router/wake.d.ts.map +1 -0
  395. package/dist/router/wake.js +180 -0
  396. package/dist/router/wake.js.map +1 -0
  397. package/dist/server/combined-server.d.ts +95 -0
  398. package/dist/server/combined-server.d.ts.map +1 -0
  399. package/dist/server/combined-server.js +335 -0
  400. package/dist/server/combined-server.js.map +1 -0
  401. package/dist/steering/index.d.ts +11 -0
  402. package/dist/steering/index.d.ts.map +1 -0
  403. package/dist/steering/index.js +11 -0
  404. package/dist/steering/index.js.map +1 -0
  405. package/dist/steering/inject.d.ts +39 -0
  406. package/dist/steering/inject.d.ts.map +1 -0
  407. package/dist/steering/inject.js +197 -0
  408. package/dist/steering/inject.js.map +1 -0
  409. package/dist/steering/types.d.ts +100 -0
  410. package/dist/steering/types.d.ts.map +1 -0
  411. package/dist/steering/types.js +11 -0
  412. package/dist/steering/types.js.map +1 -0
  413. package/dist/store/backends/index.d.ts +11 -0
  414. package/dist/store/backends/index.d.ts.map +1 -0
  415. package/dist/store/backends/index.js +15 -0
  416. package/dist/store/backends/index.js.map +1 -0
  417. package/dist/store/backends/json-backend.d.ts +23 -0
  418. package/dist/store/backends/json-backend.d.ts.map +1 -0
  419. package/dist/store/backends/json-backend.js +220 -0
  420. package/dist/store/backends/json-backend.js.map +1 -0
  421. package/dist/store/backends/memory-backend.d.ts +12 -0
  422. package/dist/store/backends/memory-backend.d.ts.map +1 -0
  423. package/dist/store/backends/memory-backend.js +205 -0
  424. package/dist/store/backends/memory-backend.js.map +1 -0
  425. package/dist/store/backends/sqlite-backend.d.ts +27 -0
  426. package/dist/store/backends/sqlite-backend.d.ts.map +1 -0
  427. package/dist/store/backends/sqlite-backend.js +231 -0
  428. package/dist/store/backends/sqlite-backend.js.map +1 -0
  429. package/dist/store/backends/tinybase-backend.d.ts +22 -0
  430. package/dist/store/backends/tinybase-backend.d.ts.map +1 -0
  431. package/dist/store/backends/tinybase-backend.js +203 -0
  432. package/dist/store/backends/tinybase-backend.js.map +1 -0
  433. package/dist/store/backends/types.d.ts +175 -0
  434. package/dist/store/backends/types.d.ts.map +1 -0
  435. package/dist/store/backends/types.js +28 -0
  436. package/dist/store/backends/types.js.map +1 -0
  437. package/dist/store/event-store.d.ts +128 -0
  438. package/dist/store/event-store.d.ts.map +1 -0
  439. package/dist/store/event-store.js +1751 -0
  440. package/dist/store/event-store.js.map +1 -0
  441. package/dist/store/instance.d.ts +290 -0
  442. package/dist/store/instance.d.ts.map +1 -0
  443. package/dist/store/instance.js +363 -0
  444. package/dist/store/instance.js.map +1 -0
  445. package/dist/store/migrations.d.ts +41 -0
  446. package/dist/store/migrations.d.ts.map +1 -0
  447. package/dist/store/migrations.js +79 -0
  448. package/dist/store/migrations.js.map +1 -0
  449. package/dist/store/test-utils.d.ts +63 -0
  450. package/dist/store/test-utils.d.ts.map +1 -0
  451. package/dist/store/test-utils.js +63 -0
  452. package/dist/store/test-utils.js.map +1 -0
  453. package/dist/store/types/config.d.ts +16 -0
  454. package/dist/store/types/config.d.ts.map +1 -0
  455. package/dist/store/types/config.js +8 -0
  456. package/dist/store/types/config.js.map +1 -0
  457. package/dist/store/types/conversations.d.ts +91 -0
  458. package/dist/store/types/conversations.d.ts.map +1 -0
  459. package/dist/store/types/conversations.js +8 -0
  460. package/dist/store/types/conversations.js.map +1 -0
  461. package/dist/store/types/sessions.d.ts +44 -0
  462. package/dist/store/types/sessions.d.ts.map +1 -0
  463. package/dist/store/types/sessions.js +9 -0
  464. package/dist/store/types/sessions.js.map +1 -0
  465. package/dist/store/types.d.ts +115 -0
  466. package/dist/store/types.d.ts.map +1 -0
  467. package/dist/store/types.js +6 -0
  468. package/dist/store/types.js.map +1 -0
  469. package/dist/task/backend/index.d.ts +93 -0
  470. package/dist/task/backend/index.d.ts.map +1 -0
  471. package/dist/task/backend/index.js +178 -0
  472. package/dist/task/backend/index.js.map +1 -0
  473. package/dist/task/backend/memory.d.ts +70 -0
  474. package/dist/task/backend/memory.d.ts.map +1 -0
  475. package/dist/task/backend/memory.js +621 -0
  476. package/dist/task/backend/memory.js.map +1 -0
  477. package/dist/task/backend/opentasks/backend.d.ts +140 -0
  478. package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
  479. package/dist/task/backend/opentasks/backend.js +1023 -0
  480. package/dist/task/backend/opentasks/backend.js.map +1 -0
  481. package/dist/task/backend/opentasks/client.d.ts +337 -0
  482. package/dist/task/backend/opentasks/client.d.ts.map +1 -0
  483. package/dist/task/backend/opentasks/client.js +225 -0
  484. package/dist/task/backend/opentasks/client.js.map +1 -0
  485. package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
  486. package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
  487. package/dist/task/backend/opentasks/daemon-manager.js +195 -0
  488. package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
  489. package/dist/task/backend/opentasks/index.d.ts +21 -0
  490. package/dist/task/backend/opentasks/index.d.ts.map +1 -0
  491. package/dist/task/backend/opentasks/index.js +21 -0
  492. package/dist/task/backend/opentasks/index.js.map +1 -0
  493. package/dist/task/backend/opentasks/mapping.d.ts +48 -0
  494. package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
  495. package/dist/task/backend/opentasks/mapping.js +77 -0
  496. package/dist/task/backend/opentasks/mapping.js.map +1 -0
  497. package/dist/task/backend/sudocode/__tests__/integration/test-utils.d.ts +54 -0
  498. package/dist/task/backend/sudocode/__tests__/integration/test-utils.d.ts.map +1 -0
  499. package/dist/task/backend/sudocode/__tests__/integration/test-utils.js +88 -0
  500. package/dist/task/backend/sudocode/__tests__/integration/test-utils.js.map +1 -0
  501. package/dist/task/backend/sudocode/backend.d.ts +155 -0
  502. package/dist/task/backend/sudocode/backend.d.ts.map +1 -0
  503. package/dist/task/backend/sudocode/backend.js +942 -0
  504. package/dist/task/backend/sudocode/backend.js.map +1 -0
  505. package/dist/task/backend/sudocode/client.d.ts +303 -0
  506. package/dist/task/backend/sudocode/client.d.ts.map +1 -0
  507. package/dist/task/backend/sudocode/client.js +101 -0
  508. package/dist/task/backend/sudocode/client.js.map +1 -0
  509. package/dist/task/backend/sudocode/index.d.ts +19 -0
  510. package/dist/task/backend/sudocode/index.d.ts.map +1 -0
  511. package/dist/task/backend/sudocode/index.js +17 -0
  512. package/dist/task/backend/sudocode/index.js.map +1 -0
  513. package/dist/task/backend/sudocode/mapping.d.ts +51 -0
  514. package/dist/task/backend/sudocode/mapping.d.ts.map +1 -0
  515. package/dist/task/backend/sudocode/mapping.js +86 -0
  516. package/dist/task/backend/sudocode/mapping.js.map +1 -0
  517. package/dist/task/backend/sudocode/server-client.d.ts +56 -0
  518. package/dist/task/backend/sudocode/server-client.d.ts.map +1 -0
  519. package/dist/task/backend/sudocode/server-client.js +367 -0
  520. package/dist/task/backend/sudocode/server-client.js.map +1 -0
  521. package/dist/task/backend/sudocode/standalone-client.d.ts +91 -0
  522. package/dist/task/backend/sudocode/standalone-client.d.ts.map +1 -0
  523. package/dist/task/backend/sudocode/standalone-client.js +476 -0
  524. package/dist/task/backend/sudocode/standalone-client.js.map +1 -0
  525. package/dist/task/backend/sudocode/sync-policy.d.ts +166 -0
  526. package/dist/task/backend/sudocode/sync-policy.d.ts.map +1 -0
  527. package/dist/task/backend/sudocode/sync-policy.js +221 -0
  528. package/dist/task/backend/sudocode/sync-policy.js.map +1 -0
  529. package/dist/task/backend/sudocode/tools.d.ts +87 -0
  530. package/dist/task/backend/sudocode/tools.d.ts.map +1 -0
  531. package/dist/task/backend/sudocode/tools.js +743 -0
  532. package/dist/task/backend/sudocode/tools.js.map +1 -0
  533. package/dist/task/backend/tool-provider.d.ts +56 -0
  534. package/dist/task/backend/tool-provider.d.ts.map +1 -0
  535. package/dist/task/backend/tool-provider.js +424 -0
  536. package/dist/task/backend/tool-provider.js.map +1 -0
  537. package/dist/task/backend/types.d.ts +297 -0
  538. package/dist/task/backend/types.d.ts.map +1 -0
  539. package/dist/task/backend/types.js +27 -0
  540. package/dist/task/backend/types.js.map +1 -0
  541. package/dist/task/backend/unified-tool-provider.d.ts +57 -0
  542. package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
  543. package/dist/task/backend/unified-tool-provider.js +623 -0
  544. package/dist/task/backend/unified-tool-provider.js.map +1 -0
  545. package/dist/task/index.d.ts +7 -0
  546. package/dist/task/index.d.ts.map +1 -0
  547. package/dist/task/index.js +7 -0
  548. package/dist/task/index.js.map +1 -0
  549. package/dist/task/retry-policy.d.ts +89 -0
  550. package/dist/task/retry-policy.d.ts.map +1 -0
  551. package/dist/task/retry-policy.js +160 -0
  552. package/dist/task/retry-policy.js.map +1 -0
  553. package/dist/task/task-manager.d.ts +70 -0
  554. package/dist/task/task-manager.d.ts.map +1 -0
  555. package/dist/task/task-manager.js +319 -0
  556. package/dist/task/task-manager.js.map +1 -0
  557. package/dist/task/types.d.ts +72 -0
  558. package/dist/task/types.d.ts.map +1 -0
  559. package/dist/task/types.js +33 -0
  560. package/dist/task/types.js.map +1 -0
  561. package/dist/teams/team-loader.d.ts +2 -1
  562. package/dist/teams/team-loader.d.ts.map +1 -1
  563. package/dist/teams/team-loader.js +2 -1
  564. package/dist/teams/team-loader.js.map +1 -1
  565. package/dist/teams/team-manager.d.ts +101 -0
  566. package/dist/teams/team-manager.d.ts.map +1 -0
  567. package/dist/teams/team-manager.js +260 -0
  568. package/dist/teams/team-manager.js.map +1 -0
  569. package/dist/teams/team-runtime-v2.d.ts +0 -3
  570. package/dist/teams/team-runtime-v2.d.ts.map +1 -1
  571. package/dist/teams/team-runtime-v2.js +8 -87
  572. package/dist/teams/team-runtime-v2.js.map +1 -1
  573. package/dist/teams/team-runtime.d.ts +245 -0
  574. package/dist/teams/team-runtime.d.ts.map +1 -0
  575. package/dist/teams/team-runtime.js +1023 -0
  576. package/dist/teams/team-runtime.js.map +1 -0
  577. package/dist/trigger/router/index.d.ts +11 -0
  578. package/dist/trigger/router/index.d.ts.map +1 -0
  579. package/dist/trigger/router/index.js +10 -0
  580. package/dist/trigger/router/index.js.map +1 -0
  581. package/dist/trigger/router/strategies/ai-router-strategy.d.ts +34 -0
  582. package/dist/trigger/router/strategies/ai-router-strategy.d.ts.map +1 -0
  583. package/dist/trigger/router/strategies/ai-router-strategy.js +359 -0
  584. package/dist/trigger/router/strategies/ai-router-strategy.js.map +1 -0
  585. package/dist/trigger/router/strategies/direct-strategy.d.ts +32 -0
  586. package/dist/trigger/router/strategies/direct-strategy.d.ts.map +1 -0
  587. package/dist/trigger/router/strategies/direct-strategy.js +119 -0
  588. package/dist/trigger/router/strategies/direct-strategy.js.map +1 -0
  589. package/dist/trigger/router/strategies/index.d.ts +11 -0
  590. package/dist/trigger/router/strategies/index.d.ts.map +1 -0
  591. package/dist/trigger/router/strategies/index.js +11 -0
  592. package/dist/trigger/router/strategies/index.js.map +1 -0
  593. package/dist/trigger/router/strategies/role-strategy.d.ts +39 -0
  594. package/dist/trigger/router/strategies/role-strategy.d.ts.map +1 -0
  595. package/dist/trigger/router/strategies/role-strategy.js +207 -0
  596. package/dist/trigger/router/strategies/role-strategy.js.map +1 -0
  597. package/dist/trigger/router/trigger-router.d.ts +54 -0
  598. package/dist/trigger/router/trigger-router.d.ts.map +1 -0
  599. package/dist/trigger/router/trigger-router.js +362 -0
  600. package/dist/trigger/router/trigger-router.js.map +1 -0
  601. package/dist/trigger/router/types.d.ts +225 -0
  602. package/dist/trigger/router/types.d.ts.map +1 -0
  603. package/dist/trigger/router/types.js +10 -0
  604. package/dist/trigger/router/types.js.map +1 -0
  605. package/dist/trigger/sources/cron/cron-service.d.ts.map +1 -1
  606. package/dist/trigger/sources/cron/cron-service.js +6 -3
  607. package/dist/trigger/sources/cron/cron-service.js.map +1 -1
  608. package/dist/trigger/trigger-system.d.ts +77 -0
  609. package/dist/trigger/trigger-system.d.ts.map +1 -0
  610. package/dist/trigger/trigger-system.js +84 -0
  611. package/dist/trigger/trigger-system.js.map +1 -0
  612. package/dist/util/git-safety.d.ts +33 -0
  613. package/dist/util/git-safety.d.ts.map +1 -0
  614. package/dist/util/git-safety.js +94 -0
  615. package/dist/util/git-safety.js.map +1 -0
  616. package/dist/workspace/dataplane-adapter.d.ts +260 -0
  617. package/dist/workspace/dataplane-adapter.d.ts.map +1 -0
  618. package/dist/workspace/dataplane-adapter.js +416 -0
  619. package/dist/workspace/dataplane-adapter.js.map +1 -0
  620. package/dist/workspace/index.d.ts +0 -1
  621. package/dist/workspace/index.d.ts.map +1 -1
  622. package/dist/workspace/index.js +0 -2
  623. package/dist/workspace/index.js.map +1 -1
  624. package/dist/workspace/landing/direct-push.d.ts.map +1 -1
  625. package/dist/workspace/landing/direct-push.js +22 -7
  626. package/dist/workspace/landing/direct-push.js.map +1 -1
  627. package/dist/workspace/landing/queue-to-branch.d.ts.map +1 -1
  628. package/dist/workspace/landing/queue-to-branch.js +1 -3
  629. package/dist/workspace/landing/queue-to-branch.js.map +1 -1
  630. package/dist/workspace/types.d.ts +0 -13
  631. package/dist/workspace/types.d.ts.map +1 -1
  632. package/dist/workspace/workspace-manager.d.ts +0 -11
  633. package/dist/workspace/workspace-manager.d.ts.map +1 -1
  634. package/dist/workspace/workspace-manager.js +0 -30
  635. package/dist/workspace/workspace-manager.js.map +1 -1
  636. package/package.json +28 -2
  637. package/templates/teams/self-driving/prompts/grinder.md +1 -0
  638. package/templates/teams/self-driving/prompts/judge.md +1 -0
  639. package/templates/teams/self-driving/prompts/planner.md +1 -0
  640. package/templates/teams/self-driving/roles/grinder.yaml +15 -0
  641. package/templates/teams/self-driving/roles/judge.yaml +10 -0
  642. package/templates/teams/self-driving/roles/planner.yaml +16 -0
  643. package/.claude/commands/openspec/apply.md +0 -23
  644. package/.claude/commands/openspec/archive.md +0 -27
  645. package/.claude/commands/openspec/proposal.md +0 -28
  646. package/.claude/settings.json +0 -133
  647. package/.gitattributes +0 -3
  648. package/.opentasks/config.json +0 -9
  649. package/.opentasks/graph.jsonl +0 -0
  650. package/.sessionlog/settings.json +0 -4
  651. package/.sudocode/issues.jsonl +0 -183
  652. package/.sudocode/specs.jsonl +0 -56
  653. package/AGENTS.md +0 -18
  654. package/CLAUDE.md +0 -923
  655. package/docs/architecture.md +0 -508
  656. package/docs/configuration.md +0 -323
  657. package/docs/conflict-recovery.md +0 -472
  658. package/docs/design/task-dispatcher.md +0 -880
  659. package/docs/design-subsystem-extraction.md +0 -627
  660. package/docs/git-cascade-integration-gaps.md +0 -678
  661. package/docs/implementation-details.md +0 -1127
  662. package/docs/implementation-summary.md +0 -448
  663. package/docs/lifecycle-events-design.md +0 -111
  664. package/docs/mail-integration.md +0 -608
  665. package/docs/openhive-capability-summary.md +0 -415
  666. package/docs/openhive-integration.md +0 -415
  667. package/docs/plan-self-driving-support.md +0 -433
  668. package/docs/roadmap-v2-gaps.md +0 -216
  669. package/docs/spec-self-driving-support.md +0 -462
  670. package/docs/team-templates.md +0 -860
  671. package/docs/teams.md +0 -306
  672. package/docs/trigger-system-design.md +0 -333
  673. package/docs/troubleshooting.md +0 -489
  674. package/docs/workspace-interfaces.md +0 -731
  675. package/docs/workspace-redesign-plan.md +0 -302
  676. package/examples/distributed-peer-communication.ts +0 -202
  677. package/examples/local-peer-communication.ts +0 -165
  678. package/index.js +0 -2
  679. package/mvp_docs/agent-execution-system.md +0 -347
  680. package/mvp_docs/agent-interface.md +0 -580
  681. package/mvp_docs/data-structures.md +0 -701
  682. package/mvp_docs/dynamic-meta-orchestration.md +0 -116
  683. package/mvp_docs/multi-agent-interaction-design.md +0 -779
  684. package/mvp_docs/mvp-implementation-plan.md +0 -1148
  685. package/renovate.json5 +0 -6
  686. package/scripts/test-acp-integration.ts +0 -422
  687. package/src/__tests__/boot-v2.test.ts +0 -631
  688. package/src/__tests__/e2e/acp-over-map-live.e2e.test.ts +0 -496
  689. package/src/__tests__/e2e/acp-over-map.e2e.test.ts +0 -457
  690. package/src/__tests__/e2e/agent-lifecycle.e2e.test.ts +0 -770
  691. package/src/__tests__/e2e/auto-sync.e2e.test.ts +0 -257
  692. package/src/__tests__/e2e/bootstrap.e2e.test.ts +0 -319
  693. package/src/__tests__/e2e/cascade-rebase.e2e.test.ts +0 -254
  694. package/src/__tests__/e2e/cc-swarm-bridge.e2e.test.ts +0 -253
  695. package/src/__tests__/e2e/cli-run.e2e.test.ts +0 -167
  696. package/src/__tests__/e2e/cognitive-workspace.e2e.test.ts +0 -282
  697. package/src/__tests__/e2e/dispatch-coordination.e2e.test.ts +0 -495
  698. package/src/__tests__/e2e/dispatch-live.e2e.test.ts +0 -564
  699. package/src/__tests__/e2e/dispatch-opentasks.e2e.test.ts +0 -496
  700. package/src/__tests__/e2e/dispatch-phase2-live.e2e.test.ts +0 -456
  701. package/src/__tests__/e2e/dispatch-phase2.e2e.test.ts +0 -386
  702. package/src/__tests__/e2e/dispatch.e2e.test.ts +0 -376
  703. package/src/__tests__/e2e/done-scenarios.e2e.test.ts +0 -322
  704. package/src/__tests__/e2e/live-agent.e2e.test.ts +0 -1330
  705. package/src/__tests__/e2e/map-server.e2e.test.ts +0 -128
  706. package/src/__tests__/e2e/map-sidecar.e2e.test.ts +0 -139
  707. package/src/__tests__/e2e/opentasks-integration.e2e.test.ts +0 -280
  708. package/src/__tests__/e2e/pull-mode.e2e.test.ts +0 -632
  709. package/src/__tests__/e2e/resume-continue.e2e.test.ts +0 -312
  710. package/src/__tests__/e2e/self-driving-v3.e2e.test.ts +0 -197
  711. package/src/__tests__/e2e/spawn-resolver.e2e.test.ts +0 -200
  712. package/src/__tests__/e2e/swarmkit-integration.e2e.test.ts +0 -562
  713. package/src/__tests__/e2e/swarmkit-live.e2e.test.ts +0 -1049
  714. package/src/__tests__/e2e/trajectory-tracking.e2e.test.ts +0 -258
  715. package/src/__tests__/e2e/trigger-wake.e2e.test.ts +0 -257
  716. package/src/__tests__/e2e/workspace-lifecycle.e2e.test.ts +0 -383
  717. package/src/__tests__/e2e/workspace-v3.e2e.test.ts +0 -413
  718. package/src/acp/__tests__/claude-code-replay.test.ts +0 -225
  719. package/src/acp/__tests__/macro-agent.test.ts +0 -387
  720. package/src/acp/__tests__/session-mapper.test.ts +0 -152
  721. package/src/acp/__tests__/websocket-server.test.ts +0 -194
  722. package/src/acp/claude-code-replay.ts +0 -208
  723. package/src/acp/index.ts +0 -32
  724. package/src/acp/macro-agent.ts +0 -995
  725. package/src/acp/map-bridge.ts +0 -193
  726. package/src/acp/session-mapper.ts +0 -116
  727. package/src/acp/types.ts +0 -99
  728. package/src/acp/websocket-server.ts +0 -213
  729. package/src/adapters/__tests__/federation.test.ts +0 -256
  730. package/src/adapters/__tests__/inbox-adapter.test.ts +0 -316
  731. package/src/adapters/__tests__/tasks-adapter.test.ts +0 -270
  732. package/src/adapters/federation.ts +0 -185
  733. package/src/adapters/inbox-adapter.ts +0 -292
  734. package/src/adapters/inbox-client-adapter.ts +0 -173
  735. package/src/adapters/index.ts +0 -44
  736. package/src/adapters/opentasks-daemon.ts +0 -252
  737. package/src/adapters/tasks-adapter.ts +0 -330
  738. package/src/adapters/types.ts +0 -286
  739. package/src/agent/__tests__/agent-manager-topology.test.ts +0 -73
  740. package/src/agent/__tests__/agent-manager-v2.completion-signal.test.ts +0 -284
  741. package/src/agent/__tests__/agent-manager-v2.permission-interception.test.ts +0 -296
  742. package/src/agent/__tests__/agent-manager-v2.permissions.test.ts +0 -233
  743. package/src/agent/__tests__/agent-manager-v2.test.ts +0 -614
  744. package/src/agent/__tests__/agent-store.test.ts +0 -465
  745. package/src/agent/__tests__/task-ref-resolution.test.ts +0 -231
  746. package/src/agent/agent-manager-v2.ts +0 -2187
  747. package/src/agent/agent-manager.ts +0 -403
  748. package/src/agent/agent-store.ts +0 -409
  749. package/src/agent/index.ts +0 -7
  750. package/src/agent/prompts/coordinator-signals.ts +0 -115
  751. package/src/agent/prompts/index.ts +0 -7
  752. package/src/agent/system-prompt.ts +0 -298
  753. package/src/agent/types.ts +0 -480
  754. package/src/agent-detection/__tests__/command-builder.test.ts +0 -336
  755. package/src/agent-detection/__tests__/detector.test.ts +0 -768
  756. package/src/agent-detection/__tests__/registry.test.ts +0 -254
  757. package/src/agent-detection/command-builder.ts +0 -90
  758. package/src/agent-detection/detector.ts +0 -307
  759. package/src/agent-detection/index.ts +0 -36
  760. package/src/agent-detection/registry.ts +0 -200
  761. package/src/agent-detection/types.ts +0 -184
  762. package/src/api/__tests__/server.test.ts +0 -292
  763. package/src/api/index.ts +0 -8
  764. package/src/api/server.ts +0 -380
  765. package/src/api/types.ts +0 -39
  766. package/src/auth/__tests__/token.test.ts +0 -100
  767. package/src/auth/index.ts +0 -1
  768. package/src/auth/token.ts +0 -82
  769. package/src/boot-v2.ts +0 -1343
  770. package/src/cli/__tests__/stable-instance-id.test.ts +0 -57
  771. package/src/cli/acp.ts +0 -101
  772. package/src/cli/inbox-mcp-proxy.ts +0 -56
  773. package/src/cli/index.ts +0 -566
  774. package/src/cli/mcp.ts +0 -305
  775. package/src/cli/parse-args.ts +0 -54
  776. package/src/cli/stable-instance-id.ts +0 -14
  777. package/src/cognitive/__tests__/macro-agent-backend.test.ts +0 -673
  778. package/src/cognitive/__tests__/session-converter.test.ts +0 -423
  779. package/src/cognitive/__tests__/workspace-handler.test.ts +0 -221
  780. package/src/cognitive/analyst-role.ts +0 -59
  781. package/src/cognitive/index.ts +0 -49
  782. package/src/cognitive/macro-agent-backend.ts +0 -402
  783. package/src/cognitive/session-converter.ts +0 -151
  784. package/src/cognitive/types.ts +0 -187
  785. package/src/cognitive/workspace-handler.ts +0 -163
  786. package/src/config/index.ts +0 -9
  787. package/src/config/project-config.ts +0 -294
  788. package/src/control/__tests__/control-resilience.test.ts +0 -251
  789. package/src/control/__tests__/control-socket.test.ts +0 -240
  790. package/src/control/control-client.ts +0 -337
  791. package/src/control/control-server.ts +0 -298
  792. package/src/control/index.ts +0 -17
  793. package/src/control/types.ts +0 -95
  794. package/src/dispatch/CLAUDE.md +0 -129
  795. package/src/dispatch/__tests__/loadout-translation.test.ts +0 -141
  796. package/src/dispatch/__tests__/mail-inbound-consumer.integration.test.ts +0 -519
  797. package/src/dispatch/__tests__/mail-inbound-consumer.test.ts +0 -800
  798. package/src/dispatch/__tests__/mail-inbound-reuse-consumer.test.ts +0 -575
  799. package/src/dispatch/__tests__/permission-evaluator.test.ts +0 -196
  800. package/src/dispatch/__tests__/permission-overlay.test.ts +0 -56
  801. package/src/dispatch/__tests__/permissions-handler.test.ts +0 -168
  802. package/src/dispatch/__tests__/spawn-agent-handler.test.ts +0 -282
  803. package/src/dispatch/loadout-translation.ts +0 -138
  804. package/src/dispatch/mail-inbound-consumer.ts +0 -560
  805. package/src/dispatch/mail-inbound-reuse-consumer.ts +0 -479
  806. package/src/dispatch/permission-evaluator.ts +0 -191
  807. package/src/dispatch/permission-overlay.ts +0 -89
  808. package/src/dispatch/permissions-handler.ts +0 -112
  809. package/src/dispatch/spawn-agent-handler.ts +0 -160
  810. package/src/index.ts +0 -117
  811. package/src/integrations/__tests__/context-builder.test.ts +0 -218
  812. package/src/integrations/__tests__/sessionlog.test.ts +0 -498
  813. package/src/integrations/__tests__/skilltree.test.ts +0 -136
  814. package/src/integrations/context-builder.ts +0 -280
  815. package/src/integrations/sessionlog.ts +0 -194
  816. package/src/integrations/skilltree.ts +0 -184
  817. package/src/lifecycle/__tests__/cascade-consolidation.test.ts +0 -240
  818. package/src/lifecycle/__tests__/handlers-v2.test.ts +0 -565
  819. package/src/lifecycle/cascade.ts +0 -335
  820. package/src/lifecycle/cleanup.ts +0 -373
  821. package/src/lifecycle/handlers-v2.ts +0 -508
  822. package/src/lifecycle/index.ts +0 -76
  823. package/src/lifecycle/types.ts +0 -260
  824. package/src/map/__tests__/cascade-bridge.test.ts +0 -229
  825. package/src/map/__tests__/cascade-diff-server.test.ts +0 -434
  826. package/src/map/__tests__/emit-event.test.ts +0 -71
  827. package/src/map/__tests__/lifecycle-bridge.test.ts +0 -430
  828. package/src/map/__tests__/mail-bridge.test.ts +0 -321
  829. package/src/map/__tests__/permission-forwarding.test.ts +0 -143
  830. package/src/map/__tests__/sidecar-diff-install-smoke.test.ts +0 -90
  831. package/src/map/__tests__/sidecar-integration.test.ts +0 -190
  832. package/src/map/__tests__/task-bridge.test.ts +0 -153
  833. package/src/map/__tests__/trajectory-reporter.test.ts +0 -173
  834. package/src/map/acp-bridge.ts +0 -293
  835. package/src/map/cascade-action-handler.ts +0 -205
  836. package/src/map/cascade-bridge.ts +0 -339
  837. package/src/map/cascade-diff-server.ts +0 -404
  838. package/src/map/cc-swarm-hooks.ts +0 -242
  839. package/src/map/coordination-handler.ts +0 -232
  840. package/src/map/index.ts +0 -18
  841. package/src/map/lifecycle-bridge.ts +0 -236
  842. package/src/map/mail-bridge.ts +0 -263
  843. package/src/map/repo-workspace.ts +0 -82
  844. package/src/map/server.ts +0 -758
  845. package/src/map/sidecar.ts +0 -826
  846. package/src/map/task-bridge.ts +0 -89
  847. package/src/map/trajectory-reporter.ts +0 -124
  848. package/src/map/types.ts +0 -304
  849. package/src/mcp/__tests__/mcp-server-v2.test.ts +0 -236
  850. package/src/mcp/index.ts +0 -6
  851. package/src/mcp/mcp-server-v2.ts +0 -485
  852. package/src/mcp/tools/done-v2.ts +0 -213
  853. package/src/mcp/types.ts +0 -432
  854. package/src/metrics/__tests__/metrics.test.ts +0 -205
  855. package/src/metrics/index.ts +0 -13
  856. package/src/metrics/metrics.ts +0 -151
  857. package/src/metrics/types.ts +0 -63
  858. package/src/roles/__tests__/config-loader.test.ts +0 -540
  859. package/src/roles/builtin/coordinator.ts +0 -75
  860. package/src/roles/builtin/generic.ts +0 -39
  861. package/src/roles/builtin/index.ts +0 -51
  862. package/src/roles/builtin/integrator.ts +0 -62
  863. package/src/roles/builtin/monitor.ts +0 -65
  864. package/src/roles/builtin/worker.ts +0 -134
  865. package/src/roles/capabilities.ts +0 -257
  866. package/src/roles/config-loader.ts +0 -405
  867. package/src/roles/index.ts +0 -141
  868. package/src/roles/registry.ts +0 -713
  869. package/src/roles/types.ts +0 -344
  870. package/src/store/index.ts +0 -8
  871. package/src/store/types/agents.ts +0 -69
  872. package/src/store/types/events.ts +0 -91
  873. package/src/store/types/index.ts +0 -9
  874. package/src/store/types/messages.ts +0 -32
  875. package/src/store/types/primitives.ts +0 -9
  876. package/src/store/types/tasks.ts +0 -124
  877. package/src/teams/__tests__/team-manager-v2.test.ts +0 -425
  878. package/src/teams/__tests__/team-runtime-v2.test.ts +0 -402
  879. package/src/teams/index.ts +0 -29
  880. package/src/teams/seed-defaults.ts +0 -83
  881. package/src/teams/team-loader.ts +0 -476
  882. package/src/teams/team-manager-v2.ts +0 -343
  883. package/src/teams/team-runtime-v2.ts +0 -943
  884. package/src/teams/types.ts +0 -276
  885. package/src/trigger/__tests__/cron-service.test.ts +0 -548
  886. package/src/trigger/__tests__/scheduler.test.ts +0 -371
  887. package/src/trigger/__tests__/system-event-queue.test.ts +0 -147
  888. package/src/trigger/__tests__/trigger-system-v2.test.ts +0 -257
  889. package/src/trigger/__tests__/wake-manager.test.ts +0 -356
  890. package/src/trigger/__tests__/webhook-handler.test.ts +0 -567
  891. package/src/trigger/index.ts +0 -110
  892. package/src/trigger/queue/index.ts +0 -21
  893. package/src/trigger/queue/system-event-queue.ts +0 -232
  894. package/src/trigger/queue/types.ts +0 -149
  895. package/src/trigger/sources/cron/cron-service.ts +0 -499
  896. package/src/trigger/sources/cron/index.ts +0 -41
  897. package/src/trigger/sources/cron/scheduler.ts +0 -344
  898. package/src/trigger/sources/cron/types.ts +0 -333
  899. package/src/trigger/sources/index.ts +0 -10
  900. package/src/trigger/sources/webhook/index.ts +0 -25
  901. package/src/trigger/sources/webhook/types.ts +0 -205
  902. package/src/trigger/sources/webhook/webhook-handler.ts +0 -410
  903. package/src/trigger/strategies/ai-router.ts +0 -170
  904. package/src/trigger/trigger-system-v2.ts +0 -536
  905. package/src/trigger/types.ts +0 -228
  906. package/src/trigger/wake/index.ts +0 -22
  907. package/src/trigger/wake/types.ts +0 -162
  908. package/src/trigger/wake/wake-manager.ts +0 -390
  909. package/src/workspace/__tests__/git-cascade-adapter.test.ts +0 -563
  910. package/src/workspace/__tests__/land-dispatch.test.ts +0 -214
  911. package/src/workspace/__tests__/self-driving-yaml.test.ts +0 -122
  912. package/src/workspace/__tests__/shared-worktree-refcount.test.ts +0 -154
  913. package/src/workspace/__tests__/standalone-mode.test.ts +0 -118
  914. package/src/workspace/__tests__/workspace-manager-v3.test.ts +0 -245
  915. package/src/workspace/__tests__/yaml-schema.test.ts +0 -210
  916. package/src/workspace/config.ts +0 -165
  917. package/src/workspace/git-cascade-adapter.ts +0 -1213
  918. package/src/workspace/index.ts +0 -110
  919. package/src/workspace/landing/__tests__/strategies.test.ts +0 -184
  920. package/src/workspace/landing/direct-push.ts +0 -91
  921. package/src/workspace/landing/index.ts +0 -40
  922. package/src/workspace/landing/merge-to-parent.ts +0 -229
  923. package/src/workspace/landing/optimistic-push.ts +0 -36
  924. package/src/workspace/landing/queue-to-branch.ts +0 -108
  925. package/src/workspace/merge-queue/__tests__/conflict-resolution-git.e2e.test.ts +0 -641
  926. package/src/workspace/merge-queue/__tests__/conflict-resolution.test.ts +0 -707
  927. package/src/workspace/merge-queue/__tests__/merge-queue-concurrent.test.ts +0 -628
  928. package/src/workspace/merge-queue/__tests__/merge-queue-edge-cases.test.ts +0 -1217
  929. package/src/workspace/merge-queue/__tests__/merge-queue.test.ts +0 -506
  930. package/src/workspace/merge-queue/__tests__/real-git-operations.e2e.test.ts +0 -556
  931. package/src/workspace/merge-queue/__tests__/resolver-flow.test.ts +0 -472
  932. package/src/workspace/merge-queue/index.ts +0 -38
  933. package/src/workspace/merge-queue/merge-queue.ts +0 -585
  934. package/src/workspace/merge-queue/schema.ts +0 -98
  935. package/src/workspace/merge-queue/types.ts +0 -316
  936. package/src/workspace/pool/__tests__/worktree-pool.integration.test.ts +0 -1281
  937. package/src/workspace/pool/__tests__/worktree-pool.test.ts +0 -590
  938. package/src/workspace/pool/index.ts +0 -26
  939. package/src/workspace/pool/types.ts +0 -276
  940. package/src/workspace/pool/worktree-pool.ts +0 -659
  941. package/src/workspace/recovery/__tests__/auto-resolve-integration.test.ts +0 -127
  942. package/src/workspace/recovery/__tests__/spawn-resolver.test.ts +0 -139
  943. package/src/workspace/recovery/__tests__/strategies.test.ts +0 -145
  944. package/src/workspace/recovery/abandon.ts +0 -51
  945. package/src/workspace/recovery/auto-resolve.ts +0 -119
  946. package/src/workspace/recovery/defer.ts +0 -23
  947. package/src/workspace/recovery/escalate.ts +0 -30
  948. package/src/workspace/recovery/index.ts +0 -58
  949. package/src/workspace/recovery/spawn-resolver.ts +0 -152
  950. package/src/workspace/recovery/types.ts +0 -54
  951. package/src/workspace/strategies/index.ts +0 -18
  952. package/src/workspace/strategies/optimistic.ts +0 -139
  953. package/src/workspace/strategies/queue.ts +0 -81
  954. package/src/workspace/strategies/registry.ts +0 -89
  955. package/src/workspace/strategies/trunk.ts +0 -123
  956. package/src/workspace/strategies/types.ts +0 -145
  957. package/src/workspace/topology/__tests__/yaml-driven.test.ts +0 -345
  958. package/src/workspace/topology/index.ts +0 -18
  959. package/src/workspace/topology/no-workspace.ts +0 -39
  960. package/src/workspace/topology/types.ts +0 -116
  961. package/src/workspace/topology/yaml-driven.ts +0 -316
  962. package/src/workspace/types-v3.ts +0 -162
  963. package/src/workspace/types.ts +0 -541
  964. package/src/workspace/workspace-manager.ts +0 -1577
  965. package/src/workspace/yaml-schema.ts +0 -216
  966. package/test_fixtures/README.md +0 -425
  967. package/test_fixtures/fixtures/behaviors/coordinators.ts +0 -196
  968. package/test_fixtures/fixtures/behaviors/index.ts +0 -62
  969. package/test_fixtures/fixtures/behaviors/integrators.ts +0 -143
  970. package/test_fixtures/fixtures/behaviors/monitors.ts +0 -199
  971. package/test_fixtures/fixtures/behaviors/workers.ts +0 -348
  972. package/test_fixtures/fixtures/index.ts +0 -7
  973. package/test_fixtures/fixtures/projects/index.ts +0 -23
  974. package/test_fixtures/fixtures/projects/project-with-specs.ts +0 -44
  975. package/test_fixtures/fixtures/projects/typescript-project.ts +0 -200
  976. package/test_fixtures/fixtures/repos/index.ts +0 -6
  977. package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -299
  978. package/test_fixtures/fixtures/repos/types.ts +0 -174
  979. package/test_fixtures/harness/assertions/harness-assertions.ts +0 -752
  980. package/test_fixtures/harness/assertions/index.ts +0 -8
  981. package/test_fixtures/harness/index.ts +0 -15
  982. package/test_fixtures/harness/simulator/agent-simulator.ts +0 -768
  983. package/test_fixtures/harness/simulator/behavior-executor.ts +0 -580
  984. package/test_fixtures/harness/simulator/index.ts +0 -14
  985. package/test_fixtures/harness/simulator/types.ts +0 -459
  986. package/test_fixtures/harness/test-harness.ts +0 -770
  987. package/test_fixtures/harness/timing/event-stepper.ts +0 -344
  988. package/test_fixtures/harness/timing/index.ts +0 -8
  989. package/tsconfig.json +0 -21
  990. package/vitest.config.ts +0 -30
  991. package/vitest.e2e.config.ts +0 -28
  992. package/vitest.setup.ts +0 -12
@@ -1,2187 +0,0 @@
1
- /**
2
- * AgentManager V2 — Uses AgentStore + InboxAdapter + TasksAdapter
3
- *
4
- * Replaces EventStore/MessageRouter dependencies with the adapter layer.
5
- * Messages flow through agent-inbox, tasks through opentasks,
6
- * agent lifecycle state in AgentStore (minimal SQLite).
7
- *
8
- * @module agent/agent-manager-v2
9
- */
10
-
11
- import { nanoid } from "nanoid";
12
- import {
13
- uniqueNamesGenerator,
14
- adjectives,
15
- animals,
16
- } from "unique-names-generator";
17
- import {
18
- AgentFactory,
19
- type Session,
20
- type AgentHandle,
21
- type ExtendedSessionUpdate,
22
- type PermissionMode,
23
- } from "acp-factory";
24
- import {
25
- AgentStore,
26
- type AgentRecord,
27
- type SessionRecord,
28
- } from "./agent-store.js";
29
- import type {
30
- AgentId,
31
- TaskId,
32
- Timestamp,
33
- Agent,
34
- AgentState,
35
- } from "../store/types/index.js";
36
- import type {
37
- SpawnAgentOptions,
38
- SpawnedAgent,
39
- AgentFilter,
40
- AgentHierarchy,
41
- AgentHierarchyNode,
42
- HierarchyOptions,
43
- ActiveSession,
44
- AgentStopReason,
45
- HeadManagerOptions,
46
- SystemPromptContext,
47
- AgentLifecycleCallback,
48
- AgentLifecycleEvent,
49
- AgentConfig,
50
- ContinueAgentOptions,
51
- MCPServerStdioConfig,
52
- } from "./types.js";
53
- import { AgentManagerError } from "./types.js";
54
- import type { RoleRegistry, Capability } from "../roles/types.js";
55
- import { AGENT_CAPABILITIES } from "../roles/capabilities.js";
56
- import { DefaultRoleRegistry } from "../roles/registry.js";
57
- import { generateSystemPrompt } from "./system-prompt.js";
58
- import type { WorkspaceManager, Workspace } from "../workspace/types.js";
59
- import {
60
- terminateWithChangeConsolidation,
61
- type WorkspaceProvider,
62
- type CascadeAgentManager,
63
- } from "../lifecycle/cascade.js";
64
- import { AgentTokenManager } from "../auth/token.js";
65
- import type { InboxAdapter } from "../adapters/types.js";
66
- import type { TasksAdapter } from "../adapters/types.js";
67
- import type { AgentManager, SpawnInterceptor } from "./agent-manager.js";
68
- import { getPermissionOverlay } from "../dispatch/permission-overlay.js";
69
- import { evaluatePermission } from "../dispatch/permission-evaluator.js";
70
-
71
- // ─────────────────────────────────────────────────────────────────
72
- // Helper
73
- // ─────────────────────────────────────────────────────────────────
74
-
75
- /**
76
- * Derive the canonical Claude Code tool name from a `permission_request`
77
- * `toolCall` object.
78
- *
79
- * Why this is needed: claude-agent-acp's `toolInfoFromToolUse` mangles
80
- * built-in tool names into display titles (e.g., `Read /tmp/x` instead of
81
- * `Read`). MCP tools use their fully-qualified `mcp__server__tool` name as
82
- * the title. The `kind` field (Claude SDK's tool category) is the
83
- * cleanest signal for built-ins, with the input shape disambiguating
84
- * within a category (e.g., `edit` covers Write/Edit/MultiEdit — we look
85
- * at `old_string`/`edits` to pick which).
86
- *
87
- * Pure: no side effects; safe to call from the prompt iterator.
88
- */
89
- function deriveToolName(toolCall: {
90
- title?: string;
91
- kind?: string;
92
- rawInput?: unknown;
93
- } | undefined): string {
94
- const title = toolCall?.title ?? "";
95
- const kind = toolCall?.kind ?? "";
96
- // MCP tools — title is the canonical name.
97
- if (title.startsWith("mcp__")) return title.split(/\s/)[0] ?? "";
98
- const input =
99
- toolCall?.rawInput && typeof toolCall.rawInput === "object"
100
- ? (toolCall.rawInput as Record<string, unknown>)
101
- : {};
102
- switch (kind) {
103
- case "read":
104
- return "Read";
105
- case "execute":
106
- return "Bash";
107
- case "edit":
108
- if ("edits" in input) return "MultiEdit";
109
- if ("old_string" in input) return "Edit";
110
- return "Write";
111
- case "search":
112
- return "path" in input ? "Grep" : "Glob";
113
- case "think":
114
- return "Task";
115
- case "switch_mode":
116
- return "ExitPlanMode";
117
- }
118
- // Fallback: first whitespace-delimited token of the title (Read/Write/
119
- // Edit cases not caught above; built-ins newer than this matrix).
120
- return title.split(/\s/)[0] ?? "";
121
- }
122
-
123
- function getSpawnCapability(childRole: string): Capability {
124
- const baseRole = childRole.split(".")[0];
125
- switch (baseRole) {
126
- case "worker":
127
- return AGENT_CAPABILITIES.SPAWN_WORKER;
128
- case "integrator":
129
- return AGENT_CAPABILITIES.SPAWN_INTEGRATOR;
130
- case "monitor":
131
- return AGENT_CAPABILITIES.SPAWN_MONITOR;
132
- case "coordinator":
133
- return AGENT_CAPABILITIES.SPAWN_CUSTOM;
134
- default:
135
- return `agent.spawn.${childRole}` as Capability;
136
- }
137
- }
138
-
139
- function generateName(): string {
140
- return uniqueNamesGenerator({
141
- dictionaries: [adjectives, animals],
142
- separator: "-",
143
- length: 2,
144
- });
145
- }
146
-
147
- // ─────────────────────────────────────────────────────────────────
148
- // Configuration
149
- // ─────────────────────────────────────────────────────────────────
150
-
151
- /** Minimal health check interface (monitor module removed in V2) */
152
- interface HealthCheckService {
153
- startForCoordinator(agentId: string): void;
154
- stopForCoordinator(agentId: string): void;
155
- }
156
-
157
- export interface AgentManagerV2Config {
158
- defaultPermissionMode?: PermissionMode;
159
- defaultAgentType?: string;
160
- defaultCwd?: string;
161
- workspaceManager?: WorkspaceManager;
162
- roleRegistry?: RoleRegistry;
163
- healthCheckService?: HealthCheckService;
164
- agentTokenManager?: AgentTokenManager;
165
- serverUrl?: string;
166
- serverToken?: string;
167
- /** Control socket path for MCP subprocess lifecycle RPC */
168
- controlSocketPath?: string;
169
- /**
170
- * Default opentasks resource ID hosted on the OpenHive hub. When set,
171
- * spawn paths build `taskRef = { resource_id: <this>, node_id: task_id }`
172
- * automatically from `SpawnAgentOptions.task_id` (for any spawn where
173
- * `resolveTaskRef` returned undefined AND the caller didn't supply an
174
- * explicit `taskRef`).
175
- *
176
- * Operators set this once at swarm registration for the common
177
- * single-graph case. Multi-graph deployments should use `resolveTaskRef`
178
- * instead.
179
- */
180
- taskResourceId?: string;
181
-
182
- /**
183
- * Multi-graph resolver. Called at every spawn; return a `TaskRef` to set
184
- * the binding or `undefined` to fall through to the `taskResourceId`
185
- * default. Explicit `SpawnAgentOptions.taskRef` always wins over both.
186
- *
187
- * Keep cheap — runs per-spawn.
188
- */
189
- resolveTaskRef?: (
190
- spawnOptions: SpawnAgentOptions
191
- ) => import("git-cascade/events").TaskRef | undefined;
192
- }
193
-
194
- // ─────────────────────────────────────────────────────────────────
195
- // Factory
196
- // ─────────────────────────────────────────────────────────────────
197
-
198
- export function createAgentManagerV2(
199
- agentStore: AgentStore,
200
- inboxAdapter: InboxAdapter,
201
- tasksAdapter: TasksAdapter,
202
- config: AgentManagerV2Config = {}
203
- ): AgentManager {
204
- const {
205
- defaultPermissionMode = "auto-approve",
206
- defaultAgentType = "claude-code",
207
- defaultCwd = process.cwd(),
208
- workspaceManager,
209
- roleRegistry = new DefaultRoleRegistry(),
210
- healthCheckService,
211
- serverUrl,
212
- serverToken,
213
- agentTokenManager,
214
- controlSocketPath,
215
- taskResourceId,
216
- resolveTaskRef,
217
- } = config;
218
-
219
- // In-memory state
220
- const activeSessions = new Map<AgentId, ActiveSession>();
221
- const agentWorkspaces = new Map<AgentId, Workspace>();
222
- const lifecycleListeners = new Set<AgentLifecycleCallback>();
223
- // In-flight fire-and-forget terminate() promises (e.g. the promptUntilDone
224
- // completion poller tears the agent down without awaiting it, to keep
225
- // completion latency low). close() awaits these so shutdown cannot return
226
- // while a group-kill is still racing — which would let process.exit orphan
227
- // the subtree.
228
- const pendingTerminations = new Set<Promise<unknown>>();
229
- let spawnInterceptor: SpawnInterceptor | null = null;
230
- let isShuttingDown = false;
231
- let mapServerUrl: string | undefined;
232
-
233
- // Swarmkit integration configs (set via late-binding setters from boot-v2)
234
- let minimemConfig: { enabled: boolean; dir?: string; provider?: string; global?: boolean } | undefined;
235
- let skilltreeConfig: { enabled: boolean; basePath?: string; defaultProfile?: string } | undefined;
236
- let sessionlogConfig: { enabled: boolean; sync?: string } | undefined;
237
- // Compiled skill loadouts per role (populated by team runtime)
238
- const skillLoadouts = new Map<string, string>();
239
- // MAP sidecar reference for trajectory reporting (set via setSidecar)
240
- let sidecarRef: { connected: boolean; reportCheckpoint(cp: any): Promise<any> } | null = null;
241
-
242
- // TopologyPolicy for workspace allocation (Phase 3+); set via setTopologyPolicy.
243
- // When null, createWorkspaceForRole falls back to legacy role-name dispatch.
244
- let topologyPolicy:
245
- | import('../workspace/topology/types.js').TopologyPolicy
246
- | null = null;
247
-
248
- // ── Helpers ──────────────────────────────────────────────────
249
-
250
- function notifyLifecycle(event: AgentLifecycleEvent): void {
251
- for (const listener of lifecycleListeners) {
252
- try {
253
- listener(event);
254
- } catch {
255
- // Ignore listener errors
256
- }
257
- }
258
- }
259
-
260
- function agentRecordToAgent(record: AgentRecord): Agent {
261
- const session = agentStore.getSession(record.id as AgentId);
262
- return {
263
- id: record.id,
264
- name: record.name,
265
- session_id: session?.session_id ?? "",
266
- parent: record.parent_id,
267
- lineage: record.lineage,
268
- state: record.state,
269
- stop_reason: record.stop_reason as Agent["stop_reason"],
270
- task: record.task,
271
- task_id: record.task_id,
272
- role: record.role,
273
- team_instance: record.team,
274
- config: (record.config as Agent["config"]) ?? {},
275
- cwd: record.cwd,
276
- plan: [],
277
- metadata: record.metadata,
278
- created_at: record.created_at,
279
- started_at: record.started_at,
280
- stopped_at: record.stopped_at,
281
- last_activity_at: record.last_activity_at,
282
- };
283
- }
284
-
285
- function buildMcpServerConfig(opts: {
286
- agentId: string;
287
- parentId: string;
288
- taskId: string;
289
- cwd: string;
290
- permissionMode: string;
291
- lineage?: string[];
292
- sessionId?: string;
293
- streamId?: string;
294
- }): MCPServerStdioConfig {
295
- const env: Record<string, string> = {
296
- MACRO_AGENT_ID: opts.agentId,
297
- MACRO_PARENT_ID: opts.parentId,
298
- MACRO_TASK_ID: opts.taskId,
299
- MACRO_AGENT_CWD: opts.cwd,
300
- MACRO_PERMISSION_MODE: opts.permissionMode,
301
- MACRO_STREAM_ID: opts.streamId ?? "",
302
- // Point to inbox socket for agent-inbox MCP tools
303
- INBOX_SOCKET_PATH: inboxAdapter.socketPath,
304
- // Control socket for lifecycle RPC (spawn, terminate, etc.)
305
- MACRO_CONTROL_SOCKET_PATH: controlSocketPath ?? "",
306
- // Base directory for AgentStore + inbox in MCP subprocess
307
- MACRO_BASE_DIR: controlSocketPath
308
- ? controlSocketPath.replace(/\/control\.sock$/, "")
309
- : "",
310
- // opentasks client auto-discovers its socket
311
- };
312
-
313
- if (serverUrl) {
314
- env.MACRO_SERVER_URL = serverUrl;
315
- env.MACRO_AGENT_LINEAGE = JSON.stringify(opts.lineage ?? []);
316
- env.MACRO_SESSION_ID = opts.sessionId ?? "";
317
- if (serverToken) env.MACRO_SERVER_TOKEN = serverToken;
318
- if (agentTokenManager) {
319
- env.MACRO_AGENT_TOKEN = agentTokenManager.createToken(opts.agentId);
320
- }
321
- }
322
-
323
- // Use node with local dist path to ensure we run V2 MCP server,
324
- // not a globally installed V1 version.
325
- const mcpEntryPoint = new URL("../../dist/cli/mcp.js", import.meta.url).pathname;
326
-
327
- return {
328
- name: "macro-agent",
329
- command: "node",
330
- args: [mcpEntryPoint],
331
- env,
332
- };
333
- }
334
-
335
- // ── Workspace Helper ─────────────────────────────────────────
336
-
337
- /**
338
- * Execute a TopologyPolicy decision against the WorkspaceManager.
339
- *
340
- * Translates declarative `WorkspaceDecision` into concrete workspace
341
- * allocations. Returns a `Workspace` compatible with the legacy shape
342
- * so the rest of AgentManagerV2 doesn't need to change.
343
- */
344
- async function executeWorkspaceDecision(
345
- agentId: AgentId,
346
- decision: import('../workspace/topology/types.js').WorkspaceDecision,
347
- role?: string,
348
- spawnOptions?: SpawnAgentOptions
349
- ): Promise<Workspace | undefined> {
350
- if (!workspaceManager) return undefined;
351
-
352
- switch (decision.kind) {
353
- case 'none':
354
- case 'share-parent-cwd':
355
- return undefined;
356
-
357
- case 'share-with-agent': {
358
- const worktree = workspaceManager.allocateWorktree({
359
- agentId,
360
- sharedWithAgent: decision.agentId,
361
- });
362
- return {
363
- agentId,
364
- path: worktree.path,
365
- branch: worktree.currentStream
366
- ? `stream/${worktree.currentStream}`
367
- : 'unknown',
368
- streamId: worktree.currentStream ?? '',
369
- role: 'v3', // V3 path — bypass legacy worker task/merge-queue flows
370
- createdAt: worktree.createdAt,
371
- };
372
- }
373
-
374
- case 'attach-to-stream': {
375
- // Record even if no worktree — the topology needs the stream↔role
376
- // mapping for event-driven features like on_parent_advanced.
377
- const attachPolicy = topologyPolicy as unknown as {
378
- recordAgentStream?: (a: string, s: string, role?: string) => void;
379
- };
380
- attachPolicy.recordAgentStream?.(agentId, decision.streamId, role);
381
-
382
- if (!decision.allocateWorktree) {
383
- return undefined;
384
- }
385
- const worktree = workspaceManager.allocateWorktree({
386
- agentId,
387
- streamId: decision.streamId,
388
- });
389
- return {
390
- agentId,
391
- path: worktree.path,
392
- branch: `stream/${decision.streamId}`,
393
- streamId: decision.streamId,
394
- role: 'v3', // V3 path — attach-to-team-root
395
- createdAt: worktree.createdAt,
396
- };
397
- }
398
-
399
- case 'new-stream': {
400
- // If the spawning agent has a taskRef and the streamSpec doesn't
401
- // already carry one, weave it into metadata so the resulting stream
402
- // binds to the OpenTasks node. Explicit streamSpec.metadata.task_ref
403
- // wins.
404
- const taskRef = spawnOptions?.taskRef;
405
- const existingMeta = decision.streamSpec.metadata as
406
- | Record<string, unknown>
407
- | undefined;
408
- const streamSpec = taskRef && !existingMeta?.task_ref
409
- ? {
410
- ...decision.streamSpec,
411
- metadata: { ...(existingMeta ?? {}), task_ref: taskRef },
412
- }
413
- : decision.streamSpec;
414
- const streamId = workspaceManager.createStreamV3(streamSpec);
415
- // Record the mapping in the topology if it supports it (for share-with lookup).
416
- const policy = topologyPolicy as unknown as {
417
- recordAgentStream?: (a: string, s: string, role?: string) => void;
418
- };
419
- policy.recordAgentStream?.(agentId, streamId, role);
420
-
421
- if (!decision.allocateWorktree) {
422
- return undefined;
423
- }
424
- const worktree = workspaceManager.allocateWorktree({
425
- agentId,
426
- streamId,
427
- });
428
- return {
429
- agentId,
430
- path: worktree.path,
431
- branch: `stream/${streamId}`,
432
- streamId,
433
- role: 'v3', // V3 path — new-stream
434
- createdAt: worktree.createdAt,
435
- };
436
- }
437
- }
438
- }
439
-
440
- async function createWorkspaceForRole(
441
- agentId: AgentId,
442
- role: string,
443
- options: SpawnAgentOptions
444
- ): Promise<Workspace | undefined> {
445
- if (!workspaceManager) return undefined;
446
-
447
- // V3 path — TopologyPolicy-driven. Set by boot-v2 when team YAML has
448
- // `macro_agent.workspace`. When set, this takes precedence over the legacy
449
- // capability/role-name dispatch below.
450
- if (topologyPolicy) {
451
- const decision = await topologyPolicy.onAgentSpawn({
452
- agentId,
453
- role,
454
- parentAgentId: options.parent ?? undefined,
455
- parentStreamId: options.streamId,
456
- teamStreamId: (() => {
457
- const stream = (
458
- topologyPolicy as { getAgentStream?: (a: AgentId) => string | null }
459
- ).getAgentStream?.(agentId);
460
- return stream ?? undefined;
461
- })(),
462
- workspaceManager,
463
- getAgentByRole: (r: string) => {
464
- for (const [aid, ws] of agentWorkspaces) {
465
- const rec = agentStore.getAgent(aid);
466
- if (rec?.role === r) return aid;
467
- }
468
- return null;
469
- },
470
- });
471
- return executeWorkspaceDecision(agentId, decision, role, options);
472
- }
473
-
474
- // Capability-based dispatch for programmatic callers that don't use
475
- // team YAML. This is the supported path for libraries that construct
476
- // WorkspaceManager + GitCascadeAdapter directly and spawn agents with
477
- // explicit `capabilities` + `streamId` arguments. It coexists with the
478
- // V3 topology path above.
479
- return capabilityBasedDispatch(agentId, options, workspaceManager);
480
- }
481
-
482
- /**
483
- * Capability-based workspace allocation for programmatic callers.
484
- *
485
- * Matches on `workspace.stream` / `workspace.integrate` / `workspace.worktree`
486
- * capabilities + corresponding streamId/streamConfig args. Delegates to the
487
- * role-shaped WorkspaceManager methods (createWorkerWorkspace,
488
- * createIntegratorWorkspace, createCoordinatorWorkspace).
489
- *
490
- * Not used by team-YAML-driven teams — those go through TopologyPolicy above.
491
- */
492
- async function capabilityBasedDispatch(
493
- agentId: AgentId,
494
- options: SpawnAgentOptions,
495
- ws: WorkspaceManager
496
- ): Promise<Workspace | undefined> {
497
- const capabilities = options.capabilities ?? [];
498
- const streamId = options.streamId;
499
- // Merge taskRef (if set at spawn time) into streamConfig.metadata so that
500
- // adapter.createStream → x-cascade/stream.opened carries the binding to
501
- // OpenTasks. Explicit streamConfig.metadata.task_ref wins if already set.
502
- const streamConfig = options.streamConfig
503
- ? options.taskRef &&
504
- !(options.streamConfig.metadata &&
505
- (options.streamConfig.metadata as Record<string, unknown>).task_ref)
506
- ? {
507
- ...options.streamConfig,
508
- metadata: {
509
- ...(options.streamConfig.metadata ?? {}),
510
- task_ref: options.taskRef,
511
- },
512
- }
513
- : options.streamConfig
514
- : undefined;
515
- const gitCascadeTaskId = options.gitCascadeTaskId;
516
-
517
- if (capabilities.includes("workspace.stream") && streamConfig) {
518
- const newStreamId = ws.createIntegrationStream(agentId, streamConfig);
519
- return ws.createCoordinatorWorkspace(agentId, newStreamId);
520
- }
521
-
522
- if (capabilities.includes("workspace.integrate") && streamId) {
523
- return ws.createIntegratorWorkspace(agentId, streamId);
524
- }
525
-
526
- if (capabilities.includes("workspace.worktree") && streamId) {
527
- const taskId = gitCascadeTaskId ?? agentId;
528
- return ws.createWorkerWorkspace(agentId, taskId, streamId);
529
- }
530
-
531
- // No matching capability — agent inherits parent cwd (no workspace)
532
- return undefined;
533
- }
534
-
535
- // ── Core Lifecycle ───────────────────────────────────────────
536
-
537
- async function spawn(rawOptions: SpawnAgentOptions): Promise<SpawnedAgent> {
538
- if (isShuttingDown) {
539
- throw new AgentManagerError(
540
- "Cannot spawn agent during shutdown",
541
- "SHUTDOWN_IN_PROGRESS"
542
- );
543
- }
544
-
545
- // Apply spawn interceptor (set by TeamRuntime)
546
- const interceptedOptions = spawnInterceptor
547
- ? await spawnInterceptor(rawOptions)
548
- : rawOptions;
549
-
550
- // Resolve taskRef with three-level precedence:
551
- // 1. Explicit `options.taskRef` (caller knows exactly what graph).
552
- // 2. `resolveTaskRef(opts)` (multi-graph deployments decide per spawn).
553
- // 3. `taskResourceId` + `options.task_id` (single-graph default).
554
- // If none resolves, spawn proceeds with no taskRef — cascade events
555
- // land without a task binding (hub back-fills from first commit that
556
- // carries one, if any).
557
- let resolvedTaskRef = interceptedOptions.taskRef;
558
- if (!resolvedTaskRef && resolveTaskRef) {
559
- try {
560
- resolvedTaskRef = resolveTaskRef(interceptedOptions);
561
- } catch (err) {
562
- // Resolver failures must not block spawn. Log + fall through.
563
- // eslint-disable-next-line no-console
564
- console.warn(
565
- "[agent-manager-v2] resolveTaskRef threw; falling back to taskResourceId default:",
566
- err instanceof Error ? err.message : err
567
- );
568
- }
569
- }
570
- if (!resolvedTaskRef && taskResourceId && interceptedOptions.task_id) {
571
- resolvedTaskRef = {
572
- resource_id: taskResourceId,
573
- node_id: String(interceptedOptions.task_id),
574
- };
575
- }
576
- const options = resolvedTaskRef === interceptedOptions.taskRef
577
- ? interceptedOptions
578
- : { ...interceptedOptions, taskRef: resolvedTaskRef };
579
-
580
- const {
581
- task,
582
- task_id,
583
- parent,
584
- cwd = defaultCwd,
585
- permissionMode = defaultPermissionMode,
586
- askForAllTools = false,
587
- subscribeParent = true,
588
- topics = [],
589
- config: agentConfig,
590
- agentType = defaultAgentType,
591
- customPrompt,
592
- interactionPatterns,
593
- role,
594
- team_instance,
595
- capabilities,
596
- } = options;
597
-
598
- // Generate IDs
599
- const agentId = `agent_${nanoid(12)}` as AgentId;
600
- const taskId = (task_id ?? `task_${nanoid(12)}`) as TaskId;
601
- const sessionId = `session_${nanoid(12)}`;
602
- const name = generateName();
603
-
604
- // Validate parent exists
605
- if (parent) {
606
- const parentRecord = agentStore.getAgent(parent);
607
- if (!parentRecord) {
608
- throw new AgentManagerError(
609
- `Parent agent ${parent} not found`,
610
- "AGENT_NOT_FOUND",
611
- parent
612
- );
613
- }
614
-
615
- // Check spawn capability
616
- if (role) {
617
- const requiredCap = getSpawnCapability(role);
618
- const parentRole = parentRecord.role;
619
- if (
620
- !roleRegistry.hasCapability(parentRole, requiredCap) &&
621
- !roleRegistry.hasCapability(parentRole, AGENT_CAPABILITIES.SPAWN_CUSTOM)
622
- ) {
623
- throw new AgentManagerError(
624
- `Parent ${parent} (role: ${parentRole}) lacks capability ${requiredCap}`,
625
- "CAPABILITY_DENIED",
626
- parent
627
- );
628
- }
629
- }
630
- }
631
-
632
- // Compute lineage
633
- const lineage: AgentId[] = [];
634
- if (parent) {
635
- const parentRecord = agentStore.getAgent(parent);
636
- if (parentRecord) {
637
- lineage.push(...parentRecord.lineage, parent);
638
- }
639
- }
640
-
641
- // Generate system prompt
642
- const resolvedRole = role
643
- ? roleRegistry.resolveRole(role)
644
- : undefined;
645
- const systemPromptContext: SystemPromptContext = {
646
- agentId,
647
- task,
648
- taskId,
649
- parentId: parent ?? null,
650
- isHeadManager: !parent,
651
- lineage,
652
- role,
653
- };
654
- let systemPrompt = generateSystemPrompt(systemPromptContext);
655
- if (customPrompt) {
656
- systemPrompt += `\n\n## Role Instructions\n\n${customPrompt}`;
657
- } else if (resolvedRole?.systemPrompt) {
658
- systemPrompt += `\n\n## Role Instructions\n\n${resolvedRole.systemPrompt}`;
659
- }
660
- if (interactionPatterns?.length) {
661
- systemPrompt += `\n\n${interactionPatterns.join("\n\n")}`;
662
- }
663
-
664
- // Persist agent in store. Stash taskRef in metadata so done()'s
665
- // lifecycle context can read it without separate plumbing — this is the
666
- // path that makes per-commit task_ref binding work end-to-end.
667
- const now = Date.now() as Timestamp;
668
- const agentRecord: AgentRecord = {
669
- id: agentId,
670
- name,
671
- role: role ?? (parent ? "worker" : "coordinator"),
672
- state: "running",
673
- parent_id: parent ?? null,
674
- lineage,
675
- team: team_instance,
676
- scope: team_instance ?? "default",
677
- task: task ?? "",
678
- task_id: taskId,
679
- cwd,
680
- capabilities: capabilities ?? resolvedRole?.capabilities ?? [],
681
- created_at: now,
682
- started_at: now,
683
- config: agentConfig as Record<string, unknown>,
684
- metadata: {
685
- ...(options.taskRef ? { task_ref: options.taskRef } : {}),
686
- // Persist isolatedSettings so resume() applies the same agentMeta
687
- // policy without needing the original SpawnAgentOptions.
688
- ...(options.isolatedSettings ? { isolatedSettings: true } : {}),
689
- },
690
- };
691
- agentStore.putAgent(agentRecord);
692
-
693
- let handle: AgentHandle | undefined;
694
- let workspace: Workspace | undefined;
695
-
696
- try {
697
- // Spawn process via acp-factory
698
- const env: Record<string, string> = {
699
- ...agentConfig?.env,
700
- };
701
-
702
- // Configure cc-swarm to connect to macro-agent's local MAP server.
703
- // These env vars are read by cc-swarm hooks in the Claude Code process
704
- // (not the MCP subprocess), so they must be in the agent process env.
705
- if (mapServerUrl) {
706
- env.SWARM_MAP_SERVER = mapServerUrl;
707
- env.SWARM_MAP_ENABLED = "true";
708
- env.SWARM_MAP_SCOPE = `swarm:${agentId}`;
709
- env.SWARM_SESSIONLOG_ENABLED = "true";
710
- env.SWARM_SESSIONLOG_SYNC = "metrics";
711
- }
712
-
713
- handle = await AgentFactory.spawn(agentType, {
714
- permissionMode,
715
- env,
716
- });
717
-
718
- // Create workspace if applicable
719
- workspace = await createWorkspaceForRole(agentId, role ?? "", options);
720
- if (workspace) {
721
- agentWorkspaces.set(agentId, workspace);
722
-
723
- // Create and claim git-cascade task for workers
724
- if (
725
- workspace.role === "worker" &&
726
- workspace.streamId &&
727
- workspaceManager
728
- ) {
729
- const dpTaskId = options.gitCascadeTaskId ?? agentId;
730
- workspaceManager.createTask(workspace.streamId, {
731
- title: task ?? `Task for ${agentId}`,
732
- });
733
- workspaceManager.claimTask(dpTaskId, agentId, workspace.path);
734
- }
735
-
736
- agentStore.updateAgent(agentId, {
737
- cwd: workspace.path,
738
- workspace_path: workspace.path,
739
- workspace_stream_id: workspace.streamId,
740
- });
741
- }
742
-
743
- const effectiveCwd = workspace?.path ?? cwd;
744
-
745
- // Build MCP server config
746
- const macroAgentMcp = buildMcpServerConfig({
747
- agentId,
748
- parentId: parent ?? "",
749
- taskId,
750
- cwd: effectiveCwd,
751
- permissionMode,
752
- lineage,
753
- sessionId,
754
- streamId: workspace?.streamId,
755
- });
756
-
757
- // Convert to acp-factory format
758
- const mcpServers = [
759
- {
760
- name: macroAgentMcp.name,
761
- command: macroAgentMcp.command,
762
- args: macroAgentMcp.args ?? [],
763
- env: Object.entries(macroAgentMcp.env ?? {}).map(([k, v]) => ({
764
- name: k,
765
- value: v,
766
- })),
767
- },
768
- ...(agentConfig?.mcpServers?.map((s) => {
769
- if ("command" in s) {
770
- return {
771
- name: s.name,
772
- command: s.command,
773
- args: s.args ?? [],
774
- env: Object.entries(s.env ?? {}).map(([k, v]) => ({
775
- name: k,
776
- value: v,
777
- })),
778
- };
779
- }
780
- return {
781
- name: s.name,
782
- type: s.type,
783
- url: s.url,
784
- headers: Object.entries(s.headers ?? {}).map(([k, v]) => ({
785
- name: k,
786
- value: v,
787
- })),
788
- };
789
- }) ?? []),
790
- ];
791
-
792
- // Always-on subsystem MCP servers (the "trinity"). The macro-agent
793
- // architecture docs describe agent-inbox + opentasks as separate MCP
794
- // servers available to spawned workers, but until this entry block
795
- // existed they were only reachable when host-level Claude plugins
796
- // happened to have wired them. That left mail-inbound workers
797
- // (`parent: null` + `isolatedSettings: true`) without inbox/tasks
798
- // tools — see openhive-2 docs/LOADOUTS_DESIGN.md "Loadout-provided
799
- // MCP servers" live finding 2026-05-03.
800
- //
801
- // Registering them here makes them per-spawn defaults independent
802
- // of host configuration. Caller-supplied `agentConfig.mcpServers`
803
- // remains additive (Option C / "hybrid"): the trinity is always
804
- // there, callers can layer more on top.
805
-
806
- // agent-inbox — exposes send_message, check_inbox, read_thread,
807
- // list_agents via the InboxMcpProxy stdio bridge.
808
- if (inboxAdapter.socketPath) {
809
- const inboxProxyEntry = new URL(
810
- "../../dist/cli/inbox-mcp-proxy.js",
811
- import.meta.url,
812
- ).pathname;
813
- mcpServers.push({
814
- name: "agent-inbox",
815
- command: "node",
816
- args: [inboxProxyEntry],
817
- env: [
818
- { name: "INBOX_SOCKET_PATH", value: inboxAdapter.socketPath },
819
- { name: "MACRO_AGENT_ID", value: agentId },
820
- ],
821
- } as any);
822
- }
823
-
824
- // opentasks — exposes task, link, annotate, query via the
825
- // `opentasks mcp` CLI subcommand. The package's dist/mcp/stdio.js
826
- // is an exports-only module (no auto-start); the CLI's `mcp`
827
- // subcommand is what actually wires StdioServerTransport. Conditional
828
- // on tasksAdapter.connected — when the daemon isn't running, skip
829
- // rather than mount a server that would fail at every tool call.
830
- if (tasksAdapter.connected) {
831
- const opentasksCliEntry = new URL(
832
- "opentasks/dist/cli.js",
833
- import.meta.url,
834
- ).pathname;
835
- mcpServers.push({
836
- name: "opentasks",
837
- command: "node",
838
- args: [opentasksCliEntry, "mcp"],
839
- env: [],
840
- } as any);
841
- }
842
-
843
- // Register minimem MCP server (agent-type independent — works for any MCP-capable agent)
844
- if (minimemConfig?.enabled) {
845
- mcpServers.push({
846
- name: "minimem",
847
- command: "minimem",
848
- args: [
849
- "mcp",
850
- "--dir", minimemConfig.dir ?? ".swarm/minimem/",
851
- "--provider", minimemConfig.provider ?? "auto",
852
- ...(minimemConfig.global ? ["--global"] : []),
853
- ],
854
- env: [],
855
- } as any);
856
- }
857
-
858
- // Build agentMeta. Two layers:
859
- //
860
- // 1. `settingSources: []` — when the caller requests isolated
861
- // settings (mail-inbound dispatch workers via
862
- // SpawnAgentOptions.isolatedSettings), strip user/project/local
863
- // setting sources so the worker doesn't load the host's
864
- // claude-code-swarm / oh-my-claudecode / etc plugin MCP servers
865
- // — those plugins assume host-shaped environment (sockets,
866
- // daemons) and hang at session/new MCP-init when missing.
867
- // Interactive `multiagent` callers leave this false so their
868
- // installed plugins load normally.
869
- //
870
- // 2. `settings.permissions` — when the caller passes
871
- // SpawnAgentOptions.permissions (e.g., from a materialized
872
- // loadout), wire the rules inline via the Claude Agent SDK's
873
- // session-level settings pass-through. Verified live: `deny`
874
- // wins even over `permissionMode: "auto-approve"`. Inline
875
- // wiring avoids file collisions when concurrent workers share
876
- // a CWD (no `.claude/settings.json` written to disk).
877
- //
878
- // SDK contract pinned by the boundary test in
879
- // `src/agent/__tests__/agent-manager-v2.permissions.test.ts` —
880
- // it captures the literal `agentMeta` argument passed to
881
- // `handle.createSession` and asserts both `settingSources: []`
882
- // AND `settings.permissions` are present together (the
883
- // interaction between filesystem-stripping and inline
884
- // reconciliation that the SDK's docs don't fully spell out).
885
- // If a future SDK version changes how `settings` reconciles
886
- // with empty `settingSources`, that test will catch it.
887
- //
888
- // `ask` rules collapse based on `fullAutonomous`:
889
- // - fullAutonomous: true → ask → allow (autonomous worker
890
- // opts to proceed when there's no human to answer)
891
- // - fullAutonomous: false → ask → deny (safe default;
892
- // autonomous workers shouldn't make judgment calls)
893
- const claudeCodeOptions: Record<string, any> = {};
894
- if (options.isolatedSettings || permissionMode === "interactive") {
895
- claudeCodeOptions.settingSources = [];
896
- }
897
- if (options.permissions) {
898
- const { allow = [], deny = [], ask = [] } = options.permissions;
899
- const finalAllow = options.fullAutonomous ? [...allow, ...ask] : [...allow];
900
- const finalDeny = options.fullAutonomous ? [...deny] : [...deny, ...ask];
901
- claudeCodeOptions.settings = {
902
- permissions: {
903
- ...(finalAllow.length ? { allow: finalAllow } : {}),
904
- ...(finalDeny.length ? { deny: finalDeny } : {}),
905
- },
906
- };
907
- }
908
- // P3 spike: when an agent should funnel every tool call through the host
909
- // (so the prompt-iterator handler can apply runtime overlays), set
910
- // `ask: ['*']` on settings.permissions. The SDK then consults canUseTool
911
- // for every tool, which emits `permission_request` session updates.
912
- // Used for dispatch-target agents (mail+reuse, ACP+reuse) that need
913
- // dynamic enforcement; chat agents and parented children stay on
914
- // their session's static rules.
915
- if (options.askForAllTools) {
916
- const existingPerms =
917
- claudeCodeOptions.settings?.permissions ?? {};
918
- claudeCodeOptions.settings = {
919
- ...claudeCodeOptions.settings,
920
- permissions: {
921
- ...existingPerms,
922
- ask: ["*"],
923
- },
924
- };
925
- }
926
-
927
- // 3. Runtime permission overlay enforcement lives in the prompt
928
- // iterator (see `prompt()` below), NOT here at spawn time.
929
- //
930
- // Background: an earlier design installed a Claude SDK PreToolUse
931
- // hook here that closed over the per-process permission-overlay
932
- // registry. That mechanism was verified broken: function callbacks
933
- // inside arrays don't survive JSON.stringify across the
934
- // macro-agent → claude-agent-acp stdio JSON-RPC boundary, so the
935
- // hook arrived as `null` at the SDK and silently no-op'd.
936
- //
937
- // The current design uses ACP's `permission_request` session
938
- // update path instead. When an agent is spawned with
939
- // `askForAllTools: true` + `permissionMode: 'interactive'`, the
940
- // SDK consults `canUseTool` on every tool call, claude-agent-acp
941
- // converts that into a `client.requestPermission` call, and
942
- // acp-factory emits it as a `permission_request` session update.
943
- // The prompt iterator below intercepts those updates, evaluates
944
- // against the overlay, and responds via `respondPermission`.
945
- // See `docs/PERMISSION_OVERLAY_ACP_DESIGN.md` for the full design.
946
-
947
- const agentMeta = Object.keys(claudeCodeOptions).length > 0
948
- ? { claudeCode: { options: claudeCodeOptions } }
949
- : undefined;
950
-
951
- // Build capabilities context + skill-tree loadout for system prompt
952
- // Matches cc-swarm's context injection pattern (role-aware, tool-specific)
953
- let contextSuffix = "";
954
- try {
955
- const { buildCapabilitiesContext } = await import("../integrations/context-builder.js");
956
- contextSuffix = buildCapabilitiesContext({
957
- role: parent ? (role ?? "worker") : null, // null = orchestrator, string = spawned agent
958
- teamName: team_instance ?? undefined,
959
- minimem: minimemConfig
960
- ? { enabled: minimemConfig.enabled, status: "ready" }
961
- : undefined,
962
- skilltree: skilltreeConfig
963
- ? { enabled: skilltreeConfig.enabled, status: "ready", profile: skilltreeConfig.defaultProfile }
964
- : undefined,
965
- sessionlog: sessionlogConfig
966
- ? { enabled: sessionlogConfig.enabled, sync: sessionlogConfig.sync }
967
- : undefined,
968
- mesh: mapServerUrl ? { enabled: false } : undefined, // mesh state from config
969
- map: mapServerUrl
970
- ? { enabled: true, scope: `swarm:${agentId}`, status: "connected" }
971
- : undefined,
972
- opentasks: tasksAdapter.connected
973
- ? { enabled: true, status: "connected" }
974
- : undefined,
975
- inbox: { enabled: true },
976
- });
977
- } catch { /* context builder not available */ }
978
-
979
- // Inject skill-tree loadout if available for this role
980
- const roleLoadout = role ? skillLoadouts.get(role) : undefined;
981
- if (roleLoadout) {
982
- contextSuffix += `\n\n## Skills\n\n${roleLoadout}`;
983
- }
984
-
985
- // Merge context into system prompt
986
- const enrichedPrompt = contextSuffix
987
- ? `${systemPrompt ?? ""}\n\n${contextSuffix}`.trim()
988
- : systemPrompt;
989
-
990
- // Create session
991
- const session = await handle.createSession(effectiveCwd, {
992
- mcpServers,
993
- systemPrompt: enrichedPrompt ?? systemPrompt,
994
- ...(agentMeta && { agentMeta }),
995
- } as any);
996
-
997
- // Store session record
998
- agentStore.putSession({
999
- agent_id: agentId,
1000
- session_id: sessionId,
1001
- provider_session_id: session.id,
1002
- created_at: now,
1003
- });
1004
-
1005
- // Update agent with provider session ID. Merge with existing metadata
1006
- // so fields set at spawn time (e.g. task_ref) aren't clobbered.
1007
- const existingMeta = agentStore.getAgent(agentId)?.metadata ?? {};
1008
- agentStore.updateAgent(agentId, {
1009
- metadata: { ...existingMeta, provider_session_id: session.id },
1010
- });
1011
-
1012
- // Register agent in inbox
1013
- await inboxAdapter.registerAgent(agentId, {
1014
- name,
1015
- role: role ?? "worker",
1016
- scope: team_instance ?? "default",
1017
- });
1018
-
1019
- // Track active session
1020
- const activeSession: ActiveSession = {
1021
- agentId,
1022
- handle,
1023
- session,
1024
- createdAt: now,
1025
- isPrompting: false,
1026
- };
1027
- activeSessions.set(agentId, activeSession);
1028
-
1029
- // Notify lifecycle
1030
- const agent = agentRecordToAgent(agentStore.getAgent(agentId)!);
1031
- notifyLifecycle({ type: "spawned", agent });
1032
- notifyLifecycle({ type: "started", agent });
1033
-
1034
- // Start health monitoring for coordinators
1035
- if (healthCheckService && role === "coordinator") {
1036
- healthCheckService.startForCoordinator(agentId);
1037
- }
1038
-
1039
- return {
1040
- id: agentId,
1041
- session_id: sessionId,
1042
- agent,
1043
- session,
1044
- workspace,
1045
- streamId: workspace?.streamId,
1046
- };
1047
- } catch (err) {
1048
- // Cleanup on failure
1049
- if (handle) {
1050
- try {
1051
- await handle.close();
1052
- } catch {
1053
- /* ignore */
1054
- }
1055
- }
1056
- agentStore.updateAgent(agentId, {
1057
- state: "failed",
1058
- stop_reason: "failed",
1059
- stopped_at: Date.now(),
1060
- });
1061
- throw err;
1062
- }
1063
- }
1064
-
1065
- async function terminate(
1066
- agentId: AgentId,
1067
- reason: AgentStopReason
1068
- ): Promise<void> {
1069
- const record = agentStore.getAgent(agentId);
1070
- if (!record) {
1071
- throw new AgentManagerError(
1072
- `Agent ${agentId} not found`,
1073
- "AGENT_NOT_FOUND",
1074
- agentId
1075
- );
1076
- }
1077
-
1078
- // Close active session
1079
- const activeSession = activeSessions.get(agentId);
1080
- if (activeSession) {
1081
- try {
1082
- await activeSession.handle.close();
1083
- } catch {
1084
- /* ignore close errors */
1085
- }
1086
- activeSessions.delete(agentId);
1087
- }
1088
-
1089
- // Stop health monitoring
1090
- if (healthCheckService && record.role === "coordinator") {
1091
- healthCheckService.stopForCoordinator(agentId);
1092
- }
1093
-
1094
- // Land the worker's work if completed with a workspace.
1095
- //
1096
- // V3 path (preferred): look up the role's YAML landing strategy via
1097
- // TopologyPolicy.getRoleConfig and dispatch through
1098
- // WorkspaceManager.land(). This fires cascade events (stream.merged or
1099
- // queue.added) so the hub sees the work. Landing = 'none' short-circuits.
1100
- //
1101
- // Legacy fallback: if no TopologyPolicy is wired or it can't resolve a
1102
- // landing for this role, submit to the legacy MergeQueue as before.
1103
- // Keeps pre-V3 programmatic callers + tests that bypass YAML working.
1104
- if (
1105
- workspaceManager &&
1106
- agentWorkspaces.has(agentId) &&
1107
- reason === "completed"
1108
- ) {
1109
- const ws = agentWorkspaces.get(agentId)!;
1110
- if (ws.role === "worker" && ws.streamId) {
1111
- const roleConfig = topologyPolicy?.getRoleConfig?.(record.role);
1112
- const yamlLandingName = roleConfig?.landing;
1113
- const usingV3Landing =
1114
- typeof yamlLandingName === "string" && yamlLandingName.length > 0;
1115
-
1116
- if (usingV3Landing) {
1117
- try {
1118
- const taskRef = (record.metadata as Record<string, unknown> | undefined)
1119
- ?.task_ref as { resource_id: string; node_id: string } | undefined;
1120
- await workspaceManager.land({
1121
- agentId,
1122
- streamId: ws.streamId,
1123
- sourceWorktree: ws.path,
1124
- strategyName: yamlLandingName,
1125
- strategyConfig: roleConfig?.landing_config,
1126
- taskRef,
1127
- // Dispatcher overwrites this with `this`; placeholder keeps the
1128
- // type satisfied without a cast.
1129
- workspaceManager,
1130
- });
1131
- } catch {
1132
- // Non-fatal landing failure — agent still terminates; conflicts
1133
- // and strategy errors surface via WorkspaceEvent emission and
1134
- // the strategy's own logs.
1135
- }
1136
- } else {
1137
- try {
1138
- const mergeQueue = workspaceManager.getMergeQueue();
1139
- if (mergeQueue) {
1140
- mergeQueue.submit({
1141
- streamId: ws.streamId,
1142
- workerBranch: ws.branch,
1143
- taskId: record.task_id ?? agentId,
1144
- workerAgentId: agentId,
1145
- });
1146
- }
1147
- } catch {
1148
- // Non-fatal merge queue submission failure
1149
- }
1150
- }
1151
- }
1152
- }
1153
-
1154
- // Deallocate workspace
1155
- if (workspaceManager && agentWorkspaces.has(agentId)) {
1156
- try {
1157
- workspaceManager.deallocateWorkspace(agentId);
1158
- } catch {
1159
- /* ignore */
1160
- }
1161
- agentWorkspaces.delete(agentId);
1162
- }
1163
-
1164
- // Revoke auth token
1165
- if (agentTokenManager) {
1166
- agentTokenManager.revokeToken(agentId);
1167
- }
1168
-
1169
- // Notify parent via inbox
1170
- if (record.parent_id) {
1171
- try {
1172
- await inboxAdapter.send(
1173
- agentId,
1174
- record.parent_id,
1175
- {
1176
- type: "event",
1177
- event: "agent_stopped",
1178
- data: {
1179
- agentId,
1180
- reason,
1181
- taskId: record.task_id,
1182
- role: record.role,
1183
- },
1184
- },
1185
- { importance: "high", threadTag: `lifecycle:${agentId}` }
1186
- );
1187
- } catch {
1188
- // Non-fatal inbox notification failure
1189
- }
1190
- }
1191
-
1192
- // Deregister from inbox
1193
- await inboxAdapter.deregisterAgent(agentId);
1194
-
1195
- // Update agent state
1196
- agentStore.updateAgent(agentId, {
1197
- state: "stopped" as AgentState,
1198
- stop_reason: reason as any,
1199
- stopped_at: Date.now(),
1200
- });
1201
-
1202
- // Emit final trajectory checkpoint with phase: "ended"
1203
- if (sidecarRef?.connected) {
1204
- try {
1205
- const session = agentStore.getSession(agentId);
1206
- sidecarRef.reportCheckpoint({
1207
- id: `${session?.session_id ?? agentId}-ended`,
1208
- session_id: session?.session_id ?? agentId,
1209
- agent: record.name ?? agentId,
1210
- branch: null,
1211
- files_touched: [],
1212
- checkpoints_count: 0,
1213
- metadata: { phase: "ended", reason },
1214
- }).catch(() => {});
1215
- } catch {
1216
- // best effort
1217
- }
1218
- }
1219
-
1220
- // Notify lifecycle
1221
- const updatedAgent = agentRecordToAgent(agentStore.getAgent(agentId)!);
1222
- notifyLifecycle({ type: "stopped", agent: updatedAgent, reason });
1223
-
1224
- // Cascade termination to children
1225
- const children = agentStore.getChildren(agentId);
1226
- for (const child of children) {
1227
- if (child.state === "running" || child.state === "spawning") {
1228
- const wsProvider: WorkspaceProvider = {
1229
- getWorkspace: (id: AgentId) => agentWorkspaces.get(id) ?? null,
1230
- };
1231
- const cascadeAdapter: CascadeAgentManager = {
1232
- getChildren: (id: AgentId) =>
1233
- agentStore
1234
- .getChildren(id)
1235
- .map((r) => agentRecordToAgent(r)),
1236
- terminate: (id: AgentId, r: AgentStopReason) => terminate(id, r),
1237
- };
1238
- const parentTaskRef = (record.metadata as Record<string, unknown> | undefined)
1239
- ?.task_ref as { resource_id: string; node_id: string } | undefined;
1240
- await terminateWithChangeConsolidation(
1241
- child.id as AgentId,
1242
- agentId,
1243
- cascadeAdapter,
1244
- wsProvider,
1245
- undefined,
1246
- workspaceManager ?? undefined,
1247
- parentTaskRef
1248
- );
1249
- }
1250
- }
1251
- }
1252
-
1253
- async function resume(
1254
- agentId: AgentId,
1255
- overridePermissionMode?: PermissionMode
1256
- ): Promise<SpawnedAgent> {
1257
- if (isShuttingDown) {
1258
- throw new AgentManagerError(
1259
- "Cannot resume agent during shutdown",
1260
- "SHUTDOWN_IN_PROGRESS"
1261
- );
1262
- }
1263
-
1264
- const record = agentStore.getAgent(agentId);
1265
- if (!record) {
1266
- throw new AgentManagerError(
1267
- `Agent ${agentId} not found`,
1268
- "AGENT_NOT_FOUND",
1269
- agentId
1270
- );
1271
- }
1272
-
1273
- if (activeSessions.has(agentId)) {
1274
- throw new AgentManagerError(
1275
- `Agent ${agentId} already has active session`,
1276
- "ALREADY_RUNNING",
1277
- agentId
1278
- );
1279
- }
1280
-
1281
- const permMode = overridePermissionMode ?? defaultPermissionMode;
1282
- const agentCwd = record.cwd || defaultCwd;
1283
-
1284
- const handle = await AgentFactory.spawn(defaultAgentType, {
1285
- permissionMode: permMode,
1286
- });
1287
-
1288
- const macroAgentMcp = buildMcpServerConfig({
1289
- agentId,
1290
- parentId: record.parent_id ?? "",
1291
- taskId: record.task_id ?? "",
1292
- cwd: agentCwd,
1293
- permissionMode: permMode,
1294
- lineage: record.lineage,
1295
- });
1296
-
1297
- const mcpServers = [
1298
- {
1299
- name: macroAgentMcp.name,
1300
- command: macroAgentMcp.command,
1301
- args: macroAgentMcp.args ?? [],
1302
- env: Object.entries(macroAgentMcp.env ?? {}).map(([k, v]) => ({
1303
- name: k,
1304
- value: v,
1305
- })),
1306
- },
1307
- ];
1308
-
1309
- // Strip user/project/local setting sources for isolated workers (the
1310
- // metadata flag is set at spawn time when SpawnAgentOptions.isolatedSettings
1311
- // was true) or interactive mode. See spawn() for the rationale.
1312
- const isIsolated = (record.metadata as Record<string, unknown> | undefined)?.isolatedSettings === true;
1313
- const agentMeta =
1314
- isIsolated || permMode === "interactive"
1315
- ? { claudeCode: { options: { settingSources: [] } } }
1316
- : undefined;
1317
-
1318
- // Try to load existing session or create new
1319
- const sessionRecord = agentStore.getSession(agentId);
1320
- let session: Session;
1321
-
1322
- if (sessionRecord?.provider_session_id) {
1323
- session = await handle.loadSession(
1324
- sessionRecord.provider_session_id,
1325
- agentCwd,
1326
- mcpServers as any,
1327
- agentMeta ? { agentMeta } : undefined
1328
- );
1329
- } else {
1330
- session = await handle.createSession(agentCwd, {
1331
- mcpServers,
1332
- ...(agentMeta && { agentMeta }),
1333
- });
1334
- }
1335
-
1336
- const now = Date.now() as Timestamp;
1337
- activeSessions.set(agentId, {
1338
- agentId,
1339
- handle,
1340
- session,
1341
- createdAt: now,
1342
- isPrompting: false,
1343
- });
1344
-
1345
- agentStore.updateAgent(agentId, {
1346
- state: "running",
1347
- started_at: now,
1348
- });
1349
- agentStore.putSession({
1350
- agent_id: agentId,
1351
- session_id: sessionRecord?.session_id ?? `session_${nanoid(12)}`,
1352
- provider_session_id: session.id,
1353
- created_at: now,
1354
- });
1355
-
1356
- const agent = agentRecordToAgent(agentStore.getAgent(agentId)!);
1357
-
1358
- // Re-publish the agent to subscribers (local MAP server, hub lifecycle
1359
- // bridge, team auto-join listeners) so a resumed agent is a first-class
1360
- // registered agent — not just an in-memory handle. Without this, the hub
1361
- // never re-registers the agent after cold-start; ACP routing works but
1362
- // the hub's "Registered Agents" view stays empty and capabilities never
1363
- // propagate back through `map/agents/register`.
1364
- //
1365
- // Spawn semantics are correct here: the process is new, the session is
1366
- // (re)loaded, and subscribers treat it as a fresh registration. Paired
1367
- // with the `stopped` event that fired on the prior termination, this
1368
- // keeps the bridge's `registered` map consistent.
1369
- notifyLifecycle({ type: "spawned", agent });
1370
- notifyLifecycle({ type: "started", agent });
1371
-
1372
- return {
1373
- id: agentId,
1374
- session_id: sessionRecord?.session_id ?? "",
1375
- agent,
1376
- session,
1377
- };
1378
- }
1379
-
1380
- async function continueAgent(
1381
- agentId: AgentId,
1382
- options?: ContinueAgentOptions
1383
- ): Promise<SpawnedAgent> {
1384
- const record = agentStore.getAgent(agentId);
1385
- if (!record) {
1386
- throw new AgentManagerError(
1387
- `Agent ${agentId} not found`,
1388
- "AGENT_NOT_FOUND",
1389
- agentId
1390
- );
1391
- }
1392
-
1393
- const contextLines: string[] = [];
1394
- if (options?.additionalContext) {
1395
- contextLines.push(options.additionalContext);
1396
- }
1397
- contextLines.push(`## Prior Session Context`);
1398
- contextLines.push(`Continuing from agent ${agentId}.`);
1399
-
1400
- const resumeContext = contextLines.join("\n");
1401
- const taskDescription =
1402
- options?.task ?? record.task ?? `Continue work from ${agentId}`;
1403
-
1404
- return spawn({
1405
- task: taskDescription,
1406
- role: record.role,
1407
- parent: record.parent_id ?? undefined,
1408
- cwd: record.cwd || defaultCwd,
1409
- customPrompt: resumeContext,
1410
- });
1411
- }
1412
-
1413
- async function forkAgent(
1414
- sourceAgentId: AgentId,
1415
- options?: { name?: string; prompt?: string; cwd?: string }
1416
- ): Promise<SpawnedAgent> {
1417
- if (isShuttingDown) {
1418
- throw new AgentManagerError(
1419
- "Cannot fork during shutdown",
1420
- "SHUTDOWN_IN_PROGRESS"
1421
- );
1422
- }
1423
-
1424
- const record = agentStore.getAgent(sourceAgentId);
1425
- if (!record) {
1426
- throw new AgentManagerError(
1427
- `Agent ${sourceAgentId} not found`,
1428
- "AGENT_NOT_FOUND",
1429
- sourceAgentId
1430
- );
1431
- }
1432
-
1433
- const activeSession = activeSessions.get(sourceAgentId);
1434
- const sessionRecord = agentStore.getSession(sourceAgentId);
1435
- if (!activeSession && !sessionRecord?.provider_session_id) {
1436
- throw new AgentManagerError(
1437
- `Agent ${sourceAgentId} has no session to fork`,
1438
- "FORK_NOT_SUPPORTED",
1439
- sourceAgentId
1440
- );
1441
- }
1442
-
1443
- const forkCwd = options?.cwd ?? record.cwd ?? defaultCwd;
1444
-
1445
- // Get forked session ID
1446
- let forkedProviderSessionId: string;
1447
- if (activeSession) {
1448
- const forkedSession = await activeSession.session.forkWithFlush();
1449
- forkedProviderSessionId = forkedSession.id;
1450
- } else {
1451
- forkedProviderSessionId = sessionRecord!.provider_session_id!;
1452
- }
1453
-
1454
- // Spawn new process
1455
- const handle = await AgentFactory.spawn(defaultAgentType, {
1456
- permissionMode: defaultPermissionMode,
1457
- });
1458
-
1459
- const agentId = `agent_${nanoid(12)}` as AgentId;
1460
- const taskId = `task_${nanoid(12)}` as TaskId;
1461
- const sessionId = `session_${nanoid(12)}`;
1462
- const name = options?.name ?? generateName();
1463
- const now = Date.now() as Timestamp;
1464
-
1465
- // Persist forked agent
1466
- agentStore.putAgent({
1467
- id: agentId,
1468
- name,
1469
- role: record.role,
1470
- state: "running",
1471
- parent_id: record.parent_id,
1472
- lineage: record.lineage,
1473
- team: record.team,
1474
- scope: record.scope,
1475
- task: options?.prompt ?? `[Fork of ${sourceAgentId}]`,
1476
- task_id: taskId,
1477
- cwd: forkCwd,
1478
- capabilities: record.capabilities,
1479
- created_at: now,
1480
- started_at: now,
1481
- metadata: { fork_of: sourceAgentId },
1482
- });
1483
-
1484
- const macroAgentMcp = buildMcpServerConfig({
1485
- agentId,
1486
- parentId: record.parent_id ?? "",
1487
- taskId,
1488
- cwd: forkCwd,
1489
- permissionMode: defaultPermissionMode,
1490
- lineage: record.lineage,
1491
- sessionId,
1492
- });
1493
-
1494
- const session = await handle.loadSession(
1495
- forkedProviderSessionId,
1496
- forkCwd,
1497
- [
1498
- {
1499
- name: macroAgentMcp.name,
1500
- command: macroAgentMcp.command,
1501
- args: macroAgentMcp.args ?? [],
1502
- env: Object.entries(macroAgentMcp.env ?? {}).map(([k, v]) => ({
1503
- name: k,
1504
- value: v,
1505
- })),
1506
- },
1507
- ] as any
1508
- );
1509
-
1510
- agentStore.putSession({
1511
- agent_id: agentId,
1512
- session_id: sessionId,
1513
- provider_session_id: session.id,
1514
- created_at: now,
1515
- });
1516
-
1517
- await inboxAdapter.registerAgent(agentId, {
1518
- name,
1519
- role: record.role,
1520
- scope: record.scope,
1521
- });
1522
-
1523
- activeSessions.set(agentId, {
1524
- agentId,
1525
- handle,
1526
- session,
1527
- createdAt: now,
1528
- isPrompting: false,
1529
- });
1530
-
1531
- const agent = agentRecordToAgent(agentStore.getAgent(agentId)!);
1532
- notifyLifecycle({ type: "spawned", agent });
1533
- notifyLifecycle({ type: "started", agent });
1534
-
1535
- return { id: agentId, session_id: sessionId, agent, session };
1536
- }
1537
-
1538
- // ── Query Methods ──────────────────────────────────────────
1539
-
1540
- function get(agentId: AgentId): Agent | null {
1541
- const record = agentStore.getAgent(agentId);
1542
- return record ? agentRecordToAgent(record) : null;
1543
- }
1544
-
1545
- function list(filter?: AgentFilter): Agent[] {
1546
- const records = agentStore.listAgents({
1547
- state: filter?.state,
1548
- parent_id: filter?.parent,
1549
- });
1550
-
1551
- let result = records.map(agentRecordToAgent);
1552
-
1553
- if (filter?.task_id) {
1554
- result = result.filter((a) => a.task_id === filter.task_id);
1555
- }
1556
- if (filter?.headManagersOnly) {
1557
- result = result.filter((a) => !a.parent);
1558
- }
1559
-
1560
- return result;
1561
- }
1562
-
1563
- function getChildren(agentId: AgentId): Agent[] {
1564
- return agentStore.getChildren(agentId).map(agentRecordToAgent);
1565
- }
1566
-
1567
- function getHierarchy(
1568
- agentId: AgentId,
1569
- options?: HierarchyOptions
1570
- ): AgentHierarchy | null {
1571
- const record = agentStore.getAgent(agentId);
1572
- if (!record) return null;
1573
-
1574
- function buildTree(
1575
- id: AgentId,
1576
- depth: number
1577
- ): AgentHierarchyNode {
1578
- const agent = agentRecordToAgent(agentStore.getAgent(id)!);
1579
- const maxDepth = options?.depth;
1580
- const children =
1581
- maxDepth !== undefined && depth >= maxDepth
1582
- ? []
1583
- : agentStore
1584
- .getChildren(id)
1585
- .map((c) => buildTree(c.id as AgentId, depth + 1));
1586
-
1587
- return { agent, children };
1588
- }
1589
-
1590
- const root = buildTree(agentId, 0);
1591
-
1592
- function countNodes(node: AgentHierarchyNode): number {
1593
- return 1 + node.children.reduce((sum, c) => sum + countNodes(c), 0);
1594
- }
1595
-
1596
- function maxDepth(node: AgentHierarchyNode, d: number): number {
1597
- if (node.children.length === 0) return d;
1598
- return Math.max(...node.children.map((c) => maxDepth(c, d + 1)));
1599
- }
1600
-
1601
- return {
1602
- root,
1603
- depth: maxDepth(root, 0),
1604
- totalAgents: countNodes(root),
1605
- };
1606
- }
1607
-
1608
- // ── Head Manager ─────────────────────────────────────────────
1609
-
1610
- async function getOrCreateHeadManager(
1611
- options: HeadManagerOptions
1612
- ): Promise<SpawnedAgent> {
1613
- // Check for an existing head manager matching this cwd that ALSO has a
1614
- // live session in this process. The activeSessions check has to be inside
1615
- // the predicate (not after .find) — the agentStore is persistent across
1616
- // process restarts, so without this filter we'd match stale "running"
1617
- // records from previous processes whose sessions are gone, then fall
1618
- // through to spawn() and create a duplicate coordinator.
1619
- const existing = agentStore
1620
- .listAgents({ parent_id: null, state: "running" })
1621
- .find(
1622
- (a) =>
1623
- a.cwd === options.cwd &&
1624
- activeSessions.has(a.id as AgentId),
1625
- );
1626
-
1627
- if (existing) {
1628
- const sessionEntry = activeSessions.get(existing.id as AgentId)!;
1629
- const storedSession = agentStore.getSession(existing.id as AgentId);
1630
- return {
1631
- id: existing.id as AgentId,
1632
- session_id: storedSession?.session_id ?? sessionEntry.session.id ?? "",
1633
- agent: agentRecordToAgent(existing),
1634
- session: sessionEntry.session,
1635
- };
1636
- }
1637
-
1638
- return spawn({
1639
- task: "Head manager",
1640
- parent: null,
1641
- cwd: options.cwd,
1642
- permissionMode: options.permissionMode,
1643
- customPrompt: options.systemPrompt,
1644
- role: "coordinator",
1645
- topics: options.topics,
1646
- });
1647
- }
1648
-
1649
- function listHeadManagers(): Agent[] {
1650
- return agentStore
1651
- .listAgents({ parent_id: null })
1652
- .map(agentRecordToAgent);
1653
- }
1654
-
1655
- /**
1656
- * Look up the spawned-agent shape for any agent that's still alive in this
1657
- * process (any role, not just coordinators). Returns null if the agent
1658
- * doesn't exist, isn't running, or has no live session in `activeSessions`.
1659
- *
1660
- * Used by the ACP layer to bind a session to a specific agent when the MAP
1661
- * stream targets one explicitly — preserving the routing intent that
1662
- * cwd-based head-manager lookup would otherwise lose in multi-coordinator
1663
- * scenarios.
1664
- */
1665
- function getActiveAgentSession(agentId: AgentId): SpawnedAgent | null {
1666
- if (!activeSessions.has(agentId)) return null;
1667
- const record = agentStore.getAgent(agentId);
1668
- if (!record || record.state !== "running") return null;
1669
- const sessionEntry = activeSessions.get(agentId)!;
1670
- const storedSession = agentStore.getSession(agentId);
1671
- return {
1672
- id: agentId,
1673
- session_id: storedSession?.session_id ?? sessionEntry.session.id ?? "",
1674
- agent: agentRecordToAgent(record),
1675
- session: sessionEntry.session,
1676
- };
1677
- }
1678
-
1679
- // ── Session Interaction ──────────────────────────────────────
1680
-
1681
- async function* prompt(
1682
- agentId: AgentId,
1683
- message: string
1684
- ): AsyncIterable<ExtendedSessionUpdate> {
1685
- const activeSession = activeSessions.get(agentId);
1686
- if (!activeSession) {
1687
- throw new AgentManagerError(
1688
- `No active session for agent ${agentId}`,
1689
- "SESSION_NOT_FOUND",
1690
- agentId
1691
- );
1692
- }
1693
-
1694
- activeSession.isPrompting = true;
1695
- try {
1696
- // Permission overlay enforcement — for agents in dispatch context
1697
- // (mail-inbound + ACP reuse targets), the dispatch consumer sets a
1698
- // per-agent overlay before driving prompt(). When set, `permission_request`
1699
- // session updates are intercepted here, evaluated against the overlay,
1700
- // and answered via `respondToPermission`. The update is NOT yielded
1701
- // to the consumer in that case — dispatch enforcement is internal.
1702
- //
1703
- // When no overlay is set (the common case — chat agents, sub-agents
1704
- // spawned by parents, etc.), permission_request updates are yielded
1705
- // through unchanged so chat surfaces' UI permission dialogs (the
1706
- // swarmcraft PermissionDialog rendered via the openhive-acp-service
1707
- // WS subscription) keep working.
1708
- //
1709
- // See `docs/PERMISSION_OVERLAY_ACP_DESIGN.md` for the rationale and
1710
- // a diagram of the four-process flow.
1711
- for await (const update of activeSession.session.prompt(message)) {
1712
- const u = update as {
1713
- sessionUpdate?: string;
1714
- requestId?: string;
1715
- toolCall?: { title?: string; kind?: string; rawInput?: unknown };
1716
- options?: Array<{ kind?: string; optionId?: string }>;
1717
- };
1718
- if (u?.sessionUpdate === "permission_request") {
1719
- const overlay = getPermissionOverlay(agentId);
1720
- // No overlay → pass through to the consumer (chat UI, etc.).
1721
- if (!overlay) {
1722
- yield update;
1723
- continue;
1724
- }
1725
- let optionId: string | undefined;
1726
- try {
1727
- const toolName = deriveToolName(u.toolCall);
1728
- const toolInput = u.toolCall?.rawInput ?? {};
1729
- const decision = evaluatePermission(toolName, toolInput, overlay)
1730
- .decision;
1731
- const wantedKind =
1732
- decision === "deny" ? "reject_once" : "allow_once";
1733
- const opt =
1734
- u.options?.find((o) => o.kind === wantedKind) ??
1735
- u.options?.find(
1736
- (o) =>
1737
- o.kind === (decision === "deny" ? "reject_always" : "allow_always"),
1738
- );
1739
- optionId = opt?.optionId;
1740
- } catch {
1741
- // Fail closed: on registry/evaluator error, deny.
1742
- optionId = u.options?.find((o) => o.kind === "reject_once")?.optionId;
1743
- }
1744
- if (u.requestId && optionId) {
1745
- try {
1746
- (activeSession.session as any).respondToPermission?.(
1747
- u.requestId,
1748
- optionId,
1749
- );
1750
- } catch (err) {
1751
- console.warn(
1752
- `[perm-overlay] respondToPermission failed agent=${agentId} req=${u.requestId}: ${(err as Error).message}`,
1753
- );
1754
- }
1755
- }
1756
- // Don't yield permission_request to the consumer — dispatch-internal.
1757
- continue;
1758
- }
1759
- yield update;
1760
- }
1761
- } finally {
1762
- activeSession.isPrompting = false;
1763
- agentStore.updateAgent(agentId, {
1764
- last_activity_at: Date.now(),
1765
- });
1766
- }
1767
- }
1768
-
1769
- async function promptUntilDone(
1770
- agentId: AgentId,
1771
- message: string,
1772
- options?: {
1773
- maxFollowUps?: number;
1774
- onUpdate?: (update: ExtendedSessionUpdate) => void;
1775
- /**
1776
- * Optional caller-supplied completion predicate. When it returns true the
1777
- * loop stops consuming, terminates the agent as "completed", and returns
1778
- * `completedExternally: true` — WITHOUT requiring the macro `done()` tool.
1779
- *
1780
- * Checked three ways (all fire terminate + return completedExternally):
1781
- * (a) reactively after each streamed update (fast path),
1782
- * (b) reactively after each attempt's stream ends (fast path),
1783
- * (c) on a CONCURRENT ~2s timer while consuming the stream. (c) is the
1784
- * critical path for the live τ rollout: the agent runs the whole
1785
- * episode in ONE prompt() call, calls τ's finish, the env writes its
1786
- * reward sink (done:true), and then the prompt() stream goes SILENT
1787
- * and does NOT close — the async iterator just blocks. With only the
1788
- * reactive checks (a)/(b) the predicate is never re-evaluated and
1789
- * solve() hangs until the rollout backstop. The concurrent poller
1790
- * observes done:true independent of update arrival, flips
1791
- * completedExternally, and terminate()s the agent — which ends the
1792
- * in-flight prompt() generator (via return or throw, both handled).
1793
- *
1794
- * Generic by design: this module has NO knowledge of what the predicate
1795
- * reads (e.g. an external reward sink). Back-compat: when absent, NO poller
1796
- * is started and behavior is unchanged — only `done()` detection drives
1797
- * completion.
1798
- *
1799
- * @param pollIntervalMs Override the concurrent poll cadence (default
1800
- * 2000ms). Primarily a test seam.
1801
- */
1802
- isComplete?: () => boolean | Promise<boolean>;
1803
- pollIntervalMs?: number;
1804
- }
1805
- ): Promise<{
1806
- doneCalled: boolean;
1807
- doneStatus?: string;
1808
- completedExternally: boolean;
1809
- updates: ExtendedSessionUpdate[];
1810
- }> {
1811
- const maxFollowUps = options?.maxFollowUps ?? 2;
1812
- const pollIntervalMs = options?.pollIntervalMs ?? 2000;
1813
- const allUpdates: ExtendedSessionUpdate[] = [];
1814
- let doneCalled = false;
1815
- let doneStatus: string | undefined;
1816
- let completedExternally = false;
1817
-
1818
- let currentMessage = message;
1819
-
1820
- for (let attempt = 0; attempt <= maxFollowUps; attempt++) {
1821
- // ── Concurrent completion poller ─────────────────────────────────────
1822
- // Only armed when the caller supplies a predicate (back-compat: no
1823
- // predicate → no poller, identical behavior). The live failure mode is a
1824
- // prompt() stream that has gone SILENT but not CLOSED after the episode
1825
- // externally completed; the reactive per-update check never fires again
1826
- // because no updates arrive. This timer re-evaluates isComplete()
1827
- // independent of update arrival. On true it flips completedExternally and
1828
- // terminate()s the agent, which ends the in-flight prompt() generator
1829
- // (return or throw) so the for-await below unblocks. The interval is
1830
- // always cleared in `finally` so no timer leaks across attempts.
1831
- let pollTimer: ReturnType<typeof setInterval> | undefined;
1832
- let polling = false;
1833
-
1834
- // Resolves the instant completion is detected (external predicate OR the
1835
- // macro done() tool). The attempt is RACED against this signal so it
1836
- // returns WITHOUT waiting for the prompt() generator to drain or for
1837
- // terminate() to finish. The prior design relied on terminate() ending
1838
- // the silent in-flight stream to unblock the for-await; when that teardown
1839
- // stalled (e.g. a long, busy real episode whose subprocess is slow to die),
1840
- // promptUntilDone never returned and the macro session stayed "running"
1841
- // until the multi-hour hard-timer — the refinement "finalization hang".
1842
- let signalDone: () => void = () => {};
1843
- const doneSignal = new Promise<void>((resolve) => {
1844
- signalDone = resolve;
1845
- });
1846
-
1847
- const startPoller = () => {
1848
- if (!options?.isComplete) return;
1849
- pollTimer = setInterval(() => {
1850
- if (polling || completedExternally) return;
1851
- polling = true;
1852
- void (async () => {
1853
- try {
1854
- if (!completedExternally && options.isComplete && (await options.isComplete())) {
1855
- completedExternally = true;
1856
- signalDone();
1857
- // Tear down the agent/session in the BACKGROUND — never await it
1858
- // here, so a slow teardown cannot gate the return. Tracked in
1859
- // pendingTerminations so close() awaits it before shutdown
1860
- // returns (else a still-racing group-kill is abandoned by a
1861
- // subsequent process.exit, orphaning the subtree). Best effort.
1862
- {
1863
- const t = terminate(agentId, "completed" as any).catch(() => {});
1864
- pendingTerminations.add(t);
1865
- void t.finally(() => pendingTerminations.delete(t));
1866
- }
1867
- }
1868
- } catch {
1869
- // Predicate errored — leave completion to the reactive checks.
1870
- } finally {
1871
- polling = false;
1872
- }
1873
- })();
1874
- }, pollIntervalMs);
1875
- };
1876
-
1877
- // Consume the stream as a background task so a silent-but-open generator
1878
- // can be raced against the completion signal below.
1879
- const consume = (async () => {
1880
- for await (const update of prompt(agentId, currentMessage)) {
1881
- allUpdates.push(update);
1882
- options?.onUpdate?.(update);
1883
-
1884
- // External completion predicate (reactive fast path).
1885
- if (options?.isComplete && (await options.isComplete())) {
1886
- completedExternally = true;
1887
- signalDone();
1888
- break;
1889
- }
1890
- if (completedExternally) break;
1891
-
1892
- // Detect done() tool call from session updates.
1893
- // acp-factory uses { sessionUpdate: "tool_call", title: "mcp__macro-agent__done" }
1894
- const uAny = update as any;
1895
-
1896
- // Check title field (primary detection)
1897
- if (
1898
- (uAny.sessionUpdate === "tool_call" || uAny.sessionUpdate === "tool_call_update") &&
1899
- typeof uAny.title === "string" &&
1900
- uAny.title.endsWith("__done")
1901
- ) {
1902
- doneCalled = true;
1903
- // Extract status from rawInput (may arrive across multiple updates —
1904
- // first update has rawInput={}, subsequent has full input)
1905
- try {
1906
- const raw = uAny.rawInput;
1907
- const input =
1908
- typeof raw === "string" ? JSON.parse(raw) :
1909
- typeof raw === "object" ? raw :
1910
- uAny.input;
1911
- if (input?.status) {
1912
- doneStatus = input.status;
1913
- }
1914
- } catch {
1915
- // Best effort — rawInput may not be parseable yet
1916
- }
1917
- signalDone();
1918
- }
1919
-
1920
- // Fallback: check older format
1921
- if (
1922
- uAny.type === "result" &&
1923
- uAny.subtype === "tool_result" &&
1924
- uAny.toolName === "done"
1925
- ) {
1926
- doneCalled = true;
1927
- doneStatus = uAny.result?.status;
1928
- signalDone();
1929
- }
1930
- }
1931
- })();
1932
- // Prevent an unhandled rejection if we return via doneSignal before the
1933
- // now-orphaned stream throws from a background teardown.
1934
- consume.catch(() => {});
1935
-
1936
- try {
1937
- startPoller();
1938
- // Return as soon as EITHER the stream drains naturally OR completion is
1939
- // signalled — whichever comes first. This is the key change: completion
1940
- // no longer depends on the generator unblocking.
1941
- await Promise.race([consume, doneSignal]);
1942
- } catch (err) {
1943
- // A genuine stream error (not a post-completion teardown) re-throws.
1944
- if (!completedExternally && !doneCalled) throw err;
1945
- } finally {
1946
- // Always clear the concurrent poller so no timer leaks across attempts.
1947
- if (pollTimer) clearInterval(pollTimer);
1948
- }
1949
-
1950
- // Re-check after the stream ends in case completion landed exactly as the
1951
- // attempt's stream drained (the inner break / poller already set the flag
1952
- // when it fired mid-stream).
1953
- if (!completedExternally && options?.isComplete && (await options.isComplete())) {
1954
- completedExternally = true;
1955
- }
1956
-
1957
- if (doneCalled || completedExternally) break;
1958
-
1959
- if (attempt < maxFollowUps) {
1960
- currentMessage =
1961
- "Please call the done() tool to signal that you have completed your work.";
1962
- }
1963
- }
1964
-
1965
- // Auto-terminate when the agent completed — either via the macro done() tool
1966
- // or via the caller's external completion predicate. This closes the
1967
- // lifecycle gap: without this, agents stay in "running" state because
1968
- // nothing triggers terminate(). The external path mirrors the done() path
1969
- // (terminate as "completed").
1970
- if (doneCalled) {
1971
- const reason = doneStatus === "completed" ? "completed" : (doneStatus ?? "failed");
1972
- try {
1973
- await terminate(agentId, reason as any);
1974
- } catch {
1975
- // Best effort — agent may already be stopping
1976
- }
1977
- } else if (completedExternally) {
1978
- try {
1979
- await terminate(agentId, "completed" as any);
1980
- } catch {
1981
- // Best effort — agent may already be stopping
1982
- }
1983
- }
1984
-
1985
- return { doneCalled, doneStatus, completedExternally, updates: allUpdates };
1986
- }
1987
-
1988
- function getSession(agentId: AgentId): Session | null {
1989
- return activeSessions.get(agentId)?.session ?? null;
1990
- }
1991
-
1992
- function hasActiveSession(agentId: AgentId): boolean {
1993
- return activeSessions.has(agentId);
1994
- }
1995
-
1996
- function isPrompting(agentId: AgentId): boolean {
1997
- return activeSessions.get(agentId)?.isPrompting ?? false;
1998
- }
1999
-
2000
- async function supportsInjection(agentId: AgentId): Promise<boolean> {
2001
- const session = activeSessions.get(agentId)?.session;
2002
- if (!session) return false;
2003
- return typeof (session as any).supportsInject === "function"
2004
- ? (session as any).supportsInject()
2005
- : false;
2006
- }
2007
-
2008
- function isProcessRunning(agentId: AgentId): boolean {
2009
- const session = activeSessions.get(agentId);
2010
- if (!session) return false;
2011
- return typeof (session as any).handle?.isRunning === "function"
2012
- ? (session as any).handle.isRunning()
2013
- : true;
2014
- }
2015
-
2016
- function respondToPermission(
2017
- agentId: AgentId,
2018
- requestId: string,
2019
- optionId: string
2020
- ): boolean {
2021
- const session = activeSessions.get(agentId)?.session;
2022
- if (!session) return false;
2023
- return (session as any).respondToPermission?.(requestId, optionId) ?? false;
2024
- }
2025
-
2026
- function cancelPermission(agentId: AgentId, requestId: string): boolean {
2027
- const session = activeSessions.get(agentId)?.session;
2028
- if (!session) return false;
2029
- return (session as any).cancelPermission?.(requestId) ?? false;
2030
- }
2031
-
2032
- function setPermissionMode(
2033
- agentId: AgentId,
2034
- mode: PermissionMode
2035
- ): boolean {
2036
- const session = activeSessions.get(agentId);
2037
- if (!session) return false;
2038
- if (typeof (session.handle as any).setPermissionMode === "function") {
2039
- (session.handle as any).setPermissionMode(mode);
2040
- return true;
2041
- }
2042
- return false;
2043
- }
2044
-
2045
- function getPermissionMode(agentId: AgentId): PermissionMode | null {
2046
- const session = activeSessions.get(agentId);
2047
- if (!session) return null;
2048
- return typeof (session.handle as any).getPermissionMode === "function"
2049
- ? (session.handle as any).getPermissionMode()
2050
- : null;
2051
- }
2052
-
2053
- // ── Lifecycle Callbacks ──────────────────────────────────────
2054
-
2055
- function onLifecycleEvent(
2056
- callback: AgentLifecycleCallback
2057
- ): () => void {
2058
- lifecycleListeners.add(callback);
2059
- return () => lifecycleListeners.delete(callback);
2060
- }
2061
-
2062
- function setSpawnInterceptorFn(
2063
- interceptor: SpawnInterceptor | null
2064
- ): void {
2065
- spawnInterceptor = interceptor;
2066
- }
2067
-
2068
- function getRoleRegistry(): RoleRegistry {
2069
- return roleRegistry;
2070
- }
2071
-
2072
- // ── Legacy stubs ─────────────────────────────────────────────
2073
- // These methods exist for backward compatibility but are no-ops
2074
- // since messaging and task management are now in subsystems.
2075
-
2076
- function setOpenTasksSocketPath(_socketPath: string): void {
2077
- // No-op: opentasks client auto-discovers socket
2078
- }
2079
-
2080
- function setMapServerUrl(url: string): void {
2081
- mapServerUrl = url;
2082
- }
2083
-
2084
- function setIntegrationConfigs(configs: {
2085
- minimem?: typeof minimemConfig;
2086
- skilltree?: typeof skilltreeConfig;
2087
- sessionlog?: typeof sessionlogConfig;
2088
- }): void {
2089
- if (configs.minimem) minimemConfig = configs.minimem;
2090
- if (configs.skilltree) skilltreeConfig = configs.skilltree;
2091
- if (configs.sessionlog) sessionlogConfig = configs.sessionlog;
2092
- }
2093
-
2094
- function setSkillLoadout(role: string, content: string): void {
2095
- skillLoadouts.set(role, content);
2096
- }
2097
-
2098
- function setSidecar(sidecar: { connected: boolean; reportCheckpoint(cp: any): Promise<any> } | null): void {
2099
- sidecarRef = sidecar;
2100
- }
2101
-
2102
- function setTopologyPolicyFn(
2103
- policy: import('../workspace/topology/types.js').TopologyPolicy | null
2104
- ): void {
2105
- topologyPolicy = policy;
2106
- }
2107
-
2108
- function setMailServices(): void {
2109
- // No-op: agent-inbox handles conversation tracking
2110
- }
2111
-
2112
- // ── Cleanup ──────────────────────────────────────────────────
2113
-
2114
- async function close(): Promise<void> {
2115
- isShuttingDown = true;
2116
-
2117
- for (const [agentId, session] of activeSessions) {
2118
- try {
2119
- await session.handle.close();
2120
- } catch {
2121
- /* ignore */
2122
- }
2123
- agentStore.updateAgent(agentId, {
2124
- state: "stopped",
2125
- stop_reason: "cancelled",
2126
- stopped_at: Date.now(),
2127
- });
2128
- }
2129
- activeSessions.clear();
2130
-
2131
- // Await any in-flight fire-and-forget terminations (e.g. the completion
2132
- // poller's background teardown) so shutdown does not return while a
2133
- // group-kill is still racing — otherwise a follow-on process.exit abandons
2134
- // it and orphans the acp/claude/mcp_env subtree. Bounded by a backstop so a
2135
- // genuinely stuck close() cannot wedge shutdown.
2136
- if (pendingTerminations.size > 0) {
2137
- await Promise.race([
2138
- Promise.allSettled([...pendingTerminations]),
2139
- new Promise((resolve) => setTimeout(resolve, 6000)),
2140
- ]);
2141
- }
2142
-
2143
- agentWorkspaces.clear();
2144
- lifecycleListeners.clear();
2145
-
2146
- // Note: isShuttingDown stays true after close() to prevent further spawns
2147
- }
2148
-
2149
- // ── Return AgentManager interface ────────────────────────────
2150
-
2151
- return {
2152
- spawn,
2153
- terminate,
2154
- resume,
2155
- continueAgent,
2156
- forkAgent,
2157
- get,
2158
- list,
2159
- getChildren,
2160
- getHierarchy,
2161
- getOrCreateHeadManager,
2162
- listHeadManagers,
2163
- getActiveAgentSession,
2164
- prompt,
2165
- promptUntilDone,
2166
- getSession,
2167
- hasActiveSession,
2168
- isPrompting,
2169
- supportsInjection,
2170
- isProcessRunning,
2171
- respondToPermission,
2172
- cancelPermission,
2173
- setPermissionMode,
2174
- getPermissionMode,
2175
- onLifecycleEvent,
2176
- setSpawnInterceptor: setSpawnInterceptorFn,
2177
- getRoleRegistry,
2178
- setOpenTasksSocketPath,
2179
- setMapServerUrl,
2180
- setIntegrationConfigs,
2181
- setSkillLoadout,
2182
- setSidecar,
2183
- setTopologyPolicy: setTopologyPolicyFn,
2184
- setMailServices,
2185
- close,
2186
- } as AgentManager;
2187
- }