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
@@ -74,6 +74,9 @@ export interface SpawnAgentOptions {
74
74
  */
75
75
  role?: string;
76
76
 
77
+ /** Team instance ID this agent belongs to (set by TeamManager interceptor) */
78
+ team_instance?: string;
79
+
77
80
  /**
78
81
  * Stream ID to join (for workers and integrators).
79
82
  * Required for workers and integrators when using workspace isolation.
@@ -91,6 +94,12 @@ export interface SpawnAgentOptions {
91
94
  * If provided, the worker will claim this task and work on it.
92
95
  */
93
96
  dataplaneTaskId?: string;
97
+
98
+ /**
99
+ * Resolved capabilities for this agent's role.
100
+ * Injected by TeamRuntime spawn interceptor for capability-based workspace dispatch.
101
+ */
102
+ capabilities?: string[];
94
103
  }
95
104
 
96
105
  /**
@@ -380,4 +389,6 @@ export type AgentManagerErrorCode =
380
389
  | "NOT_RUNNING"
381
390
  | "INVALID_STATE"
382
391
  | "PERMISSION_DENIED"
383
- | "CAPABILITY_DENIED";
392
+ | "CAPABILITY_DENIED"
393
+ | "SHUTDOWN_IN_PROGRESS"
394
+ | "FORK_NOT_SUPPORTED";
@@ -9,6 +9,7 @@ import type { EventStore } from "../../store/event-store.js";
9
9
  import type { AgentManager } from "../../agent/agent-manager.js";
10
10
  import type { TaskManager } from "../../task/task-manager.js";
11
11
  import type { MessageRouter } from "../../router/message-router.js";
12
+ import type { TeamManager, TeamInstance } from "../../teams/team-manager.js";
12
13
  import type { Agent, Task, Event } from "../../store/types/index.js";
13
14
 
14
15
  // ─────────────────────────────────────────────────────────────────
@@ -154,6 +155,41 @@ function createMockMessageRouter(): MessageRouter {
154
155
  };
155
156
  }
156
157
 
158
+ function createMockTeamInstance(overrides: Partial<TeamInstance> = {}): TeamInstance {
159
+ return {
160
+ id: "test-team-1",
161
+ templateName: "test-team",
162
+ runtime: {
163
+ getTaskMode: vi.fn(() => "push"),
164
+ getStrategyName: vi.fn(() => "queue"),
165
+ getManifest: vi.fn(() => ({
166
+ roles: [{ name: "worker", extends: "worker" }],
167
+ communication: { channels: [] },
168
+ })),
169
+ } as any,
170
+ result: {
171
+ rootId: "agent_root1",
172
+ companionIds: ["agent_comp1"],
173
+ },
174
+ ...overrides,
175
+ };
176
+ }
177
+
178
+ function createMockTeamManager(): TeamManager {
179
+ const instance = createMockTeamInstance();
180
+ return {
181
+ startTeam: vi.fn(async () => instance),
182
+ stopTeam: vi.fn(async () => {}),
183
+ teardownAll: vi.fn(async () => {}),
184
+ getTeamForAgent: vi.fn(() => undefined),
185
+ getInstance: vi.fn((id: string) => (id === instance.id ? instance : undefined)),
186
+ getInstances: vi.fn(() => [instance]),
187
+ hasActiveTeam: vi.fn(() => true),
188
+ install: vi.fn(),
189
+ uninstall: vi.fn(),
190
+ } as unknown as TeamManager;
191
+ }
192
+
157
193
  // ─────────────────────────────────────────────────────────────────
158
194
  // Test Suite
159
195
  // ─────────────────────────────────────────────────────────────────
@@ -485,7 +521,7 @@ describe("API Server", () => {
485
521
 
486
522
  describe("Graceful Shutdown", () => {
487
523
  it("should call eventStore.persist and close on graceful shutdown", async () => {
488
- const server = createTrackedServer();
524
+ const server = createTrackedServer(services, { port: 0 });
489
525
  await server.start();
490
526
  await server.stop();
491
527
 
@@ -495,7 +531,7 @@ describe("API Server", () => {
495
531
  });
496
532
 
497
533
  it("should skip grace period on force shutdown", async () => {
498
- const server = createTrackedServer(services, { shutdownGracePeriodMs: 5000 });
534
+ const server = createTrackedServer(services, { port: 0, shutdownGracePeriodMs: 5000 });
499
535
  await server.start();
500
536
 
501
537
  const startTime = Date.now();
@@ -509,7 +545,7 @@ describe("API Server", () => {
509
545
  });
510
546
 
511
547
  it("should reject new messages during shutdown", async () => {
512
- const server = createTrackedServer();
548
+ const server = createTrackedServer(services, { port: 0 });
513
549
  await server.start();
514
550
 
515
551
  // Initialize first
@@ -535,7 +571,7 @@ describe("API Server", () => {
535
571
  });
536
572
 
537
573
  it("should only shutdown once on multiple stop calls", async () => {
538
- const server = createTrackedServer();
574
+ const server = createTrackedServer(services, { port: 0 });
539
575
  await server.start();
540
576
 
541
577
  // Call stop twice concurrently
@@ -549,6 +585,7 @@ describe("API Server", () => {
549
585
  it("should use custom shutdown grace period", async () => {
550
586
  const customGracePeriod = 100;
551
587
  const server = createTrackedServer(services, {
588
+ port: 0,
552
589
  shutdownGracePeriodMs: customGracePeriod,
553
590
  });
554
591
  await server.start();
@@ -1012,4 +1049,166 @@ describe("API Server", () => {
1012
1049
  );
1013
1050
  });
1014
1051
  });
1052
+
1053
+ // ─────────────────────────────────────────────────────────────────
1054
+ // Team Management API Endpoints
1055
+ // ─────────────────────────────────────────────────────────────────
1056
+
1057
+ describe("Team Management API", () => {
1058
+ let teamManager: TeamManager;
1059
+
1060
+ beforeEach(() => {
1061
+ teamManager = createMockTeamManager();
1062
+ services = { ...services, teamManager };
1063
+ });
1064
+
1065
+ describe("POST /api/teams", () => {
1066
+ it("should start a team instance", async () => {
1067
+ const server = createTrackedServer();
1068
+ const res = await request(server.app)
1069
+ .post("/api/teams")
1070
+ .send({ template: "test-team" });
1071
+
1072
+ expect(res.status).toBe(201);
1073
+ expect(res.body.id).toBe("test-team-1");
1074
+ expect(res.body.templateName).toBe("test-team");
1075
+ expect(res.body.rootAgentId).toBe("agent_root1");
1076
+ expect(res.body.companionAgentIds).toEqual(["agent_comp1"]);
1077
+ expect(res.body.taskMode).toBe("push");
1078
+ expect(res.body.strategy).toBe("queue");
1079
+ expect(teamManager.startTeam).toHaveBeenCalledWith("test-team", expect.any(String), undefined);
1080
+ });
1081
+
1082
+ it("should return 400 when template is missing", async () => {
1083
+ const server = createTrackedServer();
1084
+ const res = await request(server.app)
1085
+ .post("/api/teams")
1086
+ .send({});
1087
+
1088
+ expect(res.status).toBe(400);
1089
+ expect(res.body.code).toBe("INVALID_REQUEST");
1090
+ });
1091
+
1092
+ it("should allow starting multiple teams", async () => {
1093
+ const secondInstance = createMockTeamInstance({
1094
+ id: "second-team-1",
1095
+ templateName: "second-team",
1096
+ });
1097
+ (teamManager.startTeam as any)
1098
+ .mockResolvedValueOnce(createMockTeamInstance())
1099
+ .mockResolvedValueOnce(secondInstance);
1100
+
1101
+ const server = createTrackedServer();
1102
+
1103
+ const res1 = await request(server.app)
1104
+ .post("/api/teams")
1105
+ .send({ template: "test-team" });
1106
+ expect(res1.status).toBe(201);
1107
+
1108
+ const res2 = await request(server.app)
1109
+ .post("/api/teams")
1110
+ .send({ template: "second-team" });
1111
+ expect(res2.status).toBe(201);
1112
+ expect(res2.body.id).toBe("second-team-1");
1113
+ });
1114
+
1115
+ it("should return 500 on start failure", async () => {
1116
+ (teamManager.startTeam as any).mockRejectedValueOnce(
1117
+ new Error("Template not found")
1118
+ );
1119
+
1120
+ const server = createTrackedServer();
1121
+ const res = await request(server.app)
1122
+ .post("/api/teams")
1123
+ .send({ template: "bad-team" });
1124
+
1125
+ expect(res.status).toBe(500);
1126
+ expect(res.body.code).toBe("TEAM_START_FAILED");
1127
+ });
1128
+ });
1129
+
1130
+ describe("GET /api/teams", () => {
1131
+ it("should list running team instances", async () => {
1132
+ const server = createTrackedServer();
1133
+ const res = await request(server.app).get("/api/teams");
1134
+
1135
+ expect(res.status).toBe(200);
1136
+ expect(res.body).toHaveLength(1);
1137
+ expect(res.body[0].id).toBe("test-team-1");
1138
+ expect(res.body[0].templateName).toBe("test-team");
1139
+ expect(res.body[0].rootAgentId).toBe("agent_root1");
1140
+ });
1141
+
1142
+ it("should return empty array when no teams running", async () => {
1143
+ (teamManager.getInstances as any).mockReturnValue([]);
1144
+
1145
+ const server = createTrackedServer();
1146
+ const res = await request(server.app).get("/api/teams");
1147
+
1148
+ expect(res.status).toBe(200);
1149
+ expect(res.body).toEqual([]);
1150
+ });
1151
+ });
1152
+
1153
+ describe("GET /api/teams/:id", () => {
1154
+ it("should return team instance details", async () => {
1155
+ const server = createTrackedServer();
1156
+ const res = await request(server.app).get("/api/teams/test-team-1");
1157
+
1158
+ expect(res.status).toBe(200);
1159
+ expect(res.body.id).toBe("test-team-1");
1160
+ expect(res.body.roles).toBeDefined();
1161
+ expect(res.body.communication).toBeDefined();
1162
+ });
1163
+
1164
+ it("should return 404 for unknown team", async () => {
1165
+ const server = createTrackedServer();
1166
+ const res = await request(server.app).get("/api/teams/nonexistent");
1167
+
1168
+ expect(res.status).toBe(404);
1169
+ expect(res.body.code).toBe("TEAM_NOT_FOUND");
1170
+ });
1171
+ });
1172
+
1173
+ describe("DELETE /api/teams/:id", () => {
1174
+ it("should teardown a team instance", async () => {
1175
+ const server = createTrackedServer();
1176
+ const res = await request(server.app).delete("/api/teams/test-team-1");
1177
+
1178
+ expect(res.status).toBe(200);
1179
+ expect(res.body.success).toBe(true);
1180
+ expect(teamManager.stopTeam).toHaveBeenCalledWith("test-team-1");
1181
+ });
1182
+
1183
+ it("should return 404 for unknown team", async () => {
1184
+ const server = createTrackedServer();
1185
+ const res = await request(server.app).delete("/api/teams/nonexistent");
1186
+
1187
+ expect(res.status).toBe(404);
1188
+ expect(res.body.code).toBe("TEAM_NOT_FOUND");
1189
+ });
1190
+
1191
+ it("should return 500 on stop failure", async () => {
1192
+ (teamManager.stopTeam as any).mockRejectedValueOnce(
1193
+ new Error("Teardown failed")
1194
+ );
1195
+
1196
+ const server = createTrackedServer();
1197
+ const res = await request(server.app).delete("/api/teams/test-team-1");
1198
+
1199
+ expect(res.status).toBe(500);
1200
+ expect(res.body.code).toBe("TEAM_STOP_FAILED");
1201
+ });
1202
+ });
1203
+
1204
+ describe("without teamManager", () => {
1205
+ it("should not register team routes when teamManager is not provided", async () => {
1206
+ const servicesNoTeam = { eventStore, agentManager, taskManager, messageRouter };
1207
+ const server = createTrackedServer(servicesNoTeam);
1208
+
1209
+ const res = await request(server.app).get("/api/teams");
1210
+ expect(res.status).toBe(404);
1211
+ });
1212
+ });
1213
+ });
1015
1214
  });
package/src/api/server.ts CHANGED
@@ -56,6 +56,8 @@ import {
56
56
  type InjectionDeps,
57
57
  } from "../steering/index.js";
58
58
  import type { AgentId } from "../store/types/index.js";
59
+ import { secureCompare } from "../auth/token.js";
60
+ import type { TeamManager } from "../teams/team-manager.js";
59
61
 
60
62
  // ─────────────────────────────────────────────────────────────────
61
63
  // Server Configuration
@@ -73,6 +75,9 @@ export interface APIServerConfig {
73
75
 
74
76
  /** Grace period in milliseconds for in-flight work during shutdown (default: 5000) */
75
77
  shutdownGracePeriodMs?: number;
78
+
79
+ /** Server token for Bearer auth on API routes. When set, all routes except /health require auth. */
80
+ serverToken?: string;
76
81
  }
77
82
 
78
83
  export interface APIServices {
@@ -84,6 +89,8 @@ export interface APIServices {
84
89
  mailService?: import("../mail/mail-service.js").MailService;
85
90
  /** Optional conversation map for agent-to-conversation tracking */
86
91
  conversationMap?: import("../mail/conversation-map.js").ConversationMap;
92
+ /** Optional team manager for dynamic team management */
93
+ teamManager?: TeamManager;
87
94
  }
88
95
 
89
96
  // ─────────────────────────────────────────────────────────────────
@@ -343,6 +350,113 @@ function registerConversationRoutes(
343
350
  });
344
351
  }
345
352
 
353
+ // ─────────────────────────────────────────────────────────────────
354
+ // Shared Team Routes Helper
355
+ // ─────────────────────────────────────────────────────────────────
356
+
357
+ /**
358
+ * Register team management REST endpoints on an Express app.
359
+ * Shared between standalone and shared API modes.
360
+ *
361
+ * Endpoints:
362
+ * POST /api/teams — Start a team instance
363
+ * GET /api/teams — List running team instances
364
+ * GET /api/teams/:id — Get team instance details
365
+ * DELETE /api/teams/:id — Teardown a team instance
366
+ */
367
+ function registerTeamRoutes(
368
+ app: Express,
369
+ teamManager: TeamManager | undefined,
370
+ defaultCwd: string,
371
+ sendError: (res: Response, status: number, code: string, message: string) => void,
372
+ broadcast?: (channel: string, message: WSMessage) => void,
373
+ ): void {
374
+ if (!teamManager) return;
375
+
376
+ // POST /api/teams — Start a team instance
377
+ app.post("/api/teams", async (req: Request, res: Response) => {
378
+ const { template, overrides } = req.body ?? {};
379
+ if (!template || typeof template !== "string") {
380
+ return sendError(res, 400, "INVALID_REQUEST", "Missing required field: template");
381
+ }
382
+
383
+ try {
384
+ const instance = await teamManager.startTeam(template, defaultCwd, overrides);
385
+ const result = {
386
+ id: instance.id,
387
+ templateName: instance.templateName,
388
+ rootAgentId: instance.result.rootId,
389
+ companionAgentIds: instance.result.companionIds,
390
+ taskMode: instance.runtime.getTaskMode(),
391
+ strategy: instance.runtime.getStrategyName(),
392
+ };
393
+
394
+ if (broadcast) {
395
+ broadcast("teams", { type: "team_started", data: result });
396
+ }
397
+
398
+ res.status(201).json(result);
399
+ } catch (err) {
400
+ const message = err instanceof Error ? err.message : String(err);
401
+ return sendError(res, 500, "TEAM_START_FAILED", message);
402
+ }
403
+ });
404
+
405
+ // GET /api/teams — List running team instances
406
+ app.get("/api/teams", (_req: Request, res: Response) => {
407
+ const instances = teamManager.getInstances();
408
+ res.json(instances.map((inst) => ({
409
+ id: inst.id,
410
+ templateName: inst.templateName,
411
+ rootAgentId: inst.result.rootId,
412
+ companionAgentIds: inst.result.companionIds,
413
+ taskMode: inst.runtime.getTaskMode(),
414
+ strategy: inst.runtime.getStrategyName(),
415
+ })));
416
+ });
417
+
418
+ // GET /api/teams/:id — Get team instance details
419
+ app.get("/api/teams/:id", (req: Request, res: Response) => {
420
+ const instance = teamManager.getInstance(req.params.id);
421
+ if (!instance) {
422
+ return sendError(res, 404, "TEAM_NOT_FOUND", `No team instance '${req.params.id}'`);
423
+ }
424
+
425
+ const manifest = instance.runtime.getManifest();
426
+ res.json({
427
+ id: instance.id,
428
+ templateName: instance.templateName,
429
+ rootAgentId: instance.result.rootId,
430
+ companionAgentIds: instance.result.companionIds,
431
+ taskMode: instance.runtime.getTaskMode(),
432
+ strategy: instance.runtime.getStrategyName(),
433
+ roles: manifest.roles,
434
+ communication: manifest.communication,
435
+ });
436
+ });
437
+
438
+ // DELETE /api/teams/:id — Teardown a team instance
439
+ app.delete("/api/teams/:id", async (req: Request, res: Response) => {
440
+ const instance = teamManager.getInstance(req.params.id);
441
+ if (!instance) {
442
+ return sendError(res, 404, "TEAM_NOT_FOUND", `No team instance '${req.params.id}'`);
443
+ }
444
+
445
+ try {
446
+ await teamManager.stopTeam(req.params.id);
447
+
448
+ if (broadcast) {
449
+ broadcast("teams", { type: "team_stopped", data: { id: req.params.id } });
450
+ }
451
+
452
+ res.json({ success: true });
453
+ } catch (err) {
454
+ const message = err instanceof Error ? err.message : String(err);
455
+ return sendError(res, 500, "TEAM_STOP_FAILED", message);
456
+ }
457
+ });
458
+ }
459
+
346
460
  // ─────────────────────────────────────────────────────────────────
347
461
  // Create API Server
348
462
  // ─────────────────────────────────────────────────────────────────
@@ -351,7 +465,7 @@ export function createAPIServer(
351
465
  services: APIServices,
352
466
  config: APIServerConfig = {}
353
467
  ): APIServer {
354
- const { port = 3000, host = "localhost", cors = true, shutdownGracePeriodMs = 5000 } = config;
468
+ const { port = 3000, host = "localhost", cors = true, shutdownGracePeriodMs = 5000, serverToken } = config;
355
469
  const { eventStore, agentManager, taskManager } = services;
356
470
 
357
471
  // Server state
@@ -374,12 +488,27 @@ export function createAPIServer(
374
488
  if (cors) {
375
489
  app.use((_req: Request, res: Response, next: NextFunction) => {
376
490
  res.header("Access-Control-Allow-Origin", "*");
377
- res.header("Access-Control-Allow-Headers", "Content-Type");
491
+ res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
378
492
  res.header("Access-Control-Allow-Methods", "GET, POST, DELETE");
379
493
  next();
380
494
  });
381
495
  }
382
496
 
497
+ // Bearer token auth middleware (skip /health)
498
+ if (serverToken) {
499
+ app.use((req: Request, res: Response, next: NextFunction) => {
500
+ if (req.path === "/health") return next();
501
+ const authHeader = req.headers.authorization;
502
+ const token = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : undefined;
503
+ if (!token || !secureCompare(token, serverToken)) {
504
+ const error: APIError = { error: "Unauthorized", code: "AUTH_REQUIRED" };
505
+ res.status(401).json(error);
506
+ return;
507
+ }
508
+ next();
509
+ });
510
+ }
511
+
383
512
  // ─────────────────────────────────────────────────────────────────
384
513
  // Helper Functions
385
514
  // ─────────────────────────────────────────────────────────────────
@@ -438,7 +567,7 @@ export function createAPIServer(
438
567
  case "spawn":
439
568
  summary = `Agent ${event.payload.agent_id} spawned`;
440
569
  break;
441
- case "terminate":
570
+ case "stop":
442
571
  summary = `Agent terminated: ${event.payload.reason}`;
443
572
  break;
444
573
  case "status":
@@ -549,8 +678,11 @@ export function createAPIServer(
549
678
  res.json(status);
550
679
  });
551
680
 
552
- // GET /api/team - Get active team info
681
+ // GET /api/team - Get active team info (DEPRECATED: use GET /api/teams)
553
682
  app.get("/api/team", (_req: Request, res: Response) => {
683
+ res.set("Deprecation", "true");
684
+ res.set("Link", '</api/teams>; rel="successor-version"');
685
+
554
686
  // Check for team config in EventStore
555
687
  const statusEvents = eventStore.query({ type: "status", limit: 50 });
556
688
  const teamConfigEvent = statusEvents.find(
@@ -572,6 +704,9 @@ export function createAPIServer(
572
704
  });
573
705
  });
574
706
 
707
+ // Register dynamic team management routes
708
+ registerTeamRoutes(app, services.teamManager, process.cwd(), sendError, broadcastToChannel);
709
+
575
710
  // ─────────────────────────────────────────────────────────────────
576
711
  // Metrics Endpoints (Phase 5)
577
712
  // ─────────────────────────────────────────────────────────────────
@@ -1156,7 +1291,7 @@ export function createAPIServer(
1156
1291
  const gracePeriod = options?.force ? 0 : shutdownGracePeriodMs;
1157
1292
 
1158
1293
  // 1. Stop accepting new connections
1159
- server.close();
1294
+ await new Promise<void>((resolve) => server.close(() => resolve()));
1160
1295
 
1161
1296
  // 2. Wait grace period for in-flight work
1162
1297
  if (gracePeriod > 0) {
@@ -1240,10 +1375,10 @@ export function createAPIServer(
1240
1375
  * @returns Express app
1241
1376
  */
1242
1377
  export function createAPIApp(
1243
- services: Pick<APIServices, "eventStore" | "agentManager" | "taskManager" | "messageRouter"> & Pick<Partial<APIServices>, "mailService" | "conversationMap">,
1244
- config: { cors?: boolean } = {}
1378
+ services: Pick<APIServices, "eventStore" | "agentManager" | "taskManager" | "messageRouter"> & Pick<Partial<APIServices>, "mailService" | "conversationMap" | "teamManager">,
1379
+ config: { cors?: boolean; serverToken?: string; defaultCwd?: string } = {}
1245
1380
  ): Express {
1246
- const { cors = true } = config;
1381
+ const { cors = true, serverToken, defaultCwd } = config;
1247
1382
  const { agentManager, taskManager, messageRouter } = services;
1248
1383
 
1249
1384
  // Create shared state
@@ -1262,12 +1397,27 @@ export function createAPIApp(
1262
1397
  if (cors) {
1263
1398
  app.use((_req: Request, res: Response, next: NextFunction) => {
1264
1399
  res.header("Access-Control-Allow-Origin", "*");
1265
- res.header("Access-Control-Allow-Headers", "Content-Type");
1400
+ res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
1266
1401
  res.header("Access-Control-Allow-Methods", "GET, POST, DELETE");
1267
1402
  next();
1268
1403
  });
1269
1404
  }
1270
1405
 
1406
+ // Bearer token auth middleware (skip /health)
1407
+ if (serverToken) {
1408
+ app.use((req: Request, res: Response, next: NextFunction) => {
1409
+ if (req.path === "/health") return next();
1410
+ const authHeader = req.headers.authorization;
1411
+ const token = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : undefined;
1412
+ if (!token || !secureCompare(token, serverToken)) {
1413
+ const error: APIError = { error: "Unauthorized", code: "AUTH_REQUIRED" };
1414
+ res.status(401).json(error);
1415
+ return;
1416
+ }
1417
+ next();
1418
+ });
1419
+ }
1420
+
1271
1421
  // ─────────────────────────────────────────────────────────────────
1272
1422
  // Helper Functions
1273
1423
  // ─────────────────────────────────────────────────────────────────
@@ -1326,7 +1476,7 @@ export function createAPIApp(
1326
1476
  case "spawn":
1327
1477
  summary = `Agent ${event.payload.agent_id} spawned`;
1328
1478
  break;
1329
- case "terminate":
1479
+ case "stop":
1330
1480
  summary = `Agent terminated: ${event.payload.reason}`;
1331
1481
  break;
1332
1482
  case "status":
@@ -1789,6 +1939,15 @@ export function createAPIApp(
1789
1939
  // Register conversation API routes (if mail service available)
1790
1940
  registerConversationRoutes(app, services, sendError);
1791
1941
 
1942
+ // Register dynamic team management routes
1943
+ registerTeamRoutes(
1944
+ app,
1945
+ services.teamManager,
1946
+ defaultCwd ?? process.cwd(),
1947
+ sendError,
1948
+ state.broadcast,
1949
+ );
1950
+
1792
1951
  return app;
1793
1952
  }
1794
1953
 
package/src/api/types.ts CHANGED
@@ -184,7 +184,9 @@ export type WSMessageType =
184
184
  | "status"
185
185
  | "error"
186
186
  | "conversation_update"
187
- | "turn_added";
187
+ | "turn_added"
188
+ | "team_started"
189
+ | "team_stopped";
188
190
 
189
191
  export interface WSMessage {
190
192
  type: WSMessageType;
@@ -0,0 +1,100 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { generateToken, secureCompare, AgentTokenManager } from "../token.js";
3
+
4
+ describe("generateToken", () => {
5
+ it("generates a hex string of expected length", () => {
6
+ const token = generateToken();
7
+ // 32 bytes = 64 hex chars
8
+ expect(token).toHaveLength(64);
9
+ expect(token).toMatch(/^[0-9a-f]+$/);
10
+ });
11
+
12
+ it("generates different tokens each time", () => {
13
+ const a = generateToken();
14
+ const b = generateToken();
15
+ expect(a).not.toBe(b);
16
+ });
17
+
18
+ it("respects custom byte length", () => {
19
+ const token = generateToken(16);
20
+ expect(token).toHaveLength(32); // 16 bytes = 32 hex chars
21
+ });
22
+ });
23
+
24
+ describe("secureCompare", () => {
25
+ it("returns true for identical strings", () => {
26
+ expect(secureCompare("abc123", "abc123")).toBe(true);
27
+ });
28
+
29
+ it("returns false for different strings of same length", () => {
30
+ expect(secureCompare("abc123", "xyz789")).toBe(false);
31
+ });
32
+
33
+ it("returns false for different length strings", () => {
34
+ expect(secureCompare("short", "longer-string")).toBe(false);
35
+ });
36
+
37
+ it("returns true for empty strings", () => {
38
+ expect(secureCompare("", "")).toBe(true);
39
+ });
40
+ });
41
+
42
+ describe("AgentTokenManager", () => {
43
+ it("creates and verifies a token", () => {
44
+ const mgr = new AgentTokenManager();
45
+ const token = mgr.createToken("agent-1");
46
+ expect(token).toHaveLength(64);
47
+ expect(mgr.verifyToken("agent-1", token)).toBe(true);
48
+ });
49
+
50
+ it("rejects wrong token", () => {
51
+ const mgr = new AgentTokenManager();
52
+ mgr.createToken("agent-1");
53
+ expect(mgr.verifyToken("agent-1", "wrong-token")).toBe(false);
54
+ });
55
+
56
+ it("rejects unknown agent", () => {
57
+ const mgr = new AgentTokenManager();
58
+ expect(mgr.verifyToken("unknown", "any-token")).toBe(false);
59
+ });
60
+
61
+ it("revokes a token", () => {
62
+ const mgr = new AgentTokenManager();
63
+ const token = mgr.createToken("agent-1");
64
+ expect(mgr.revokeToken("agent-1")).toBe(true);
65
+ expect(mgr.verifyToken("agent-1", token)).toBe(false);
66
+ expect(mgr.hasToken("agent-1")).toBe(false);
67
+ });
68
+
69
+ it("revoke returns false for unknown agent", () => {
70
+ const mgr = new AgentTokenManager();
71
+ expect(mgr.revokeToken("unknown")).toBe(false);
72
+ });
73
+
74
+ it("hasToken returns correct state", () => {
75
+ const mgr = new AgentTokenManager();
76
+ expect(mgr.hasToken("agent-1")).toBe(false);
77
+ mgr.createToken("agent-1");
78
+ expect(mgr.hasToken("agent-1")).toBe(true);
79
+ });
80
+
81
+ it("createToken overwrites previous token", () => {
82
+ const mgr = new AgentTokenManager();
83
+ const token1 = mgr.createToken("agent-1");
84
+ const token2 = mgr.createToken("agent-1");
85
+ expect(token1).not.toBe(token2);
86
+ expect(mgr.verifyToken("agent-1", token1)).toBe(false);
87
+ expect(mgr.verifyToken("agent-1", token2)).toBe(true);
88
+ });
89
+
90
+ it("manages multiple agents independently", () => {
91
+ const mgr = new AgentTokenManager();
92
+ const t1 = mgr.createToken("agent-1");
93
+ const t2 = mgr.createToken("agent-2");
94
+ expect(mgr.verifyToken("agent-1", t1)).toBe(true);
95
+ expect(mgr.verifyToken("agent-2", t2)).toBe(true);
96
+ // Cross-validation fails
97
+ expect(mgr.verifyToken("agent-1", t2)).toBe(false);
98
+ expect(mgr.verifyToken("agent-2", t1)).toBe(false);
99
+ });
100
+ });
@@ -0,0 +1 @@
1
+ export { generateToken, secureCompare, AgentTokenManager } from "./token.js";