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
@@ -0,0 +1,711 @@
1
+ /**
2
+ * Multi-Client Event Broadcast E2E Test
3
+ *
4
+ * Spins up a REAL CombinedServer with in-memory EventStore, connects
5
+ * two WebSocket clients, and verifies that events emitted by one client's
6
+ * ACP activity are broadcast to the other client's subscription.
7
+ *
8
+ * This tests the full pipeline:
9
+ * Client B sends map/send (ACP envelope)
10
+ * → handleSend → handleACPOverMAP
11
+ * → emitEvent(message_sent)
12
+ * → processRequest → emitNotification → emitEvent(message_delivered)
13
+ * → emitEvent(message_delivered) [final response]
14
+ * → subscription match → sendToSession → WebSocket.send()
15
+ * → Client A receives map/event notification
16
+ */
17
+
18
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
19
+ import { WebSocket } from "ws";
20
+ import { createEventStore, type EventStore } from "../../../store/event-store.js";
21
+ import {
22
+ createAgentManager,
23
+ type AgentManager,
24
+ } from "../../../agent/agent-manager.js";
25
+ import { createTaskManager, type TaskManager } from "../../../task/task-manager.js";
26
+ import {
27
+ createMessageRouter,
28
+ type MessageRouter,
29
+ } from "../../../router/message-router.js";
30
+ import {
31
+ createCombinedServer,
32
+ type CombinedServer,
33
+ type CombinedServerServices,
34
+ } from "../../../server/combined-server.js";
35
+
36
+ // =============================================================================
37
+ // Helpers
38
+ // =============================================================================
39
+
40
+ function getPortFromUrl(url: string): number {
41
+ return parseInt(new URL(url).port, 10);
42
+ }
43
+
44
+ interface JsonRpcMessage {
45
+ jsonrpc: "2.0";
46
+ id?: number;
47
+ method?: string;
48
+ params?: unknown;
49
+ result?: unknown;
50
+ error?: { code: number; message: string; data?: unknown };
51
+ }
52
+
53
+ /**
54
+ * WebSocket MAP client that handles both RPC responses AND notifications.
55
+ */
56
+ class MAPTestClient {
57
+ private ws!: WebSocket;
58
+ private waiters: Map<
59
+ number,
60
+ { resolve: (r: JsonRpcMessage) => void; reject: (e: Error) => void }
61
+ > = new Map();
62
+ private nextId = 1;
63
+ private url: string;
64
+
65
+ /** All received notifications (no `id` field) */
66
+ readonly notifications: JsonRpcMessage[] = [];
67
+
68
+ /** Resolvers waiting for a notification matching some predicate */
69
+ private notificationWaiters: Array<{
70
+ check: (msg: JsonRpcMessage) => boolean;
71
+ resolve: (msg: JsonRpcMessage) => void;
72
+ reject: (e: Error) => void;
73
+ timeout: ReturnType<typeof setTimeout>;
74
+ }> = [];
75
+
76
+ constructor(url: string) {
77
+ this.url = url;
78
+ }
79
+
80
+ async connect(): Promise<void> {
81
+ this.ws = new WebSocket(this.url);
82
+ return new Promise((resolve, reject) => {
83
+ const timeout = setTimeout(
84
+ () => reject(new Error("Connection timeout")),
85
+ 5000,
86
+ );
87
+ this.ws.on("open", () => {
88
+ clearTimeout(timeout);
89
+ resolve();
90
+ });
91
+ this.ws.on("error", (err) => {
92
+ clearTimeout(timeout);
93
+ reject(err);
94
+ });
95
+ this.ws.on("message", (data: Buffer) => {
96
+ try {
97
+ const msg = JSON.parse(data.toString()) as JsonRpcMessage;
98
+
99
+ if (msg.id != null) {
100
+ // RPC response
101
+ const waiter = this.waiters.get(msg.id);
102
+ if (waiter) {
103
+ this.waiters.delete(msg.id);
104
+ waiter.resolve(msg);
105
+ }
106
+ } else if (msg.method) {
107
+ // Notification (no id)
108
+ this.notifications.push(msg);
109
+
110
+ // Check pending notification waiters
111
+ for (let i = this.notificationWaiters.length - 1; i >= 0; i--) {
112
+ const w = this.notificationWaiters[i];
113
+ if (w.check(msg)) {
114
+ clearTimeout(w.timeout);
115
+ this.notificationWaiters.splice(i, 1);
116
+ w.resolve(msg);
117
+ }
118
+ }
119
+ }
120
+ } catch {
121
+ // ignore parse errors
122
+ }
123
+ });
124
+ });
125
+ }
126
+
127
+ async request(method: string, params?: unknown): Promise<JsonRpcMessage> {
128
+ const id = this.nextId++;
129
+ return new Promise((resolve, reject) => {
130
+ const timeout = setTimeout(() => {
131
+ this.waiters.delete(id);
132
+ reject(new Error(`Request timeout: ${method}`));
133
+ }, 30000);
134
+ this.waiters.set(id, {
135
+ resolve: (r) => {
136
+ clearTimeout(timeout);
137
+ resolve(r);
138
+ },
139
+ reject: (e) => {
140
+ clearTimeout(timeout);
141
+ reject(e);
142
+ },
143
+ });
144
+ this.ws.send(JSON.stringify({ jsonrpc: "2.0", method, params, id }));
145
+ });
146
+ }
147
+
148
+ /**
149
+ * Wait for a notification matching the predicate.
150
+ * Checks already-received notifications first.
151
+ */
152
+ waitForNotification(
153
+ check: (msg: JsonRpcMessage) => boolean,
154
+ timeoutMs = 15000,
155
+ ): Promise<JsonRpcMessage> {
156
+ const existing = this.notifications.find(check);
157
+ if (existing) return Promise.resolve(existing);
158
+
159
+ return new Promise((resolve, reject) => {
160
+ const timeout = setTimeout(() => {
161
+ const idx = this.notificationWaiters.findIndex(
162
+ (w) => w.resolve === resolve,
163
+ );
164
+ if (idx >= 0) this.notificationWaiters.splice(idx, 1);
165
+ reject(
166
+ new Error(
167
+ `Timeout waiting for notification. Received ${this.notifications.length} notifications:\n` +
168
+ this.notifications
169
+ .map((n) => {
170
+ const p = n.params as Record<string, unknown> | undefined;
171
+ const evt = p?.event as Record<string, unknown> | undefined;
172
+ return ` ${n.method} → type=${evt?.type}`;
173
+ })
174
+ .join("\n"),
175
+ ),
176
+ );
177
+ }, timeoutMs);
178
+ this.notificationWaiters.push({ check, resolve, reject, timeout });
179
+ });
180
+ }
181
+
182
+ close(): void {
183
+ // Clean up pending waiters
184
+ for (const w of this.notificationWaiters) {
185
+ clearTimeout(w.timeout);
186
+ }
187
+ this.notificationWaiters.length = 0;
188
+
189
+ try {
190
+ this.ws?.close();
191
+ } catch {
192
+ // ignore
193
+ }
194
+ }
195
+ }
196
+
197
+ // =============================================================================
198
+ // Tests
199
+ // =============================================================================
200
+
201
+ describe("Multi-client event broadcast E2E", () => {
202
+ let eventStore: EventStore;
203
+ let agentManager: AgentManager;
204
+ let taskManager: TaskManager;
205
+ let messageRouter: MessageRouter;
206
+ let server: CombinedServer;
207
+ let port: number;
208
+ const clients: MAPTestClient[] = [];
209
+
210
+ beforeEach(async () => {
211
+ eventStore = await createEventStore({ inMemory: true });
212
+ messageRouter = createMessageRouter(eventStore);
213
+ taskManager = createTaskManager(eventStore);
214
+ agentManager = createAgentManager(eventStore, messageRouter, {
215
+ defaultPermissionMode: "auto-approve",
216
+ defaultCwd: process.cwd(),
217
+ });
218
+
219
+ const services: CombinedServerServices = {
220
+ eventStore,
221
+ agentManager,
222
+ taskManager,
223
+ messageRouter,
224
+ };
225
+
226
+ server = createCombinedServer(services, { port: 0, host: "localhost" });
227
+ await server.start();
228
+ port = getPortFromUrl(server.getUrl());
229
+ });
230
+
231
+ afterEach(async () => {
232
+ for (const c of clients) {
233
+ c.close();
234
+ }
235
+ clients.length = 0;
236
+ await server.stop().catch(() => {});
237
+ await agentManager.close();
238
+ await eventStore.close();
239
+ });
240
+
241
+ function createClient(): MAPTestClient {
242
+ const client = new MAPTestClient(`ws://localhost:${port}/map?token=${server.serverToken}`);
243
+ clients.push(client);
244
+ return client;
245
+ }
246
+
247
+ // Helper to check if a notification is a map/event with a specific type
248
+ function isEventOfType(type: string) {
249
+ return (msg: JsonRpcMessage) => {
250
+ if (msg.method !== "map/event") return false;
251
+ const params = msg.params as Record<string, unknown> | undefined;
252
+ const event = params?.event as Record<string, unknown> | undefined;
253
+ return event?.type === type;
254
+ };
255
+ }
256
+
257
+ /** Send ACP initialize + session/new via map/send, return the response. */
258
+ async function initializeAndCreateSession(
259
+ client: MAPTestClient,
260
+ streamId: string,
261
+ ): Promise<JsonRpcMessage> {
262
+ // ACP requires initialize before session/new
263
+ await client.request("map/send", {
264
+ to: { agent: "default" },
265
+ payload: {
266
+ acp: {
267
+ jsonrpc: "2.0",
268
+ id: 1,
269
+ method: "initialize",
270
+ params: {
271
+ clientInfo: { name: "test-client", version: "0.1.0" },
272
+ },
273
+ },
274
+ acpContext: { streamId, direction: "client-to-agent" },
275
+ },
276
+ });
277
+
278
+ return client.request("map/send", {
279
+ to: { agent: "default" },
280
+ payload: {
281
+ acp: {
282
+ jsonrpc: "2.0",
283
+ id: 2,
284
+ method: "session/new",
285
+ params: {},
286
+ },
287
+ acpContext: { streamId, direction: "client-to-agent" },
288
+ },
289
+ });
290
+ }
291
+
292
+ it("Client A receives agent_registered when Client B creates a session", { timeout: 30_000 }, async () => {
293
+ // Connect Client A and subscribe
294
+ const clientA = createClient();
295
+ await clientA.connect();
296
+ const subRes = await clientA.request("map/subscribe", {
297
+ filter: {
298
+ eventTypes: [
299
+ "agent_registered",
300
+ "message_sent",
301
+ "message_delivered",
302
+ "agent_state_changed",
303
+ ],
304
+ },
305
+ });
306
+ expect(subRes.error).toBeUndefined();
307
+ expect(subRes.result).toHaveProperty("subscriptionId");
308
+
309
+ // Connect Client B
310
+ const clientB = createClient();
311
+ await clientB.connect();
312
+
313
+ // Client B initializes ACP stream and creates a session
314
+ const streamId = `stream-${Date.now()}`;
315
+ const sessionNewRes = await initializeAndCreateSession(clientB, streamId);
316
+ console.log("session/new response:", JSON.stringify(sessionNewRes, null, 2));
317
+
318
+ // Client A should receive agent_registered notification
319
+ const agentEvent = await clientA.waitForNotification(
320
+ isEventOfType("agent_registered"),
321
+ 10000,
322
+ );
323
+
324
+ expect(agentEvent.method).toBe("map/event");
325
+ const params = agentEvent.params as Record<string, unknown>;
326
+ const event = params.event as Record<string, unknown>;
327
+ expect(event.type).toBe("agent_registered");
328
+
329
+ const data = event.data as Record<string, unknown>;
330
+ expect(data.agentId).toBeDefined();
331
+ console.log("Agent registered event data:", JSON.stringify(data, null, 2));
332
+ });
333
+
334
+ it("Client A receives message_sent when Client B sends ACP request", { timeout: 30_000 }, async () => {
335
+ // Connect and subscribe Client A
336
+ const clientA = createClient();
337
+ await clientA.connect();
338
+ await clientA.request("map/subscribe", {
339
+ filter: {
340
+ eventTypes: [
341
+ "agent_registered",
342
+ "message_sent",
343
+ "message_delivered",
344
+ ],
345
+ },
346
+ });
347
+
348
+ // Connect Client B and create a session first
349
+ const clientB = createClient();
350
+ await clientB.connect();
351
+
352
+ const streamId = `stream-${Date.now()}`;
353
+
354
+ // Initialize ACP stream
355
+ await clientB.request("map/send", {
356
+ to: { agent: "default" },
357
+ payload: {
358
+ acp: {
359
+ jsonrpc: "2.0",
360
+ id: 1,
361
+ method: "initialize",
362
+ params: {
363
+ clientInfo: { name: "test-client-b", version: "0.1.0" },
364
+ },
365
+ },
366
+ acpContext: {
367
+ streamId,
368
+ direction: "client-to-agent",
369
+ },
370
+ },
371
+ });
372
+
373
+ // Create new session (this also triggers agent_registered)
374
+ const sessionNewRes = await clientB.request("map/send", {
375
+ to: { agent: "default" },
376
+ payload: {
377
+ acp: {
378
+ jsonrpc: "2.0",
379
+ id: 2,
380
+ method: "session/new",
381
+ params: {},
382
+ },
383
+ acpContext: {
384
+ streamId,
385
+ direction: "client-to-agent",
386
+ },
387
+ },
388
+ });
389
+
390
+ console.log("session/new response:", JSON.stringify(sessionNewRes, null, 2));
391
+
392
+ // Wait for agent_registered first (confirms agent was created)
393
+ const agentEvent = await clientA.waitForNotification(
394
+ isEventOfType("agent_registered"),
395
+ 10000,
396
+ );
397
+ const agentData = (
398
+ (agentEvent.params as Record<string, unknown>).event as Record<
399
+ string,
400
+ unknown
401
+ >
402
+ ).data as Record<string, unknown>;
403
+ const agentId = agentData.agentId as string;
404
+ console.log("Created agent:", agentId);
405
+
406
+ // Client A should have received message_sent events for the ACP requests
407
+ // (initialize and session/new both emit message_sent)
408
+ const messageSentEvents = clientA.notifications.filter(
409
+ isEventOfType("message_sent"),
410
+ );
411
+ console.log(
412
+ `Client A received ${messageSentEvents.length} message_sent events`,
413
+ );
414
+ expect(messageSentEvents.length).toBeGreaterThanOrEqual(1);
415
+
416
+ // Verify the message_sent event has the ACP envelope in the data
417
+ const sentParams = messageSentEvents[0].params as Record<string, unknown>;
418
+ const sentEvent = sentParams.event as Record<string, unknown>;
419
+ const sentData = sentEvent.data as Record<string, unknown>;
420
+ expect(sentData.from).toBeDefined();
421
+ expect(sentData.to).toBeDefined();
422
+ expect(sentData.message).toBeDefined();
423
+
424
+ const message = sentData.message as Record<string, unknown>;
425
+ expect(message.payload).toBeDefined();
426
+
427
+ // The payload should be a valid ACP envelope
428
+ const payload = message.payload as Record<string, unknown>;
429
+ expect(payload.acp).toBeDefined();
430
+ expect(payload.acpContext).toBeDefined();
431
+
432
+ console.log("message_sent event data:", JSON.stringify(sentData, null, 2));
433
+ });
434
+
435
+ it("Client A receives message_delivered for ACP streaming updates", { timeout: 30_000 }, async () => {
436
+ // Connect and subscribe Client A
437
+ const clientA = createClient();
438
+ await clientA.connect();
439
+ await clientA.request("map/subscribe", {
440
+ filter: {
441
+ eventTypes: [
442
+ "agent_registered",
443
+ "message_sent",
444
+ "message_delivered",
445
+ ],
446
+ },
447
+ });
448
+
449
+ // Connect Client B
450
+ const clientB = createClient();
451
+ await clientB.connect();
452
+
453
+ const streamId = `stream-${Date.now()}`;
454
+
455
+ // Initialize
456
+ await clientB.request("map/send", {
457
+ to: { agent: "default" },
458
+ payload: {
459
+ acp: {
460
+ jsonrpc: "2.0",
461
+ id: 1,
462
+ method: "initialize",
463
+ params: {
464
+ clientInfo: { name: "test-client-b", version: "0.1.0" },
465
+ },
466
+ },
467
+ acpContext: {
468
+ streamId,
469
+ direction: "client-to-agent",
470
+ },
471
+ },
472
+ });
473
+
474
+ // Create session
475
+ const sessionRes = await clientB.request("map/send", {
476
+ to: { agent: "default" },
477
+ payload: {
478
+ acp: {
479
+ jsonrpc: "2.0",
480
+ id: 2,
481
+ method: "session/new",
482
+ params: {},
483
+ },
484
+ acpContext: {
485
+ streamId,
486
+ direction: "client-to-agent",
487
+ },
488
+ },
489
+ });
490
+
491
+ console.log("session/new response:", JSON.stringify(sessionRes, null, 2));
492
+
493
+ // Wait for agent_registered first
494
+ const agentEvent = await clientA.waitForNotification(
495
+ isEventOfType("agent_registered"),
496
+ 10000,
497
+ );
498
+ const agentData = (
499
+ (agentEvent.params as Record<string, unknown>).event as Record<
500
+ string,
501
+ unknown
502
+ >
503
+ ).data as Record<string, unknown>;
504
+ const agentId = agentData.agentId as string;
505
+
506
+ // Extract session ID from the session/new response
507
+ const sessionResult =
508
+ sessionRes.result as Record<string, unknown> | undefined;
509
+ let sessionId: string | undefined;
510
+ if (sessionResult?.delivered) {
511
+ // The response comes from sendMessage — extract sessionId from
512
+ // message_delivered events that should be in Client A's notifications
513
+ }
514
+
515
+ // Check message_delivered events — session/new should emit session info
516
+ // Wait a moment for streaming updates
517
+ await new Promise((r) => setTimeout(r, 1000));
518
+
519
+ const deliveredEvents = clientA.notifications.filter(
520
+ isEventOfType("message_delivered"),
521
+ );
522
+ console.log(
523
+ `Client A received ${deliveredEvents.length} message_delivered events`,
524
+ );
525
+
526
+ // There should be at least one message_delivered event
527
+ // (session info notification emitted during session/new processing)
528
+ expect(deliveredEvents.length).toBeGreaterThanOrEqual(1);
529
+
530
+ // Verify the delivered event has the proper structure
531
+ for (const evt of deliveredEvents) {
532
+ const p = evt.params as Record<string, unknown>;
533
+ const e = p.event as Record<string, unknown>;
534
+ const d = e.data as Record<string, unknown>;
535
+ expect(d.from).toBeDefined();
536
+ expect(d.to).toBeDefined();
537
+ expect(d.message).toBeDefined();
538
+
539
+ const msg = d.message as Record<string, unknown>;
540
+ expect(msg.payload).toBeDefined();
541
+
542
+ const payload = msg.payload as Record<string, unknown>;
543
+ expect(payload.acp).toBeDefined();
544
+ expect(payload.acpContext).toBeDefined();
545
+
546
+ console.log(
547
+ ` message_delivered: method=${(payload.acp as Record<string, unknown>).method ?? "(response)"}`,
548
+ );
549
+ }
550
+ });
551
+
552
+ it("Client A does NOT receive events for non-subscribed types", { timeout: 30_000 }, async () => {
553
+ // Client A subscribes only to agent_registered
554
+ const clientA = createClient();
555
+ await clientA.connect();
556
+ await clientA.request("map/subscribe", {
557
+ filter: { eventTypes: ["agent_registered"] },
558
+ });
559
+
560
+ // Client B sends ACP messages
561
+ const clientB = createClient();
562
+ await clientB.connect();
563
+
564
+ const streamId = `stream-${Date.now()}`;
565
+ await clientB.request("map/send", {
566
+ to: { agent: "default" },
567
+ payload: {
568
+ acp: {
569
+ jsonrpc: "2.0",
570
+ id: 1,
571
+ method: "initialize",
572
+ params: {
573
+ clientInfo: { name: "test-client-b", version: "0.1.0" },
574
+ },
575
+ },
576
+ acpContext: {
577
+ streamId,
578
+ direction: "client-to-agent",
579
+ },
580
+ },
581
+ });
582
+
583
+ await clientB.request("map/send", {
584
+ to: { agent: "default" },
585
+ payload: {
586
+ acp: {
587
+ jsonrpc: "2.0",
588
+ id: 2,
589
+ method: "session/new",
590
+ params: {},
591
+ },
592
+ acpContext: {
593
+ streamId,
594
+ direction: "client-to-agent",
595
+ },
596
+ },
597
+ });
598
+
599
+ // Wait for agent_registered (should arrive)
600
+ await clientA.waitForNotification(
601
+ isEventOfType("agent_registered"),
602
+ 10000,
603
+ );
604
+
605
+ // Give time for any other events to arrive
606
+ await new Promise((r) => setTimeout(r, 2000));
607
+
608
+ // Should NOT have received message_sent or message_delivered
609
+ const messageSent = clientA.notifications.filter(
610
+ isEventOfType("message_sent"),
611
+ );
612
+ const messageDelivered = clientA.notifications.filter(
613
+ isEventOfType("message_delivered"),
614
+ );
615
+
616
+ expect(messageSent).toHaveLength(0);
617
+ expect(messageDelivered).toHaveLength(0);
618
+ });
619
+
620
+ it("Both clients receive events when both are subscribed", { timeout: 30_000 }, async () => {
621
+ const clientA = createClient();
622
+ await clientA.connect();
623
+ await clientA.request("map/subscribe", {
624
+ filter: { eventTypes: ["agent_registered", "message_sent"] },
625
+ });
626
+
627
+ const clientB = createClient();
628
+ await clientB.connect();
629
+ await clientB.request("map/subscribe", {
630
+ filter: { eventTypes: ["agent_registered", "message_sent"] },
631
+ });
632
+
633
+ const streamId = `stream-${Date.now()}`;
634
+
635
+ // Client B initializes and creates session — both should see the events
636
+ await initializeAndCreateSession(clientB, streamId);
637
+
638
+ // Both should receive agent_registered
639
+ const eventA = await clientA.waitForNotification(
640
+ isEventOfType("agent_registered"),
641
+ 10000,
642
+ );
643
+ const eventB = await clientB.waitForNotification(
644
+ isEventOfType("agent_registered"),
645
+ 10000,
646
+ );
647
+
648
+ expect(eventA.method).toBe("map/event");
649
+ expect(eventB.method).toBe("map/event");
650
+
651
+ console.log(
652
+ `Client A notifications: ${clientA.notifications.length}`,
653
+ clientA.notifications.map((n) => {
654
+ const p = n.params as Record<string, unknown>;
655
+ const e = p?.event as Record<string, unknown>;
656
+ return e?.type;
657
+ }),
658
+ );
659
+ console.log(
660
+ `Client B notifications: ${clientB.notifications.length}`,
661
+ clientB.notifications.map((n) => {
662
+ const p = n.params as Record<string, unknown>;
663
+ const e = p?.event as Record<string, unknown>;
664
+ return e?.type;
665
+ }),
666
+ );
667
+ });
668
+
669
+ it("map/replay returns historical events", { timeout: 30_000 }, async () => {
670
+ // Client B creates an agent (generates events)
671
+ const clientB = createClient();
672
+ await clientB.connect();
673
+
674
+ const streamId = `stream-${Date.now()}`;
675
+ await initializeAndCreateSession(clientB, streamId);
676
+
677
+ // Wait for the request to be processed
678
+ await new Promise((r) => setTimeout(r, 2000));
679
+
680
+ // NOW Client A connects and replays history
681
+ const clientA = createClient();
682
+ await clientA.connect();
683
+
684
+ const replayRes = await clientA.request("map/replay", {
685
+ filter: {
686
+ eventTypes: [
687
+ "agent_registered",
688
+ "message_sent",
689
+ "message_delivered",
690
+ ],
691
+ },
692
+ limit: 100,
693
+ });
694
+
695
+ expect(replayRes.error).toBeUndefined();
696
+ const result = replayRes.result as {
697
+ events: Array<{ event: { type: string } }>;
698
+ hasMore: boolean;
699
+ };
700
+ expect(result.events).toBeDefined();
701
+ expect(result.events.length).toBeGreaterThan(0);
702
+
703
+ const eventTypes = result.events.map((e) => e.event.type);
704
+ console.log("Replayed event types:", eventTypes);
705
+
706
+ // Should include agent_registered from the session/new
707
+ expect(eventTypes).toContain("agent_registered");
708
+ // Should include message_sent (for the session/new ACP request)
709
+ expect(eventTypes).toContain("message_sent");
710
+ });
711
+ });