macro-agent 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (660) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/.sudocode/issues.jsonl +28 -0
  3. package/.sudocode/specs.jsonl +8 -0
  4. package/CLAUDE.md +25 -17
  5. package/README.md +11 -29
  6. package/dist/acp/macro-agent.d.ts +15 -0
  7. package/dist/acp/macro-agent.d.ts.map +1 -1
  8. package/dist/acp/macro-agent.js +131 -35
  9. package/dist/acp/macro-agent.js.map +1 -1
  10. package/dist/acp/types.d.ts +32 -1
  11. package/dist/acp/types.d.ts.map +1 -1
  12. package/dist/acp/types.js.map +1 -1
  13. package/dist/agent/agent-manager.d.ts +65 -1
  14. package/dist/agent/agent-manager.d.ts.map +1 -1
  15. package/dist/agent/agent-manager.js +544 -200
  16. package/dist/agent/agent-manager.js.map +1 -1
  17. package/dist/agent/types.d.ts +8 -1
  18. package/dist/agent/types.d.ts.map +1 -1
  19. package/dist/agent/types.js.map +1 -1
  20. package/dist/api/server.d.ts +8 -1
  21. package/dist/api/server.d.ts.map +1 -1
  22. package/dist/api/server.js +136 -8
  23. package/dist/api/server.js.map +1 -1
  24. package/dist/api/types.d.ts +1 -1
  25. package/dist/api/types.d.ts.map +1 -1
  26. package/dist/auth/index.d.ts +2 -0
  27. package/dist/auth/index.d.ts.map +1 -0
  28. package/dist/auth/index.js +2 -0
  29. package/dist/auth/index.js.map +1 -0
  30. package/dist/auth/token.d.ts +41 -0
  31. package/dist/auth/token.d.ts.map +1 -0
  32. package/dist/auth/token.js +73 -0
  33. package/dist/auth/token.js.map +1 -0
  34. package/dist/cli/acp.d.ts +2 -23
  35. package/dist/cli/acp.d.ts.map +1 -1
  36. package/dist/cli/acp.js +197 -61
  37. package/dist/cli/acp.js.map +1 -1
  38. package/dist/cli/index.js +152 -16
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/cli/mcp.d.ts +6 -0
  41. package/dist/cli/mcp.d.ts.map +1 -1
  42. package/dist/cli/mcp.js +279 -173
  43. package/dist/cli/mcp.js.map +1 -1
  44. package/dist/cli/parse-args.d.ts +20 -0
  45. package/dist/cli/parse-args.d.ts.map +1 -0
  46. package/dist/cli/parse-args.js +43 -0
  47. package/dist/cli/parse-args.js.map +1 -0
  48. package/dist/cli/stable-instance-id.d.ts +8 -0
  49. package/dist/cli/stable-instance-id.d.ts.map +1 -0
  50. package/dist/cli/stable-instance-id.js +14 -0
  51. package/dist/cli/stable-instance-id.js.map +1 -0
  52. package/dist/config/project-config.d.ts +85 -7
  53. package/dist/config/project-config.d.ts.map +1 -1
  54. package/dist/config/project-config.js +133 -20
  55. package/dist/config/project-config.js.map +1 -1
  56. package/dist/index.d.ts +1 -0
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +2 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/lifecycle/handlers/index.d.ts +7 -3
  61. package/dist/lifecycle/handlers/index.d.ts.map +1 -1
  62. package/dist/lifecycle/handlers/index.js +25 -8
  63. package/dist/lifecycle/handlers/index.js.map +1 -1
  64. package/dist/lifecycle/types.d.ts +2 -0
  65. package/dist/lifecycle/types.d.ts.map +1 -1
  66. package/dist/lifecycle/types.js.map +1 -1
  67. package/dist/map/adapter/acp-over-map.d.ts +17 -0
  68. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  69. package/dist/map/adapter/acp-over-map.js +384 -23
  70. package/dist/map/adapter/acp-over-map.js.map +1 -1
  71. package/dist/map/adapter/connection-manager.d.ts.map +1 -1
  72. package/dist/map/adapter/connection-manager.js +3 -0
  73. package/dist/map/adapter/connection-manager.js.map +1 -1
  74. package/dist/map/adapter/event-log.d.ts +87 -0
  75. package/dist/map/adapter/event-log.d.ts.map +1 -0
  76. package/dist/map/adapter/event-log.js +122 -0
  77. package/dist/map/adapter/event-log.js.map +1 -0
  78. package/dist/map/adapter/event-translator.js +6 -6
  79. package/dist/map/adapter/event-translator.js.map +1 -1
  80. package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
  81. package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
  82. package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
  83. package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
  84. package/dist/map/adapter/extensions/index.d.ts +13 -1
  85. package/dist/map/adapter/extensions/index.d.ts.map +1 -1
  86. package/dist/map/adapter/extensions/index.js +61 -0
  87. package/dist/map/adapter/extensions/index.js.map +1 -1
  88. package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
  89. package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
  90. package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
  91. package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
  92. package/dist/map/adapter/extensions/rename.d.ts +29 -0
  93. package/dist/map/adapter/extensions/rename.d.ts.map +1 -0
  94. package/dist/map/adapter/extensions/rename.js +49 -0
  95. package/dist/map/adapter/extensions/rename.js.map +1 -0
  96. package/dist/map/adapter/extensions/streams.d.ts +95 -0
  97. package/dist/map/adapter/extensions/streams.d.ts.map +1 -0
  98. package/dist/map/adapter/extensions/streams.js +515 -0
  99. package/dist/map/adapter/extensions/streams.js.map +1 -0
  100. package/dist/map/adapter/extensions/task.d.ts.map +1 -1
  101. package/dist/map/adapter/extensions/task.js +10 -0
  102. package/dist/map/adapter/extensions/task.js.map +1 -1
  103. package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
  104. package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
  105. package/dist/map/adapter/extensions/update-metadata.js +67 -0
  106. package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
  107. package/dist/map/adapter/index.d.ts +2 -1
  108. package/dist/map/adapter/index.d.ts.map +1 -1
  109. package/dist/map/adapter/index.js +10 -2
  110. package/dist/map/adapter/index.js.map +1 -1
  111. package/dist/map/adapter/interface.d.ts +2 -0
  112. package/dist/map/adapter/interface.d.ts.map +1 -1
  113. package/dist/map/adapter/map-adapter.d.ts +3 -0
  114. package/dist/map/adapter/map-adapter.d.ts.map +1 -1
  115. package/dist/map/adapter/map-adapter.js +258 -35
  116. package/dist/map/adapter/map-adapter.js.map +1 -1
  117. package/dist/map/adapter/subscription-manager.d.ts.map +1 -1
  118. package/dist/map/adapter/subscription-manager.js +5 -1
  119. package/dist/map/adapter/subscription-manager.js.map +1 -1
  120. package/dist/map/adapter/types.d.ts +3 -1
  121. package/dist/map/adapter/types.d.ts.map +1 -1
  122. package/dist/mcp/map-client.d.ts +39 -0
  123. package/dist/mcp/map-client.d.ts.map +1 -0
  124. package/dist/mcp/map-client.js +129 -0
  125. package/dist/mcp/map-client.js.map +1 -0
  126. package/dist/mcp/mcp-server.d.ts +16 -0
  127. package/dist/mcp/mcp-server.d.ts.map +1 -1
  128. package/dist/mcp/mcp-server.js +125 -88
  129. package/dist/mcp/mcp-server.js.map +1 -1
  130. package/dist/mcp/tools/done.d.ts.map +1 -1
  131. package/dist/mcp/tools/done.js +18 -0
  132. package/dist/mcp/tools/done.js.map +1 -1
  133. package/dist/mcp/types.d.ts +9 -1
  134. package/dist/mcp/types.d.ts.map +1 -1
  135. package/dist/mcp/types.js.map +1 -1
  136. package/dist/metrics/metrics.js +1 -1
  137. package/dist/metrics/metrics.js.map +1 -1
  138. package/dist/roles/builtin/coordinator.d.ts.map +1 -1
  139. package/dist/roles/builtin/coordinator.js +2 -1
  140. package/dist/roles/builtin/coordinator.js.map +1 -1
  141. package/dist/roles/builtin/integrator.d.ts.map +1 -1
  142. package/dist/roles/builtin/integrator.js +2 -1
  143. package/dist/roles/builtin/integrator.js.map +1 -1
  144. package/dist/roles/builtin/worker.d.ts.map +1 -1
  145. package/dist/roles/builtin/worker.js +3 -1
  146. package/dist/roles/builtin/worker.js.map +1 -1
  147. package/dist/roles/capabilities.d.ts +9 -1
  148. package/dist/roles/capabilities.d.ts.map +1 -1
  149. package/dist/roles/capabilities.js +27 -7
  150. package/dist/roles/capabilities.js.map +1 -1
  151. package/dist/roles/config-loader.d.ts +6 -6
  152. package/dist/roles/config-loader.d.ts.map +1 -1
  153. package/dist/roles/config-loader.js +8 -7
  154. package/dist/roles/config-loader.js.map +1 -1
  155. package/dist/roles/registry.d.ts +2 -2
  156. package/dist/roles/registry.js +2 -2
  157. package/dist/roles/types.d.ts +3 -1
  158. package/dist/roles/types.d.ts.map +1 -1
  159. package/dist/server/combined-server.d.ts +28 -1
  160. package/dist/server/combined-server.d.ts.map +1 -1
  161. package/dist/server/combined-server.js +111 -8
  162. package/dist/server/combined-server.js.map +1 -1
  163. package/dist/store/event-store.d.ts +2 -1
  164. package/dist/store/event-store.d.ts.map +1 -1
  165. package/dist/store/event-store.js +80 -24
  166. package/dist/store/event-store.js.map +1 -1
  167. package/dist/store/instance.d.ts +1 -1
  168. package/dist/store/instance.d.ts.map +1 -1
  169. package/dist/store/instance.js +2 -2
  170. package/dist/store/instance.js.map +1 -1
  171. package/dist/store/types/agents.d.ts +23 -0
  172. package/dist/store/types/agents.d.ts.map +1 -1
  173. package/dist/store/types/events.d.ts +1 -1
  174. package/dist/store/types/events.d.ts.map +1 -1
  175. package/dist/task/backend/index.d.ts +47 -29
  176. package/dist/task/backend/index.d.ts.map +1 -1
  177. package/dist/task/backend/index.js +109 -71
  178. package/dist/task/backend/index.js.map +1 -1
  179. package/dist/task/backend/memory.d.ts +1 -0
  180. package/dist/task/backend/memory.d.ts.map +1 -1
  181. package/dist/task/backend/memory.js +3 -0
  182. package/dist/task/backend/memory.js.map +1 -1
  183. package/dist/task/backend/opentasks/backend.d.ts +140 -0
  184. package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
  185. package/dist/task/backend/opentasks/backend.js +1023 -0
  186. package/dist/task/backend/opentasks/backend.js.map +1 -0
  187. package/dist/task/backend/opentasks/client.d.ts +337 -0
  188. package/dist/task/backend/opentasks/client.d.ts.map +1 -0
  189. package/dist/task/backend/opentasks/client.js +225 -0
  190. package/dist/task/backend/opentasks/client.js.map +1 -0
  191. package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
  192. package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
  193. package/dist/task/backend/opentasks/daemon-manager.js +195 -0
  194. package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
  195. package/dist/task/backend/opentasks/index.d.ts +21 -0
  196. package/dist/task/backend/opentasks/index.d.ts.map +1 -0
  197. package/dist/task/backend/opentasks/index.js +21 -0
  198. package/dist/task/backend/opentasks/index.js.map +1 -0
  199. package/dist/task/backend/opentasks/mapping.d.ts +48 -0
  200. package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
  201. package/dist/task/backend/opentasks/mapping.js +77 -0
  202. package/dist/task/backend/opentasks/mapping.js.map +1 -0
  203. package/dist/task/backend/types.d.ts +33 -53
  204. package/dist/task/backend/types.d.ts.map +1 -1
  205. package/dist/task/backend/types.js +7 -11
  206. package/dist/task/backend/types.js.map +1 -1
  207. package/dist/task/backend/unified-tool-provider.d.ts +57 -0
  208. package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
  209. package/dist/task/backend/unified-tool-provider.js +623 -0
  210. package/dist/task/backend/unified-tool-provider.js.map +1 -0
  211. package/dist/teams/index.d.ts +3 -1
  212. package/dist/teams/index.d.ts.map +1 -1
  213. package/dist/teams/index.js +2 -0
  214. package/dist/teams/index.js.map +1 -1
  215. package/dist/teams/seed-defaults.d.ts +20 -0
  216. package/dist/teams/seed-defaults.d.ts.map +1 -0
  217. package/dist/teams/seed-defaults.js +71 -0
  218. package/dist/teams/seed-defaults.js.map +1 -0
  219. package/dist/teams/team-loader.d.ts +7 -3
  220. package/dist/teams/team-loader.d.ts.map +1 -1
  221. package/dist/teams/team-loader.js +156 -164
  222. package/dist/teams/team-loader.js.map +1 -1
  223. package/dist/teams/team-manager.d.ts +112 -0
  224. package/dist/teams/team-manager.d.ts.map +1 -0
  225. package/dist/teams/team-manager.js +305 -0
  226. package/dist/teams/team-manager.js.map +1 -0
  227. package/dist/teams/team-runtime.d.ts +125 -19
  228. package/dist/teams/team-runtime.d.ts.map +1 -1
  229. package/dist/teams/team-runtime.js +529 -119
  230. package/dist/teams/team-runtime.js.map +1 -1
  231. package/dist/teams/types.d.ts +41 -151
  232. package/dist/teams/types.d.ts.map +1 -1
  233. package/dist/teams/types.js +2 -3
  234. package/dist/teams/types.js.map +1 -1
  235. package/docs/architecture.md +7 -6
  236. package/docs/configuration.md +26 -62
  237. package/docs/implementation-details.md +5 -5
  238. package/docs/implementation-summary.md +17 -17
  239. package/docs/plan-self-driving-support.md +4 -4
  240. package/docs/spec-self-driving-support.md +10 -10
  241. package/docs/team-templates.md +2 -2
  242. package/docs/teams.md +76 -3
  243. package/docs/troubleshooting.md +10 -11
  244. package/package.json +7 -4
  245. package/references/minimem/.claude/settings.json +7 -0
  246. package/references/minimem/.sudocode/issues.jsonl +18 -0
  247. package/references/minimem/.sudocode/specs.jsonl +1 -0
  248. package/references/minimem/CLAUDE.md +310 -0
  249. package/references/minimem/README.md +562 -0
  250. package/references/minimem/claude-plugin/.claude-plugin/plugin.json +10 -0
  251. package/references/minimem/claude-plugin/.mcp.json +7 -0
  252. package/references/minimem/claude-plugin/README.md +158 -0
  253. package/references/minimem/claude-plugin/commands/recall.md +47 -0
  254. package/references/minimem/claude-plugin/commands/remember.md +41 -0
  255. package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +272 -0
  256. package/references/minimem/claude-plugin/hooks/hooks.json +27 -0
  257. package/references/minimem/claude-plugin/hooks/session-end.sh +86 -0
  258. package/references/minimem/claude-plugin/hooks/session-start.sh +85 -0
  259. package/references/minimem/claude-plugin/skills/memory/SKILL.md +108 -0
  260. package/references/minimem/media/banner.png +0 -0
  261. package/references/minimem/package-lock.json +5373 -0
  262. package/references/minimem/package.json +72 -0
  263. package/references/minimem/scripts/postbuild.js +35 -0
  264. package/references/minimem/src/__tests__/edge-cases.test.ts +371 -0
  265. package/references/minimem/src/__tests__/errors.test.ts +265 -0
  266. package/references/minimem/src/__tests__/helpers.ts +199 -0
  267. package/references/minimem/src/__tests__/internal.test.ts +407 -0
  268. package/references/minimem/src/__tests__/knowledge.test.ts +287 -0
  269. package/references/minimem/src/__tests__/minimem.integration.test.ts +1127 -0
  270. package/references/minimem/src/__tests__/session.test.ts +190 -0
  271. package/references/minimem/src/cli/__tests__/commands.test.ts +759 -0
  272. package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +141 -0
  273. package/references/minimem/src/cli/commands/append.ts +76 -0
  274. package/references/minimem/src/cli/commands/config.ts +262 -0
  275. package/references/minimem/src/cli/commands/conflicts.ts +413 -0
  276. package/references/minimem/src/cli/commands/daemon.ts +169 -0
  277. package/references/minimem/src/cli/commands/index.ts +12 -0
  278. package/references/minimem/src/cli/commands/init.ts +88 -0
  279. package/references/minimem/src/cli/commands/mcp.ts +177 -0
  280. package/references/minimem/src/cli/commands/push-pull.ts +213 -0
  281. package/references/minimem/src/cli/commands/search.ts +158 -0
  282. package/references/minimem/src/cli/commands/status.ts +84 -0
  283. package/references/minimem/src/cli/commands/sync-init.ts +290 -0
  284. package/references/minimem/src/cli/commands/sync.ts +70 -0
  285. package/references/minimem/src/cli/commands/upsert.ts +197 -0
  286. package/references/minimem/src/cli/config.ts +584 -0
  287. package/references/minimem/src/cli/index.ts +264 -0
  288. package/references/minimem/src/cli/shared.ts +161 -0
  289. package/references/minimem/src/cli/sync/__tests__/central.test.ts +152 -0
  290. package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +209 -0
  291. package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +118 -0
  292. package/references/minimem/src/cli/sync/__tests__/detection.test.ts +207 -0
  293. package/references/minimem/src/cli/sync/__tests__/integration.test.ts +476 -0
  294. package/references/minimem/src/cli/sync/__tests__/registry.test.ts +363 -0
  295. package/references/minimem/src/cli/sync/__tests__/state.test.ts +255 -0
  296. package/references/minimem/src/cli/sync/__tests__/validation.test.ts +193 -0
  297. package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +178 -0
  298. package/references/minimem/src/cli/sync/central.ts +292 -0
  299. package/references/minimem/src/cli/sync/conflicts.ts +204 -0
  300. package/references/minimem/src/cli/sync/daemon.ts +407 -0
  301. package/references/minimem/src/cli/sync/detection.ts +138 -0
  302. package/references/minimem/src/cli/sync/index.ts +107 -0
  303. package/references/minimem/src/cli/sync/operations.ts +373 -0
  304. package/references/minimem/src/cli/sync/registry.ts +279 -0
  305. package/references/minimem/src/cli/sync/state.ts +355 -0
  306. package/references/minimem/src/cli/sync/validation.ts +206 -0
  307. package/references/minimem/src/cli/sync/watcher.ts +234 -0
  308. package/references/minimem/src/cli/version.ts +34 -0
  309. package/references/minimem/src/core/index.ts +9 -0
  310. package/references/minimem/src/core/indexer.ts +628 -0
  311. package/references/minimem/src/core/searcher.ts +221 -0
  312. package/references/minimem/src/db/schema.ts +183 -0
  313. package/references/minimem/src/db/sqlite-vec.ts +24 -0
  314. package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +431 -0
  315. package/references/minimem/src/embeddings/batch-gemini.ts +392 -0
  316. package/references/minimem/src/embeddings/batch-openai.ts +409 -0
  317. package/references/minimem/src/embeddings/embeddings.ts +434 -0
  318. package/references/minimem/src/index.ts +109 -0
  319. package/references/minimem/src/internal.ts +299 -0
  320. package/references/minimem/src/minimem.ts +1276 -0
  321. package/references/minimem/src/search/__tests__/hybrid.test.ts +247 -0
  322. package/references/minimem/src/search/graph.ts +234 -0
  323. package/references/minimem/src/search/hybrid.ts +151 -0
  324. package/references/minimem/src/search/search.ts +256 -0
  325. package/references/minimem/src/server/__tests__/mcp.test.ts +341 -0
  326. package/references/minimem/src/server/__tests__/tools.test.ts +364 -0
  327. package/references/minimem/src/server/mcp.ts +326 -0
  328. package/references/minimem/src/server/tools.ts +720 -0
  329. package/references/minimem/src/session.ts +460 -0
  330. package/references/minimem/tsconfig.json +19 -0
  331. package/references/minimem/tsup.config.ts +26 -0
  332. package/references/minimem/vitest.config.ts +24 -0
  333. package/references/openteams/.claude/settings.json +6 -0
  334. package/references/openteams/README.md +1 -0
  335. package/references/openteams/SKILL.md +341 -0
  336. package/references/openteams/design.md +411 -0
  337. package/references/openteams/examples/bmad-method/prompts/analyst/ROLE.md +16 -0
  338. package/references/openteams/examples/bmad-method/prompts/analyst/SOUL.md +5 -0
  339. package/references/openteams/examples/bmad-method/prompts/architect/ROLE.md +24 -0
  340. package/references/openteams/examples/bmad-method/prompts/architect/SOUL.md +5 -0
  341. package/references/openteams/examples/bmad-method/prompts/developer/ROLE.md +25 -0
  342. package/references/openteams/examples/bmad-method/prompts/developer/SOUL.md +5 -0
  343. package/references/openteams/examples/bmad-method/prompts/master/ROLE.md +21 -0
  344. package/references/openteams/examples/bmad-method/prompts/master/SOUL.md +5 -0
  345. package/references/openteams/examples/bmad-method/prompts/pm/ROLE.md +20 -0
  346. package/references/openteams/examples/bmad-method/prompts/pm/SOUL.md +5 -0
  347. package/references/openteams/examples/bmad-method/prompts/qa/ROLE.md +17 -0
  348. package/references/openteams/examples/bmad-method/prompts/qa/SOUL.md +5 -0
  349. package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/ROLE.md +23 -0
  350. package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/SOUL.md +5 -0
  351. package/references/openteams/examples/bmad-method/prompts/scrum-master/ROLE.md +27 -0
  352. package/references/openteams/examples/bmad-method/prompts/scrum-master/SOUL.md +5 -0
  353. package/references/openteams/examples/bmad-method/prompts/tech-writer/ROLE.md +21 -0
  354. package/references/openteams/examples/bmad-method/prompts/tech-writer/SOUL.md +5 -0
  355. package/references/openteams/examples/bmad-method/prompts/ux-designer/ROLE.md +16 -0
  356. package/references/openteams/examples/bmad-method/prompts/ux-designer/SOUL.md +5 -0
  357. package/references/openteams/examples/bmad-method/roles/analyst.yaml +9 -0
  358. package/references/openteams/examples/bmad-method/roles/architect.yaml +9 -0
  359. package/references/openteams/examples/bmad-method/roles/developer.yaml +8 -0
  360. package/references/openteams/examples/bmad-method/roles/master.yaml +8 -0
  361. package/references/openteams/examples/bmad-method/roles/pm.yaml +9 -0
  362. package/references/openteams/examples/bmad-method/roles/qa.yaml +8 -0
  363. package/references/openteams/examples/bmad-method/roles/quick-flow-dev.yaml +8 -0
  364. package/references/openteams/examples/bmad-method/roles/scrum-master.yaml +9 -0
  365. package/references/openteams/examples/bmad-method/roles/tech-writer.yaml +8 -0
  366. package/references/openteams/examples/bmad-method/roles/ux-designer.yaml +8 -0
  367. package/references/openteams/examples/bmad-method/team.yaml +161 -0
  368. package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/ROLE.md +17 -0
  369. package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/SOUL.md +5 -0
  370. package/references/openteams/examples/get-shit-done/prompts/debugger/ROLE.md +25 -0
  371. package/references/openteams/examples/get-shit-done/prompts/debugger/SOUL.md +5 -0
  372. package/references/openteams/examples/get-shit-done/prompts/executor/ROLE.md +34 -0
  373. package/references/openteams/examples/get-shit-done/prompts/executor/SOUL.md +5 -0
  374. package/references/openteams/examples/get-shit-done/prompts/integration-checker/ROLE.md +18 -0
  375. package/references/openteams/examples/get-shit-done/prompts/integration-checker/SOUL.md +3 -0
  376. package/references/openteams/examples/get-shit-done/prompts/orchestrator/ROLE.md +42 -0
  377. package/references/openteams/examples/get-shit-done/prompts/orchestrator/SOUL.md +5 -0
  378. package/references/openteams/examples/get-shit-done/prompts/phase-researcher/ROLE.md +15 -0
  379. package/references/openteams/examples/get-shit-done/prompts/phase-researcher/SOUL.md +3 -0
  380. package/references/openteams/examples/get-shit-done/prompts/plan-checker/ROLE.md +17 -0
  381. package/references/openteams/examples/get-shit-done/prompts/plan-checker/SOUL.md +3 -0
  382. package/references/openteams/examples/get-shit-done/prompts/planner/ROLE.md +28 -0
  383. package/references/openteams/examples/get-shit-done/prompts/planner/SOUL.md +5 -0
  384. package/references/openteams/examples/get-shit-done/prompts/project-researcher/ROLE.md +16 -0
  385. package/references/openteams/examples/get-shit-done/prompts/project-researcher/SOUL.md +3 -0
  386. package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/ROLE.md +13 -0
  387. package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/SOUL.md +3 -0
  388. package/references/openteams/examples/get-shit-done/prompts/roadmapper/ROLE.md +14 -0
  389. package/references/openteams/examples/get-shit-done/prompts/roadmapper/SOUL.md +3 -0
  390. package/references/openteams/examples/get-shit-done/prompts/verifier/ROLE.md +19 -0
  391. package/references/openteams/examples/get-shit-done/prompts/verifier/SOUL.md +5 -0
  392. package/references/openteams/examples/get-shit-done/roles/codebase-mapper.yaml +8 -0
  393. package/references/openteams/examples/get-shit-done/roles/debugger.yaml +8 -0
  394. package/references/openteams/examples/get-shit-done/roles/executor.yaml +8 -0
  395. package/references/openteams/examples/get-shit-done/roles/integration-checker.yaml +8 -0
  396. package/references/openteams/examples/get-shit-done/roles/orchestrator.yaml +9 -0
  397. package/references/openteams/examples/get-shit-done/roles/phase-researcher.yaml +7 -0
  398. package/references/openteams/examples/get-shit-done/roles/plan-checker.yaml +8 -0
  399. package/references/openteams/examples/get-shit-done/roles/planner.yaml +8 -0
  400. package/references/openteams/examples/get-shit-done/roles/project-researcher.yaml +8 -0
  401. package/references/openteams/examples/get-shit-done/roles/research-synthesizer.yaml +7 -0
  402. package/references/openteams/examples/get-shit-done/roles/roadmapper.yaml +7 -0
  403. package/references/openteams/examples/get-shit-done/roles/verifier.yaml +8 -0
  404. package/references/openteams/examples/get-shit-done/team.yaml +154 -0
  405. package/references/openteams/package-lock.json +2181 -0
  406. package/references/openteams/package.json +48 -0
  407. package/references/openteams/schema/role.schema.json +125 -0
  408. package/references/openteams/schema/team.schema.json +284 -0
  409. package/references/openteams/src/cli/agent.ts +104 -0
  410. package/references/openteams/src/cli/cli.test.ts +381 -0
  411. package/references/openteams/src/cli/generate.ts +220 -0
  412. package/references/openteams/src/cli/message.ts +241 -0
  413. package/references/openteams/src/cli/task.ts +154 -0
  414. package/references/openteams/src/cli/team.ts +104 -0
  415. package/references/openteams/src/cli/template.ts +207 -0
  416. package/references/openteams/src/cli.ts +45 -0
  417. package/references/openteams/src/db/database.test.ts +185 -0
  418. package/references/openteams/src/db/database.ts +240 -0
  419. package/references/openteams/src/generators/agent-prompt-generator.test.ts +332 -0
  420. package/references/openteams/src/generators/agent-prompt-generator.ts +521 -0
  421. package/references/openteams/src/generators/package-generator.test.ts +129 -0
  422. package/references/openteams/src/generators/package-generator.ts +102 -0
  423. package/references/openteams/src/generators/skill-generator.test.ts +246 -0
  424. package/references/openteams/src/generators/skill-generator.ts +374 -0
  425. package/references/openteams/src/index.ts +104 -0
  426. package/references/openteams/src/services/agent-service.test.ts +158 -0
  427. package/references/openteams/src/services/agent-service.ts +84 -0
  428. package/references/openteams/src/services/communication-service.test.ts +455 -0
  429. package/references/openteams/src/services/communication-service.ts +371 -0
  430. package/references/openteams/src/services/message-service.test.ts +342 -0
  431. package/references/openteams/src/services/message-service.ts +203 -0
  432. package/references/openteams/src/services/task-service.test.ts +434 -0
  433. package/references/openteams/src/services/task-service.ts +239 -0
  434. package/references/openteams/src/services/team-service.test.ts +181 -0
  435. package/references/openteams/src/services/team-service.ts +139 -0
  436. package/references/openteams/src/services/template-service.test.ts +306 -0
  437. package/references/openteams/src/services/template-service.ts +182 -0
  438. package/references/openteams/src/spawner/acp-factory.ts +96 -0
  439. package/references/openteams/src/spawner/interface.ts +31 -0
  440. package/references/openteams/src/spawner/mock.test.ts +93 -0
  441. package/references/openteams/src/spawner/mock.ts +59 -0
  442. package/references/openteams/src/template/loader.test.ts +1319 -0
  443. package/references/openteams/src/template/loader.ts +698 -0
  444. package/references/openteams/src/template/types.ts +200 -0
  445. package/references/openteams/src/types.ts +205 -0
  446. package/references/openteams/tsconfig.json +18 -0
  447. package/references/openteams/vitest.config.ts +9 -0
  448. package/references/skill-tree/.claude/settings.json +6 -0
  449. package/references/skill-tree/.sudocode/issues.jsonl +11 -0
  450. package/references/skill-tree/.sudocode/specs.jsonl +1 -0
  451. package/references/skill-tree/CLAUDE.md +150 -0
  452. package/references/skill-tree/README.md +324 -0
  453. package/references/skill-tree/docs/GAPS_v1.md +221 -0
  454. package/references/skill-tree/docs/INTEGRATION_PLAN.md +467 -0
  455. package/references/skill-tree/docs/TODOS.md +91 -0
  456. package/references/skill-tree/docs/anthropic_skill_guide.md +1364 -0
  457. package/references/skill-tree/docs/design/federated-skill-trees.md +524 -0
  458. package/references/skill-tree/docs/design/multi-agent-sync.md +759 -0
  459. package/references/skill-tree/docs/scraper/BRAINSTORM.md +583 -0
  460. package/references/skill-tree/docs/scraper/POC_PLAN.md +420 -0
  461. package/references/skill-tree/docs/scraper/README.md +170 -0
  462. package/references/skill-tree/examples/basic-usage.ts +190 -0
  463. package/references/skill-tree/package-lock.json +1509 -0
  464. package/references/skill-tree/package.json +66 -0
  465. package/references/skill-tree/scraper/README.md +123 -0
  466. package/references/skill-tree/scraper/docs/DESIGN.md +683 -0
  467. package/references/skill-tree/scraper/docs/PLAN.md +336 -0
  468. package/references/skill-tree/scraper/drizzle.config.ts +10 -0
  469. package/references/skill-tree/scraper/package-lock.json +6329 -0
  470. package/references/skill-tree/scraper/package.json +68 -0
  471. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +7 -0
  472. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +7 -0
  473. package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +27 -0
  474. package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +21 -0
  475. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +54 -0
  476. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +24 -0
  477. package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +93 -0
  478. package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +22 -0
  479. package/references/skill-tree/scraper/tsup.config.ts +14 -0
  480. package/references/skill-tree/scraper/vitest.config.ts +17 -0
  481. package/references/skill-tree/scripts/convert-to-vitest.ts +166 -0
  482. package/references/skill-tree/skills/skill-writer/SKILL.md +339 -0
  483. package/references/skill-tree/skills/skill-writer/references/examples.md +326 -0
  484. package/references/skill-tree/skills/skill-writer/references/patterns.md +210 -0
  485. package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +123 -0
  486. package/references/skill-tree/test/run-all.ts +106 -0
  487. package/references/skill-tree/test/utils.ts +128 -0
  488. package/references/skill-tree/vitest.config.ts +16 -0
  489. package/src/__tests__/e2e/agent-spawn-visibility.e2e.test.ts +761 -0
  490. package/src/__tests__/e2e/full-agent-conflict-resolution.e2e.test.ts +2 -2
  491. package/src/__tests__/e2e/mcp-thin-client-bridge.e2e.test.ts +304 -0
  492. package/src/__tests__/e2e/mcp-tools-available.e2e.test.ts +324 -0
  493. package/src/__tests__/e2e/multi-agent.e2e.test.ts +5 -5
  494. package/src/__tests__/e2e/spawn-session-streaming.e2e.test.ts +563 -0
  495. package/src/acp/__tests__/integration.test.ts +56 -31
  496. package/src/acp/__tests__/macro-agent.test.ts +16 -7
  497. package/src/acp/macro-agent.ts +170 -36
  498. package/src/acp/types.ts +46 -1
  499. package/src/agent/__tests__/agent-manager.test.ts +228 -2
  500. package/src/agent/agent-manager.ts +809 -285
  501. package/src/agent/types.ts +12 -1
  502. package/src/api/__tests__/server.test.ts +203 -4
  503. package/src/api/server.ts +169 -10
  504. package/src/api/types.ts +3 -1
  505. package/src/auth/__tests__/token.test.ts +100 -0
  506. package/src/auth/index.ts +1 -0
  507. package/src/auth/token.ts +82 -0
  508. package/src/cli/__tests__/acp.test.ts +1 -1
  509. package/src/cli/__tests__/stable-instance-id.test.ts +1 -1
  510. package/src/cli/acp.ts +197 -72
  511. package/src/cli/index.ts +125 -15
  512. package/src/cli/mcp.ts +315 -197
  513. package/src/cli/parse-args.ts +54 -0
  514. package/src/cli/stable-instance-id.ts +14 -0
  515. package/src/config/project-config.ts +214 -27
  516. package/src/index.ts +3 -0
  517. package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
  518. package/src/lifecycle/__tests__/handlers.test.ts +53 -0
  519. package/src/lifecycle/handlers/index.ts +25 -8
  520. package/src/lifecycle/types.ts +3 -0
  521. package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +22 -4
  522. package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
  523. package/src/map/adapter/__tests__/acp-over-map-history.test.ts +263 -0
  524. package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +1 -1
  525. package/src/map/adapter/__tests__/event-broadcast.test.ts +420 -0
  526. package/src/map/adapter/__tests__/event-log.test.ts +527 -0
  527. package/src/map/adapter/__tests__/event-translator.test.ts +3 -3
  528. package/src/map/adapter/__tests__/extensions.test.ts +408 -0
  529. package/src/map/adapter/__tests__/map-adapter.test.ts +99 -0
  530. package/src/map/adapter/__tests__/mcp-bridge.test.ts +1187 -0
  531. package/src/map/adapter/__tests__/multi-client-broadcast.test.ts +711 -0
  532. package/src/map/adapter/__tests__/stream-extensions.test.ts +494 -0
  533. package/src/map/adapter/__tests__/websocket-integration.test.ts +218 -0
  534. package/src/map/adapter/acp-over-map.ts +678 -66
  535. package/src/map/adapter/connection-manager.ts +3 -0
  536. package/src/map/adapter/event-log.ts +208 -0
  537. package/src/map/adapter/event-translator.ts +6 -6
  538. package/src/map/adapter/extensions/agent-lifecycle.ts +267 -0
  539. package/src/map/adapter/extensions/index.ts +96 -0
  540. package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
  541. package/src/map/adapter/extensions/streams.ts +839 -0
  542. package/src/map/adapter/extensions/task.ts +11 -0
  543. package/src/map/adapter/extensions/update-metadata.ts +126 -0
  544. package/src/map/adapter/index.ts +33 -0
  545. package/src/map/adapter/interface.ts +2 -0
  546. package/src/map/adapter/map-adapter.ts +312 -47
  547. package/src/map/adapter/subscription-manager.ts +5 -1
  548. package/src/map/adapter/types.ts +10 -1
  549. package/src/mcp/__tests__/map-client.test.ts +386 -0
  550. package/src/mcp/__tests__/mcp-server-thin-client.test.ts +368 -0
  551. package/src/mcp/__tests__/mcp-server.test.ts +100 -1
  552. package/src/mcp/map-client.ts +177 -0
  553. package/src/mcp/mcp-server.ts +205 -103
  554. package/src/mcp/tools/done.ts +19 -0
  555. package/src/mcp/types.ts +6 -1
  556. package/src/metrics/metrics.ts +1 -1
  557. package/src/monitor/__tests__/stale-agent-flow.integration.test.ts +1 -1
  558. package/src/roles/__tests__/config-loader.test.ts +7 -7
  559. package/src/roles/builtin/coordinator.ts +2 -0
  560. package/src/roles/builtin/integrator.ts +2 -0
  561. package/src/roles/builtin/worker.ts +3 -0
  562. package/src/roles/capabilities.ts +28 -7
  563. package/src/roles/config-loader.ts +8 -7
  564. package/src/roles/registry.ts +2 -2
  565. package/src/roles/types.ts +7 -0
  566. package/src/server/__tests__/combined-server.test.ts +94 -21
  567. package/src/server/combined-server.ts +203 -33
  568. package/src/steering/__tests__/steering-integration.test.ts +1 -1
  569. package/src/store/__tests__/event-store-oob.test.ts +109 -0
  570. package/src/store/__tests__/event-store.test.ts +196 -1
  571. package/src/store/__tests__/instance.test.ts +3 -3
  572. package/src/store/event-store.ts +92 -23
  573. package/src/store/instance.ts +2 -2
  574. package/src/store/types/agents.ts +20 -0
  575. package/src/store/types/events.ts +1 -1
  576. package/src/task/backend/__tests__/create-task-backend.test.ts +225 -0
  577. package/src/task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test.ts +524 -0
  578. package/src/task/backend/__tests__/memory-pull-mode.test.ts +153 -0
  579. package/src/task/backend/__tests__/unified-tool-provider.test.ts +579 -0
  580. package/src/task/backend/index.ts +156 -106
  581. package/src/task/backend/memory.ts +4 -0
  582. package/src/task/backend/opentasks/__tests__/backend.test.ts +968 -0
  583. package/src/task/backend/opentasks/__tests__/daemon-manager.test.ts +406 -0
  584. package/src/task/backend/opentasks/__tests__/mapping.test.ts +84 -0
  585. package/src/task/backend/opentasks/__tests__/opentasks-backend.e2e.test.ts +1338 -0
  586. package/src/task/backend/opentasks/backend.ts +1323 -0
  587. package/src/task/backend/opentasks/client.ts +652 -0
  588. package/src/task/backend/opentasks/daemon-manager.ts +256 -0
  589. package/src/task/backend/opentasks/index.ts +69 -0
  590. package/src/task/backend/opentasks/mapping.ts +94 -0
  591. package/src/task/backend/types.ts +42 -66
  592. package/src/task/backend/unified-tool-provider.ts +779 -0
  593. package/src/teams/CLAUDE.md +180 -0
  594. package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
  595. package/src/teams/__tests__/e2e/workspace-isolation.e2e.test.ts +1263 -0
  596. package/src/teams/__tests__/team-manager.test.ts +814 -0
  597. package/src/teams/__tests__/team-system.test.ts +1291 -8
  598. package/src/teams/index.ts +21 -3
  599. package/src/teams/seed-defaults.ts +79 -0
  600. package/src/teams/team-loader.ts +202 -236
  601. package/src/teams/team-manager.ts +387 -0
  602. package/src/teams/team-runtime.ts +592 -121
  603. package/src/teams/types.ts +99 -200
  604. package/test_fixtures/README.md +2 -3
  605. package/test_fixtures/fixtures/index.ts +0 -3
  606. package/test_fixtures/fixtures/projects/project-with-specs.ts +7 -149
  607. package/test_fixtures/fixtures/repos/index.ts +1 -3
  608. package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -116
  609. package/test_fixtures/fixtures/repos/types.ts +0 -11
  610. package/test_fixtures/harness/__tests__/fixtures.test.ts +10 -102
  611. package/test_fixtures/harness/__tests__/temp-repo-and-simulator.test.ts +0 -33
  612. package/test_fixtures/harness/simulator/agent-simulator.ts +4 -4
  613. package/vitest.config.ts +1 -1
  614. package/vitest.e2e.config.ts +1 -1
  615. package/vitest.setup.ts +1 -30
  616. package/.macro-agent/teams/self-driving/prompts/grinder.md +0 -27
  617. package/.macro-agent/teams/self-driving/prompts/judge.md +0 -27
  618. package/.macro-agent/teams/self-driving/prompts/planner.md +0 -33
  619. package/.macro-agent/teams/self-driving/roles/grinder.yaml +0 -17
  620. package/.macro-agent/teams/self-driving/roles/judge.yaml +0 -24
  621. package/.macro-agent/teams/self-driving/roles/planner.yaml +0 -18
  622. package/.macro-agent/teams/self-driving/team.yaml +0 -103
  623. package/.macro-agent/teams/structured/prompts/developer.md +0 -26
  624. package/.macro-agent/teams/structured/prompts/lead.md +0 -25
  625. package/.macro-agent/teams/structured/prompts/reviewer.md +0 -24
  626. package/.macro-agent/teams/structured/roles/developer.yaml +0 -12
  627. package/.macro-agent/teams/structured/roles/lead.yaml +0 -11
  628. package/.macro-agent/teams/structured/roles/reviewer.yaml +0 -19
  629. package/.macro-agent/teams/structured/team.yaml +0 -89
  630. package/docs/sudocode-integration.md +0 -383
  631. package/src/task/backend/__tests__/backend-parity.test.ts +0 -451
  632. package/src/task/backend/__tests__/tool-provider-edge-cases.test.ts +0 -430
  633. package/src/task/backend/__tests__/tool-provider.test.ts +0 -983
  634. package/src/task/backend/sudocode/__tests__/backend-edge-cases.test.ts +0 -575
  635. package/src/task/backend/sudocode/__tests__/backend.test.ts +0 -1194
  636. package/src/task/backend/sudocode/__tests__/client-integration.test.ts +0 -418
  637. package/src/task/backend/sudocode/__tests__/client.test.ts +0 -345
  638. package/src/task/backend/sudocode/__tests__/e2e/backend.e2e.test.ts +0 -753
  639. package/src/task/backend/sudocode/__tests__/e2e/server-client.e2e.test.ts +0 -680
  640. package/src/task/backend/sudocode/__tests__/e2e-workflow.test.ts +0 -666
  641. package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts +0 -396
  642. package/src/task/backend/sudocode/__tests__/integration/sudocode-cli.integration.test.ts +0 -328
  643. package/src/task/backend/sudocode/__tests__/integration/test-utils.ts +0 -175
  644. package/src/task/backend/sudocode/__tests__/mapping-edge-cases.test.ts +0 -265
  645. package/src/task/backend/sudocode/__tests__/server-client.test.ts +0 -675
  646. package/src/task/backend/sudocode/__tests__/sync-policy-edge-cases.test.ts +0 -521
  647. package/src/task/backend/sudocode/__tests__/sync-policy.test.ts +0 -519
  648. package/src/task/backend/sudocode/__tests__/tools.test.ts +0 -471
  649. package/src/task/backend/sudocode/backend.ts +0 -1237
  650. package/src/task/backend/sudocode/client.ts +0 -515
  651. package/src/task/backend/sudocode/index.ts +0 -120
  652. package/src/task/backend/sudocode/mapping.ts +0 -93
  653. package/src/task/backend/sudocode/server-client.ts +0 -522
  654. package/src/task/backend/sudocode/standalone-client.ts +0 -623
  655. package/src/task/backend/sudocode/sync-policy.ts +0 -387
  656. package/src/task/backend/sudocode/tools.ts +0 -896
  657. package/src/task/backend/tool-provider.ts +0 -506
  658. package/test_fixtures/fixtures/sudocode/index.ts +0 -29
  659. package/test_fixtures/fixtures/sudocode/issues.ts +0 -185
  660. package/test_fixtures/fixtures/sudocode/specs.ts +0 -159
@@ -11,7 +11,9 @@
11
11
  import type { AgentManager } from "../../agent/agent-manager.js";
12
12
  import type { EventStore } from "../../store/event-store.js";
13
13
  import type { TaskManager } from "../../task/task-manager.js";
14
- import type { AgentId } from "../../store/types/index.js";
14
+ import type { AgentId, TaskId } from "../../store/types/index.js";
15
+ import type { AgentConfig } from "../../agent/types.js";
16
+ import type { TaskFilter } from "../../task/types.js";
15
17
  import { SessionMapper } from "../../acp/session-mapper.js";
16
18
  import type { ACPSessionId } from "../../acp/types.js";
17
19
 
@@ -23,10 +25,14 @@ import type { ACPSessionId } from "../../acp/types.js";
23
25
  function extractToolOutput(rawOutput: unknown): string | undefined {
24
26
  if (typeof rawOutput === "string") return rawOutput;
25
27
  if (Array.isArray(rawOutput)) {
26
- return rawOutput
27
- .filter((item: any) => item.type === "text" && typeof item.text === "string")
28
- .map((item: any) => item.text as string)
29
- .join("\n") || undefined;
28
+ return (
29
+ rawOutput
30
+ .filter(
31
+ (item: any) => item.type === "text" && typeof item.text === "string",
32
+ )
33
+ .map((item: any) => item.text as string)
34
+ .join("\n") || undefined
35
+ );
30
36
  }
31
37
  return undefined;
32
38
  }
@@ -56,6 +62,18 @@ export interface ACPOverMAPConfig {
56
62
  eventStore: EventStore;
57
63
  taskManager: TaskManager;
58
64
  defaultCwd?: string;
65
+
66
+ /**
67
+ * Callback when a new agent is created via session/new or session/loadSession.
68
+ * Used by MAPAdapter to emit agent.registered events to all subscribers.
69
+ */
70
+ onAgentRegistered?: (agent: {
71
+ id: string;
72
+ name?: string;
73
+ role?: string;
74
+ parent?: string;
75
+ metadata?: Record<string, unknown>;
76
+ }) => void;
59
77
  }
60
78
 
61
79
  /**
@@ -70,6 +88,8 @@ interface StreamState {
70
88
  sessionId?: string;
71
89
  agentId?: AgentId;
72
90
  abortController: AbortController;
91
+ /** Permission mode from initialization _meta */
92
+ permissionMode?: "auto-approve" | "auto-deny" | "callback" | "interactive";
73
93
  }
74
94
 
75
95
  // ─────────────────────────────────────────────────────────────────
@@ -81,18 +101,45 @@ export class ACPOverMAPHandler {
81
101
  private eventStore: EventStore;
82
102
  private taskManager: TaskManager;
83
103
  private defaultCwd: string;
104
+ private onAgentRegistered?: ACPOverMAPConfig["onAgentRegistered"];
84
105
 
85
106
  /** Stream states by streamId */
86
107
  private streams: Map<string, StreamState> = new Map();
87
108
 
88
109
  /** Session mapper for ACP session -> Agent mapping */
89
- private sessionMapper: SessionMapper = new SessionMapper();
110
+ private sessionMapper: SessionMapper;
90
111
 
91
112
  constructor(config: ACPOverMAPConfig) {
92
113
  this.agentManager = config.agentManager;
93
114
  this.eventStore = config.eventStore;
94
115
  this.taskManager = config.taskManager;
95
116
  this.defaultCwd = config.defaultCwd ?? process.cwd();
117
+ this.onAgentRegistered = config.onAgentRegistered;
118
+
119
+ // Initialize session mapper with EventStore for persistence and recovery
120
+ this.sessionMapper = new SessionMapper(this.eventStore);
121
+ const recovered = this.sessionMapper.recoverFromStore();
122
+ if (recovered > 0) {
123
+ console.error(
124
+ `[ACP-over-MAP] Recovered ${recovered} session(s) from store`,
125
+ );
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Notify subscribers that a new agent was registered.
131
+ * Looks up agent details from EventStore and calls the onAgentRegistered callback.
132
+ */
133
+ private notifyAgentRegistered(agentId: string): void {
134
+ if (!this.onAgentRegistered) return;
135
+ const agent = this.eventStore.getAgent(agentId as AgentId);
136
+ this.onAgentRegistered({
137
+ id: agentId,
138
+ name: agent?.name,
139
+ role: agent?.role,
140
+ parent: agent?.parent ?? undefined,
141
+ metadata: agent?.metadata,
142
+ });
96
143
  }
97
144
 
98
145
  /**
@@ -103,7 +150,9 @@ export class ACPOverMAPHandler {
103
150
  abortStreamsForAgent(agentId: AgentId): void {
104
151
  for (const [streamId, streamState] of this.streams) {
105
152
  if (streamState.agentId === agentId) {
106
- console.error(`[ACP-over-MAP] Aborting stream ${streamId} for stopped agent ${agentId}`);
153
+ console.error(
154
+ `[ACP-over-MAP] Aborting stream ${streamId} for stopped agent ${agentId}`,
155
+ );
107
156
  streamState.abortController.abort();
108
157
  }
109
158
  }
@@ -124,7 +173,9 @@ export class ACPOverMAPHandler {
124
173
  const { streamId, sessionId } = acpContext;
125
174
  const method = acp.method;
126
175
 
127
- console.error(`[ACP-over-MAP] Processing - streamId=${streamId} method=${method}`);
176
+ console.error(
177
+ `[ACP-over-MAP] Processing - streamId=${streamId} method=${method}`,
178
+ );
128
179
 
129
180
  // Get or create stream state
130
181
  let streamState = this.streams.get(streamId);
@@ -147,11 +198,19 @@ export class ACPOverMAPHandler {
147
198
  break;
148
199
 
149
200
  case "session/new":
150
- result = await this.handleNewSession(streamState, acp.params, emitNotification);
201
+ result = await this.handleNewSession(
202
+ streamState,
203
+ acp.params,
204
+ emitNotification,
205
+ );
151
206
  break;
152
207
 
153
208
  case "session/load":
154
- result = await this.handleLoadSession(streamState, acp.params, emitNotification);
209
+ result = await this.handleLoadSession(
210
+ streamState,
211
+ acp.params,
212
+ emitNotification,
213
+ );
155
214
  break;
156
215
 
157
216
  case "authenticate":
@@ -159,7 +218,12 @@ export class ACPOverMAPHandler {
159
218
  break;
160
219
 
161
220
  case "session/prompt":
162
- result = await this.handlePrompt(streamState, acp.params, sessionId, emitNotification);
221
+ result = await this.handlePrompt(
222
+ streamState,
223
+ acp.params,
224
+ sessionId,
225
+ emitNotification,
226
+ );
163
227
  break;
164
228
 
165
229
  case "session/cancel":
@@ -169,7 +233,11 @@ export class ACPOverMAPHandler {
169
233
  default:
170
234
  // Check for extension methods
171
235
  if (method?.startsWith("_")) {
172
- result = await this.handleExtension(streamState, method, acp.params);
236
+ result = await this.handleExtension(
237
+ streamState,
238
+ method,
239
+ acp.params,
240
+ );
173
241
  } else {
174
242
  throw new Error(`Unknown ACP method: ${method}`);
175
243
  }
@@ -211,6 +279,21 @@ export class ACPOverMAPHandler {
211
279
 
212
280
  streamState.initialized = true;
213
281
 
282
+ // Extract permission mode from _meta.macroConfig if provided
283
+ const meta = (params as Record<string, unknown> | undefined)?._meta as
284
+ | Record<string, unknown>
285
+ | undefined;
286
+ const macroConfig = meta?.macroConfig as
287
+ | Record<string, unknown>
288
+ | undefined;
289
+ const defaultSubAgentConfig = macroConfig?.defaultSubAgentConfig as
290
+ | Record<string, unknown>
291
+ | undefined;
292
+ if (defaultSubAgentConfig?.permissionMode) {
293
+ streamState.permissionMode =
294
+ defaultSubAgentConfig.permissionMode as StreamState["permissionMode"];
295
+ }
296
+
214
297
  return {
215
298
  protocolVersion: 1,
216
299
  agentCapabilities: {
@@ -237,13 +320,15 @@ export class ACPOverMAPHandler {
237
320
  throw new Error("Must call initialize before newSession");
238
321
  }
239
322
 
240
- const { cwd, mcpServers } = (params as { cwd?: string; mcpServers?: unknown[] }) ?? {};
323
+ const { cwd, mcpServers } =
324
+ (params as { cwd?: string; mcpServers?: unknown[] }) ?? {};
241
325
  const workingDir = cwd ?? this.defaultCwd;
242
326
 
243
327
  // Spawn a new head manager for this session
244
328
  const spawned = await this.agentManager.getOrCreateHeadManager({
245
329
  cwd: workingDir,
246
330
  forceNew: true,
331
+ permissionMode: streamState.permissionMode,
247
332
  });
248
333
 
249
334
  const sessionId = spawned.session_id;
@@ -253,7 +338,12 @@ export class ACPOverMAPHandler {
253
338
  // Create session mapping
254
339
  this.sessionMapper.createMapping(sessionId as ACPSessionId, spawned.id);
255
340
 
256
- console.error(`[ACP-over-MAP] Created session ${sessionId} -> agent ${spawned.id}`);
341
+ console.error(
342
+ `[ACP-over-MAP] Created session ${sessionId} -> agent ${spawned.id}`,
343
+ );
344
+
345
+ // Notify subscribers that a new agent was registered
346
+ this.notifyAgentRegistered(spawned.id);
257
347
 
258
348
  // Emit session_info_update so client has title/timestamps
259
349
  this.emitSessionInfo(streamState, sessionId, emitNotification);
@@ -270,7 +360,11 @@ export class ACPOverMAPHandler {
270
360
  throw new Error("Must call initialize before loadSession");
271
361
  }
272
362
 
273
- const { sessionId: rawSessionId, cwd, _meta } = (params as {
363
+ const {
364
+ sessionId: rawSessionId,
365
+ cwd,
366
+ _meta,
367
+ } = (params as {
274
368
  sessionId: string;
275
369
  cwd?: string;
276
370
  _meta?: Record<string, unknown>;
@@ -289,8 +383,46 @@ export class ACPOverMAPHandler {
289
383
  }
290
384
  sessionId = agent.session_id;
291
385
  console.error(
292
- `[ACP-over-MAP] loadSession: Resolved agentId ${metaAgentId} to session ${sessionId}`
386
+ `[ACP-over-MAP] loadSession: Resolved agentId ${metaAgentId} to session ${sessionId}`,
387
+ );
388
+
389
+ // Handle the agent directly — works for both head managers and sub-agents.
390
+ // The previous code only searched listHeadManagers(), so sub-agents
391
+ // were never found and a new head manager was created instead.
392
+ if (this.agentManager.hasActiveSession(metaAgentId as AgentId)) {
393
+ console.error(
394
+ `[ACP-over-MAP] loadSession: Reusing active session for agent ${metaAgentId}`,
395
+ );
396
+ } else {
397
+ // Agent exists but no active session — resume it
398
+ console.error(
399
+ `[ACP-over-MAP] loadSession: Resuming agent ${metaAgentId}`,
400
+ );
401
+ try {
402
+ await this.agentManager.resume(
403
+ metaAgentId as AgentId,
404
+ streamState.permissionMode,
405
+ );
406
+ } catch (resumeErr) {
407
+ // ALREADY_RUNNING can happen in a race — safe to ignore
408
+ const code = (resumeErr as { code?: string }).code;
409
+ if (code !== "ALREADY_RUNNING") {
410
+ throw resumeErr;
411
+ }
412
+ console.error(
413
+ `[ACP-over-MAP] loadSession: Agent ${metaAgentId} already running (race), continuing`,
414
+ );
415
+ }
416
+ }
417
+
418
+ streamState.sessionId = sessionId;
419
+ streamState.agentId = metaAgentId as AgentId;
420
+ this.sessionMapper.createMapping(
421
+ sessionId as ACPSessionId,
422
+ metaAgentId as AgentId,
293
423
  );
424
+ this.emitSessionInfo(streamState, sessionId, emitNotification);
425
+ return { sessionId };
294
426
  }
295
427
 
296
428
  const workingDir = cwd ?? this.defaultCwd;
@@ -302,17 +434,27 @@ export class ACPOverMAPHandler {
302
434
  if (existing) {
303
435
  // Check if the agent already has an active session
304
436
  if (this.agentManager.hasActiveSession(existing.id)) {
305
- console.error(`[ACP-over-MAP] loadSession: Reusing existing session for agent ${existing.id}`);
437
+ console.error(
438
+ `[ACP-over-MAP] loadSession: Reusing existing session for agent ${existing.id}`,
439
+ );
306
440
  streamState.sessionId = sessionId;
307
441
  streamState.agentId = existing.id;
308
- this.sessionMapper.createMapping(sessionId as ACPSessionId, existing.id);
442
+ this.sessionMapper.createMapping(
443
+ sessionId as ACPSessionId,
444
+ existing.id,
445
+ );
309
446
  this.emitSessionInfo(streamState, sessionId, emitNotification);
310
447
  return { sessionId };
311
448
  }
312
449
 
313
450
  // Agent exists but no active session - resume it
314
- console.error(`[ACP-over-MAP] loadSession: Resuming stopped agent ${existing.id}`);
315
- const spawned = await this.agentManager.resume(existing.id);
451
+ console.error(
452
+ `[ACP-over-MAP] loadSession: Resuming stopped agent ${existing.id}`,
453
+ );
454
+ const spawned = await this.agentManager.resume(
455
+ existing.id,
456
+ streamState.permissionMode,
457
+ );
316
458
  streamState.sessionId = sessionId;
317
459
  streamState.agentId = spawned.id;
318
460
  this.sessionMapper.createMapping(sessionId as ACPSessionId, spawned.id);
@@ -321,15 +463,22 @@ export class ACPOverMAPHandler {
321
463
  }
322
464
 
323
465
  // No existing agent found - create new with the specified session ID
324
- console.error(`[ACP-over-MAP] loadSession: Creating new agent for session ${sessionId}`);
466
+ console.error(
467
+ `[ACP-over-MAP] loadSession: Creating new agent for session ${sessionId}`,
468
+ );
325
469
  const spawned = await this.agentManager.getOrCreateHeadManager({
326
470
  cwd: workingDir,
327
471
  sessionId,
472
+ permissionMode: streamState.permissionMode,
328
473
  });
329
474
 
330
475
  streamState.sessionId = sessionId;
331
476
  streamState.agentId = spawned.id;
332
477
  this.sessionMapper.createMapping(sessionId as ACPSessionId, spawned.id);
478
+
479
+ // Notify subscribers that a new agent was registered
480
+ this.notifyAgentRegistered(spawned.id);
481
+
333
482
  this.emitSessionInfo(streamState, sessionId, emitNotification);
334
483
 
335
484
  return { sessionId };
@@ -346,15 +495,17 @@ export class ACPOverMAPHandler {
346
495
  sessionIdFromContext?: string,
347
496
  emitNotification?: ACPNotificationEmitter,
348
497
  ): Promise<unknown> {
349
- const { prompt, sessionId: paramSessionId } = (params as {
350
- prompt?: Array<{ type: string; text?: string }>;
351
- sessionId?: string;
352
- messages?: Array<{ role: string; content: string }>;
353
- }) ?? {};
498
+ const { prompt, sessionId: paramSessionId } =
499
+ (params as {
500
+ prompt?: Array<{ type: string; text?: string }>;
501
+ sessionId?: string;
502
+ messages?: Array<{ role: string; content: string }>;
503
+ }) ?? {};
354
504
 
355
505
  // Prefer the server's resolved session ID (set during loadSession) over the
356
506
  // client's acpContext.sessionId which may be stale (e.g., "_resolve_" sentinel)
357
- const sessionId = streamState.sessionId ?? paramSessionId ?? sessionIdFromContext;
507
+ const sessionId =
508
+ streamState.sessionId ?? paramSessionId ?? sessionIdFromContext;
358
509
  if (!sessionId) {
359
510
  throw new Error("No session - call newSession or loadSession first");
360
511
  }
@@ -377,15 +528,21 @@ export class ACPOverMAPHandler {
377
528
  .filter((block) => block.type === "text" && block.text)
378
529
  .map((block) => block.text)
379
530
  .join("\n");
380
- } else if ((params as { messages?: Array<{ content: string }> })?.messages) {
531
+ } else if (
532
+ (params as { messages?: Array<{ content: string }> })?.messages
533
+ ) {
381
534
  // Handle messages format (role/content array)
382
- const messages = (params as { messages: Array<{ role: string; content: string }> }).messages;
535
+ const messages = (
536
+ params as { messages: Array<{ role: string; content: string }> }
537
+ ).messages;
383
538
  messageContent = messages.map((m) => m.content).join("\n");
384
539
  } else {
385
540
  messageContent = JSON.stringify(params);
386
541
  }
387
542
 
388
- console.error(`[ACP-over-MAP] Prompting agent ${agentId} with: ${messageContent.slice(0, 100)}...`);
543
+ console.error(
544
+ `[ACP-over-MAP] Prompting agent ${agentId} with: ${messageContent.slice(0, 100)}...`,
545
+ );
389
546
 
390
547
  // Mark session as processing
391
548
  this.sessionMapper.setProcessing(sessionId as ACPSessionId, true);
@@ -416,21 +573,36 @@ export class ACPOverMAPHandler {
416
573
  this.ensureConversation(sessionId as ACPSessionId, agentId);
417
574
 
418
575
  // Accumulate response content for history recording
419
- const buffer: { parts: Array<{ type: "text"; text: string } | ({ type: "tool" } & Record<string, unknown>)> } = {
576
+ const buffer: {
577
+ parts: Array<
578
+ | { type: "text"; text: string }
579
+ | ({ type: "tool" } & Record<string, unknown>)
580
+ >;
581
+ } = {
420
582
  parts: [],
421
583
  };
422
584
 
423
585
  // Track latest plan for persistence
424
- let latestPlan: Array<{ content: string; priority: string; status: string }> | null = null;
586
+ let latestPlan: Array<{
587
+ content: string;
588
+ priority: string;
589
+ status: string;
590
+ }> | null = null;
425
591
 
426
592
  // Track tool info from initial tool_call events (title, name, input)
427
593
  // so we can merge them when tool_call_update arrives with status "completed"
428
- const toolInfoCache = new Map<string, { title?: string; name?: string; input?: unknown }>();
594
+ const toolInfoCache = new Map<
595
+ string,
596
+ { title?: string; name?: string; input?: unknown }
597
+ >();
429
598
 
430
599
  try {
431
600
  // Stream responses from the agent
432
601
  let updateCount = 0;
433
- for await (const update of this.agentManager.prompt(agentId, messageContent)) {
602
+ for await (const update of this.agentManager.prompt(
603
+ agentId,
604
+ messageContent,
605
+ )) {
434
606
  // Check for cancellation
435
607
  if (streamState.abortController.signal.aborted) {
436
608
  return { stopReason: "cancelled" };
@@ -438,9 +610,16 @@ export class ACPOverMAPHandler {
438
610
 
439
611
  // Accumulate content for history persistence (preserving text/tool interleaving order)
440
612
  const u = update as Record<string, unknown>;
441
- const updateType = u.sessionUpdate as string ?? u.type as string;
613
+ const updateType = (u.sessionUpdate as string) ?? (u.type as string);
614
+
615
+ // Annotate permission_request updates with agentId so clients can respond
616
+ if (updateType === "permission_request") {
617
+ u._agentId = agentId;
618
+ }
442
619
  if (updateType === "agent_message_chunk") {
443
- const content = u.content as { type?: string; text?: string } | undefined;
620
+ const content = u.content as
621
+ | { type?: string; text?: string }
622
+ | undefined;
444
623
  if (content?.text) {
445
624
  const last = buffer.parts[buffer.parts.length - 1];
446
625
  if (last && last.type === "text") {
@@ -450,14 +629,27 @@ export class ACPOverMAPHandler {
450
629
  }
451
630
  }
452
631
  } else if (updateType === "plan") {
453
- const entries = (u as { entries?: Array<{ content: string; priority: string; status: string }> }).entries;
632
+ const entries = (
633
+ u as {
634
+ entries?: Array<{
635
+ content: string;
636
+ priority: string;
637
+ status: string;
638
+ }>;
639
+ }
640
+ ).entries;
454
641
  if (entries) {
455
642
  latestPlan = entries;
456
643
  }
457
- } else if (updateType === "tool_call" || updateType === "tool_call_update") {
644
+ } else if (
645
+ updateType === "tool_call" ||
646
+ updateType === "tool_call_update"
647
+ ) {
458
648
  const toolCallId = u.toolCallId as string | undefined;
459
649
  const status = u.status as string | undefined;
460
- const meta = u._meta as { claudeCode?: { toolName?: string } } | undefined;
650
+ const meta = u._meta as
651
+ | { claudeCode?: { toolName?: string } }
652
+ | undefined;
461
653
 
462
654
  // Cache tool info from initial tool_call events
463
655
  if (updateType === "tool_call" && toolCallId) {
@@ -470,7 +662,9 @@ export class ACPOverMAPHandler {
470
662
 
471
663
  if (status === "completed" || status === "failed") {
472
664
  // Merge cached info for tool_call_update events that lack title/input
473
- const cached = toolCallId ? toolInfoCache.get(toolCallId) : undefined;
665
+ const cached = toolCallId
666
+ ? toolInfoCache.get(toolCallId)
667
+ : undefined;
474
668
  buffer.parts.push({
475
669
  type: "tool",
476
670
  toolCallId,
@@ -492,10 +686,17 @@ export class ACPOverMAPHandler {
492
686
  const wasCancelled = streamState.abortController.signal.aborted;
493
687
  const stopReason = wasCancelled ? "cancelled" : "end_turn";
494
688
 
495
- console.error(`[ACP-over-MAP] Prompt completed for agent ${agentId}, ${updateCount} updates, stopReason=${stopReason}`);
689
+ console.error(
690
+ `[ACP-over-MAP] Prompt completed for agent ${agentId}, ${updateCount} updates, stopReason=${stopReason}`,
691
+ );
496
692
 
497
693
  // Persist conversation turns for history
498
- this.recordPromptTurns(sessionId as ACPSessionId, agentId, messageContent, buffer);
694
+ this.recordPromptTurns(
695
+ sessionId as ACPSessionId,
696
+ agentId,
697
+ messageContent,
698
+ buffer,
699
+ );
499
700
 
500
701
  // Persist latest plan in EventStore for history loading across restarts
501
702
  if (latestPlan) {
@@ -507,10 +708,32 @@ export class ACPOverMAPHandler {
507
708
 
508
709
  return { stopReason };
509
710
  } catch (error) {
510
- console.error(`[ACP-over-MAP] Prompt error:`, error);
711
+ // Extract a meaningful error message — errors from the ACP SDK may be
712
+ // plain objects ({code, message}) rather than Error instances.
713
+ let errorMessage: string;
714
+ if (error instanceof Error) {
715
+ errorMessage = error.message;
716
+ } else if (
717
+ typeof error === "object" &&
718
+ error !== null &&
719
+ "message" in error &&
720
+ typeof (error as { message: unknown }).message === "string"
721
+ ) {
722
+ errorMessage = (error as { message: string }).message;
723
+ } else {
724
+ try {
725
+ errorMessage = JSON.stringify(error);
726
+ } catch {
727
+ errorMessage = String(error);
728
+ }
729
+ }
730
+ console.error(
731
+ `[ACP-over-MAP] Prompt error for agent ${agentId}:`,
732
+ errorMessage,
733
+ );
511
734
  return {
512
735
  stopReason: "end_turn",
513
- error: error instanceof Error ? error.message : String(error),
736
+ error: errorMessage,
514
737
  };
515
738
  } finally {
516
739
  this.sessionMapper.setProcessing(sessionId as ACPSessionId, false);
@@ -522,9 +745,11 @@ export class ACPOverMAPHandler {
522
745
  params: unknown,
523
746
  sessionIdFromContext?: string,
524
747
  ): Promise<unknown> {
525
- const { sessionId: paramSessionId } = (params as { sessionId?: string }) ?? {};
748
+ const { sessionId: paramSessionId } =
749
+ (params as { sessionId?: string }) ?? {};
526
750
  // Prefer server's resolved session ID over client's potentially stale one
527
- const sessionId = streamState.sessionId ?? paramSessionId ?? sessionIdFromContext;
751
+ const sessionId =
752
+ streamState.sessionId ?? paramSessionId ?? sessionIdFromContext;
528
753
 
529
754
  const agentId = sessionId
530
755
  ? this.sessionMapper.getAgentId(sessionId as ACPSessionId)
@@ -546,9 +771,14 @@ export class ACPOverMAPHandler {
546
771
  if (session) {
547
772
  try {
548
773
  await session.cancel();
549
- console.error(`[ACP-over-MAP] Session cancelled for agent ${agentId}`);
774
+ console.error(
775
+ `[ACP-over-MAP] Session cancelled for agent ${agentId}`,
776
+ );
550
777
  } catch (error) {
551
- console.warn(`[ACP-over-MAP] session.cancel() failed for ${agentId}:`, error);
778
+ console.warn(
779
+ `[ACP-over-MAP] session.cancel() failed for ${agentId}:`,
780
+ error,
781
+ );
552
782
  }
553
783
  }
554
784
  }
@@ -565,7 +795,7 @@ export class ACPOverMAPHandler {
565
795
  method: string,
566
796
  params: unknown,
567
797
  ): Promise<unknown> {
568
- const methodParams = params as Record<string, unknown> ?? {};
798
+ const methodParams = (params as Record<string, unknown>) ?? {};
569
799
 
570
800
  switch (method) {
571
801
  case "_macro/spawnAgent": {
@@ -573,7 +803,7 @@ export class ACPOverMAPHandler {
573
803
  task: string;
574
804
  cwd?: string;
575
805
  topics?: string[];
576
- config?: Record<string, unknown>;
806
+ config?: AgentConfig;
577
807
  parentId?: string;
578
808
  };
579
809
 
@@ -597,8 +827,13 @@ export class ACPOverMAPHandler {
597
827
  task,
598
828
  cwd: cwd ?? this.defaultCwd,
599
829
  role: "worker",
830
+ topics,
831
+ config,
600
832
  });
601
833
 
834
+ // Notify subscribers that a new agent was registered
835
+ this.notifyAgentRegistered(spawned.id);
836
+
602
837
  return {
603
838
  agentId: spawned.id,
604
839
  sessionId: spawned.session_id,
@@ -635,10 +870,19 @@ export class ACPOverMAPHandler {
635
870
  throw new Error(`Agent not found: ${agentId}`);
636
871
  }
637
872
 
873
+ // If the agent is already running, return its current state
874
+ // instead of throwing. The caller likely just wants to ensure
875
+ // the agent is active, which it already is.
638
876
  if (agent.state !== "stopped" && agent.state !== "failed") {
639
- throw new Error(
640
- `Agent ${agentId} is ${agent.state} only stopped or failed agents can be resumed`
877
+ console.error(
878
+ `[ACP-over-MAP] _macro/resume: Agent ${agentId} is already ${agent.state}, returning current state`,
641
879
  );
880
+ return {
881
+ success: true,
882
+ agentId: agent.id,
883
+ sessionId: agent.session_id,
884
+ alreadyRunning: true,
885
+ };
642
886
  }
643
887
 
644
888
  const spawned = await this.agentManager.resume(agentId as AgentId);
@@ -650,7 +894,11 @@ export class ACPOverMAPHandler {
650
894
  }
651
895
 
652
896
  case "_macro/getHistory": {
653
- const { sessionId, agentId: historyAgentId, limit } = methodParams as {
897
+ const {
898
+ sessionId,
899
+ agentId: historyAgentId,
900
+ limit,
901
+ } = methodParams as {
654
902
  sessionId?: string;
655
903
  agentId?: string;
656
904
  limit?: number;
@@ -661,12 +909,12 @@ export class ACPOverMAPHandler {
661
909
  // explicit sessionId. This allows history to survive across server
662
910
  // restarts even when the ACP session ID changes (e.g., resume()
663
911
  // fails → TUI creates new session with different ID).
912
+ const agent = historyAgentId
913
+ ? this.eventStore.getAgent(historyAgentId as AgentId)
914
+ : undefined;
664
915
  let conversationId: string | undefined;
665
- if (historyAgentId) {
666
- const agent = this.eventStore.getAgent(historyAgentId as AgentId);
667
- if (agent) {
668
- conversationId = agent.session_id;
669
- }
916
+ if (agent) {
917
+ conversationId = agent.session_id;
670
918
  }
671
919
  if (!conversationId) {
672
920
  conversationId = sessionId;
@@ -675,14 +923,41 @@ export class ACPOverMAPHandler {
675
923
  return { turns: [] };
676
924
  }
677
925
 
678
- const turns = this.eventStore.listTurns({
679
- conversationId,
680
- order: "asc",
681
- limit: limit ?? 200,
682
- });
926
+ // For forked agents, include the source agent's conversation history
927
+ // (pre-fork turns) followed by this agent's own turns.
928
+ // Only include source turns from before the fork to avoid leaking
929
+ // turns that the source recorded after the fork point.
930
+ const sourceAgentId = agent?.metadata?.fork_of as string | undefined;
931
+ let turns;
932
+ if (sourceAgentId) {
933
+ const sourceAgent = this.eventStore.getAgent(
934
+ sourceAgentId as AgentId,
935
+ );
936
+ const sourceConversationId = sourceAgent?.session_id;
937
+ const forkTimestamp = agent!.created_at;
938
+ const sourceTurns = sourceConversationId
939
+ ? this.eventStore
940
+ .listTurns({
941
+ conversationId: sourceConversationId,
942
+ order: "asc",
943
+ limit: limit ?? 200,
944
+ })
945
+ .filter((t) => t.timestamp <= forkTimestamp)
946
+ : [];
947
+ const ownTurns = this.eventStore.listTurns({
948
+ conversationId,
949
+ order: "asc",
950
+ limit: limit ?? 200,
951
+ });
952
+ turns = [...sourceTurns, ...ownTurns];
953
+ } else {
954
+ turns = this.eventStore.listTurns({
955
+ conversationId,
956
+ order: "asc",
957
+ limit: limit ?? 200,
958
+ });
959
+ }
683
960
 
684
- // Include persisted plan and agent cwd if available
685
- const agent = historyAgentId ? this.eventStore.getAgent(historyAgentId as AgentId) : undefined;
686
961
  const plan = agent?.plan ?? [];
687
962
 
688
963
  return {
@@ -699,6 +974,338 @@ export class ACPOverMAPHandler {
699
974
  };
700
975
  }
701
976
 
977
+ case "_macro/respondToPermission": {
978
+ const {
979
+ agentId: targetAgentId,
980
+ requestId,
981
+ optionId,
982
+ } = methodParams as {
983
+ agentId: string;
984
+ requestId: string;
985
+ optionId: string;
986
+ };
987
+ if (!targetAgentId || !requestId || !optionId) {
988
+ throw new Error("agentId, requestId, and optionId are required");
989
+ }
990
+ const success = this.agentManager.respondToPermission(
991
+ targetAgentId as AgentId,
992
+ requestId,
993
+ optionId,
994
+ );
995
+ return { success };
996
+ }
997
+
998
+ case "_macro/cancelPermission": {
999
+ const { agentId: targetAgentId, requestId } = methodParams as {
1000
+ agentId: string;
1001
+ requestId: string;
1002
+ };
1003
+ if (!targetAgentId || !requestId) {
1004
+ throw new Error("agentId and requestId are required");
1005
+ }
1006
+ const success = this.agentManager.cancelPermission(
1007
+ targetAgentId as AgentId,
1008
+ requestId,
1009
+ );
1010
+ return { success };
1011
+ }
1012
+
1013
+ case "_macro/setPermissionMode": {
1014
+ const { agentId: targetAgentId, permissionMode } = methodParams as {
1015
+ agentId: string;
1016
+ permissionMode: string;
1017
+ };
1018
+ if (!targetAgentId || !permissionMode) {
1019
+ throw new Error("agentId and permissionMode are required");
1020
+ }
1021
+ const previousMode = this.agentManager.getPermissionMode(
1022
+ targetAgentId as AgentId,
1023
+ );
1024
+ const success = this.agentManager.setPermissionMode(
1025
+ targetAgentId as AgentId,
1026
+ permissionMode as
1027
+ | "auto-approve"
1028
+ | "auto-deny"
1029
+ | "callback"
1030
+ | "interactive",
1031
+ );
1032
+ if (success) {
1033
+ return { success: true, previousMode: previousMode ?? undefined };
1034
+ }
1035
+ return {
1036
+ success: false,
1037
+ error: `No active session found for agent ${targetAgentId}`,
1038
+ };
1039
+ }
1040
+
1041
+ case "_macro/forkAgent": {
1042
+ const { agentId, name, prompt, cwd } = methodParams as {
1043
+ agentId: string;
1044
+ name?: string;
1045
+ prompt?: string;
1046
+ cwd?: string;
1047
+ };
1048
+ if (!agentId) {
1049
+ throw new Error("agentId is required");
1050
+ }
1051
+
1052
+ const sourceAgent = this.eventStore.getAgent(agentId as AgentId);
1053
+ if (!sourceAgent) {
1054
+ throw new Error(`Agent not found: ${agentId}`);
1055
+ }
1056
+
1057
+ const forked = await this.agentManager.forkAgent(agentId as AgentId, {
1058
+ name,
1059
+ prompt,
1060
+ cwd: cwd ?? sourceAgent.cwd ?? this.defaultCwd,
1061
+ });
1062
+
1063
+ // Fire-and-forget initial prompt if provided
1064
+ if (prompt) {
1065
+ (async () => {
1066
+ try {
1067
+ for await (const _update of this.agentManager.prompt(
1068
+ forked.id,
1069
+ prompt,
1070
+ )) {
1071
+ // drain iterator
1072
+ }
1073
+ } catch {
1074
+ // best-effort
1075
+ }
1076
+ })();
1077
+ }
1078
+
1079
+ return {
1080
+ newAgentId: forked.id,
1081
+ newSessionId: forked.session_id,
1082
+ originalAgentId: agentId,
1083
+ providerSessionId: forked.session?.id,
1084
+ };
1085
+ }
1086
+
1087
+ case "_macro/agents/update": {
1088
+ const { agentId, name, plan, metadata } = methodParams as {
1089
+ agentId?: string;
1090
+ name?: string;
1091
+ plan?: Array<{ content: string; priority: string; status: string }>;
1092
+ metadata?: Record<string, unknown>;
1093
+ };
1094
+ if (!agentId) {
1095
+ throw new Error("agentId is required");
1096
+ }
1097
+ if (
1098
+ name === undefined &&
1099
+ plan === undefined &&
1100
+ metadata === undefined
1101
+ ) {
1102
+ throw new Error(
1103
+ "At least one field to update is required (name, plan, or metadata)",
1104
+ );
1105
+ }
1106
+ if (name !== undefined && !name.trim()) {
1107
+ throw new Error("name must not be empty");
1108
+ }
1109
+
1110
+ const agent = this.eventStore.getAgent(agentId as AgentId);
1111
+ if (!agent) {
1112
+ throw new Error(`Agent not found: ${agentId}`);
1113
+ }
1114
+
1115
+ const updates: Record<string, unknown> = {};
1116
+ const updatedFields: string[] = [];
1117
+
1118
+ if (name !== undefined) {
1119
+ updates.name = name.trim();
1120
+ updatedFields.push("name");
1121
+ }
1122
+ if (plan !== undefined) {
1123
+ updates.plan = plan;
1124
+ updatedFields.push("plan");
1125
+ }
1126
+ if (metadata !== undefined) {
1127
+ updates.metadata = metadata;
1128
+ updatedFields.push("metadata");
1129
+ }
1130
+
1131
+ this.eventStore.updateAgentMetadata(agentId as AgentId, updates);
1132
+
1133
+ return {
1134
+ success: true,
1135
+ agentId,
1136
+ updated: updatedFields,
1137
+ };
1138
+ }
1139
+
1140
+ case "_macro/getModels": {
1141
+ const { sessionId } = methodParams as { sessionId: string };
1142
+ const agentId = this.sessionMapper.getAgentId(
1143
+ sessionId as ACPSessionId,
1144
+ );
1145
+ if (!agentId) {
1146
+ return { currentModelId: null, availableModels: [] };
1147
+ }
1148
+ const session = this.agentManager.getSession(agentId);
1149
+ if (!session) {
1150
+ return { currentModelId: null, availableModels: [] };
1151
+ }
1152
+ // Try clientHandler's model info store first (from _model_state_update notification)
1153
+ const clientHandler = (
1154
+ session as unknown as {
1155
+ clientHandler?: {
1156
+ getSessionModelInfo?: (id: string) => {
1157
+ currentModelId: string | null;
1158
+ availableModels: Array<{ modelId: string; name: string }>;
1159
+ } | null;
1160
+ };
1161
+ }
1162
+ ).clientHandler;
1163
+ const modelInfo = clientHandler?.getSessionModelInfo?.(session.id);
1164
+ if (modelInfo && modelInfo.availableModels.length > 0) {
1165
+ return modelInfo;
1166
+ }
1167
+ // Fall back to Session.models (from initial session response — just IDs)
1168
+ if (session.models && session.models.length > 0) {
1169
+ return {
1170
+ currentModelId: session.models[0],
1171
+ availableModels: session.models.map((id: string) => ({
1172
+ modelId: id,
1173
+ name: id,
1174
+ })),
1175
+ };
1176
+ }
1177
+ return { currentModelId: null, availableModels: [] };
1178
+ }
1179
+
1180
+ case "_session/setCompaction": {
1181
+ // Compaction is handled internally by the agent process.
1182
+ // Accept the request as a no-op so the client doesn't get an error.
1183
+ // TODO: Make sure this overrides if needed.
1184
+ return { success: true };
1185
+ }
1186
+
1187
+ // ── Task Management Extensions ────────────────────────────────
1188
+ // These mirror the registered adapter extensions (_macro/task/*)
1189
+ // so they're accessible via ACP-over-MAP streams.
1190
+
1191
+ case "_macro/task/list": {
1192
+ const { filter } = (methodParams ?? {}) as {
1193
+ filter?: {
1194
+ status?: string;
1195
+ assignedAgent?: string;
1196
+ parentTask?: string;
1197
+ createdBy?: string;
1198
+ rootTasksOnly?: boolean;
1199
+ };
1200
+ };
1201
+
1202
+ const taskFilter: TaskFilter | undefined = filter
1203
+ ? {
1204
+ status: filter.status as TaskFilter["status"],
1205
+ assigned_agent: filter.assignedAgent as AgentId | undefined,
1206
+ parent_task: filter.parentTask as TaskId | undefined,
1207
+ created_by: filter.createdBy as AgentId | undefined,
1208
+ rootTasksOnly: filter.rootTasksOnly,
1209
+ }
1210
+ : undefined;
1211
+
1212
+ const tasks = this.taskManager.list(taskFilter);
1213
+ return {
1214
+ tasks: tasks.map((t) => ({
1215
+ id: t.id,
1216
+ description: t.description,
1217
+ status: t.status,
1218
+ assignedAgent: t.assigned_agent,
1219
+ createdBy: t.created_by,
1220
+ createdAt: t.created_at,
1221
+ parentTask: t.parent_task,
1222
+ isBlocked: (t as any).isBlocked,
1223
+ externalId: (t as any).external_id,
1224
+ })),
1225
+ };
1226
+ }
1227
+
1228
+ case "_macro/task/get": {
1229
+ const { taskId } = methodParams as { taskId: string };
1230
+ if (!taskId) throw new Error("taskId is required");
1231
+ const task = this.taskManager.get(taskId as TaskId);
1232
+ if (!task) throw new Error(`Task not found: ${taskId}`);
1233
+ return {
1234
+ task: {
1235
+ id: task.id,
1236
+ description: task.description,
1237
+ status: task.status,
1238
+ assignedAgent: task.assigned_agent,
1239
+ createdBy: task.created_by,
1240
+ createdAt: task.created_at,
1241
+ parentTask: task.parent_task,
1242
+ isBlocked: (task as any).isBlocked,
1243
+ externalId: (task as any).external_id,
1244
+ },
1245
+ };
1246
+ }
1247
+
1248
+ case "_macro/task/create": {
1249
+ const { description, parentTask, externalId } = methodParams as {
1250
+ description: string;
1251
+ parentTask?: string;
1252
+ externalId?: string;
1253
+ };
1254
+ if (!description) throw new Error("description is required");
1255
+
1256
+ // Determine who is creating the task — use the stream's agent or a default
1257
+ const createdBy = (streamState.agentId ?? "tui") as AgentId;
1258
+
1259
+ const task = this.taskManager.create({
1260
+ description,
1261
+ created_by: createdBy,
1262
+ parent_task: parentTask as TaskId | undefined,
1263
+ });
1264
+
1265
+ return {
1266
+ task: {
1267
+ id: task.id,
1268
+ description: task.description,
1269
+ status: task.status,
1270
+ assignedAgent: task.assigned_agent,
1271
+ createdBy: task.created_by,
1272
+ createdAt: task.created_at,
1273
+ parentTask: task.parent_task,
1274
+ },
1275
+ };
1276
+ }
1277
+
1278
+ case "_macro/task/assign": {
1279
+ const { taskId, agentId, role } = methodParams as {
1280
+ taskId: string;
1281
+ agentId: string;
1282
+ role?: string;
1283
+ };
1284
+ if (!taskId) throw new Error("taskId is required");
1285
+ if (!agentId) throw new Error("agentId is required");
1286
+
1287
+ this.taskManager.assign(taskId as TaskId, agentId as AgentId, role);
1288
+ return { success: true };
1289
+ }
1290
+
1291
+ case "_macro/task/complete": {
1292
+ const { taskId, outputs } = methodParams as {
1293
+ taskId: string;
1294
+ outputs?: { summary?: string; data?: unknown };
1295
+ };
1296
+ if (!taskId) throw new Error("taskId is required");
1297
+
1298
+ // Update status to completed
1299
+ this.taskManager.updateStatus(taskId as TaskId, "completed");
1300
+
1301
+ // If outputs provided, update task metadata
1302
+ if (outputs) {
1303
+ this.taskManager.update(taskId as TaskId, { outputs });
1304
+ }
1305
+
1306
+ return { success: true };
1307
+ }
1308
+
702
1309
  default:
703
1310
  throw new Error(`Unknown extension method: ${method}`);
704
1311
  }
@@ -750,7 +1357,12 @@ export class ACPOverMAPHandler {
750
1357
  acpSessionId: ACPSessionId,
751
1358
  agentId: AgentId,
752
1359
  userMessage: string,
753
- buffer: { parts: Array<{ type: "text"; text: string } | ({ type: "tool" } & Record<string, unknown>)> },
1360
+ buffer: {
1361
+ parts: Array<
1362
+ | { type: "text"; text: string }
1363
+ | ({ type: "tool" } & Record<string, unknown>)
1364
+ >;
1365
+ },
754
1366
  ): void {
755
1367
  const now = Date.now();
756
1368