macro-agent 0.1.0 → 0.1.1

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 (337) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/.sudocode/specs.jsonl +4 -0
  3. package/CLAUDE.md +16 -14
  4. package/README.md +11 -29
  5. package/dist/acp/macro-agent.d.ts +15 -0
  6. package/dist/acp/macro-agent.d.ts.map +1 -1
  7. package/dist/acp/macro-agent.js +131 -35
  8. package/dist/acp/macro-agent.js.map +1 -1
  9. package/dist/acp/types.d.ts +32 -1
  10. package/dist/acp/types.d.ts.map +1 -1
  11. package/dist/acp/types.js.map +1 -1
  12. package/dist/agent/agent-manager.d.ts +65 -1
  13. package/dist/agent/agent-manager.d.ts.map +1 -1
  14. package/dist/agent/agent-manager.js +464 -183
  15. package/dist/agent/agent-manager.js.map +1 -1
  16. package/dist/agent/types.d.ts +1 -1
  17. package/dist/agent/types.d.ts.map +1 -1
  18. package/dist/api/server.d.ts +3 -0
  19. package/dist/api/server.d.ts.map +1 -1
  20. package/dist/api/server.js +37 -6
  21. package/dist/api/server.js.map +1 -1
  22. package/dist/auth/index.d.ts +2 -0
  23. package/dist/auth/index.d.ts.map +1 -0
  24. package/dist/auth/index.js +2 -0
  25. package/dist/auth/index.js.map +1 -0
  26. package/dist/auth/token.d.ts +41 -0
  27. package/dist/auth/token.d.ts.map +1 -0
  28. package/dist/auth/token.js +73 -0
  29. package/dist/auth/token.js.map +1 -0
  30. package/dist/cli/acp.d.ts +2 -23
  31. package/dist/cli/acp.d.ts.map +1 -1
  32. package/dist/cli/acp.js +127 -61
  33. package/dist/cli/acp.js.map +1 -1
  34. package/dist/cli/index.js +147 -15
  35. package/dist/cli/index.js.map +1 -1
  36. package/dist/cli/mcp.d.ts +6 -0
  37. package/dist/cli/mcp.d.ts.map +1 -1
  38. package/dist/cli/mcp.js +268 -181
  39. package/dist/cli/mcp.js.map +1 -1
  40. package/dist/cli/parse-args.d.ts +20 -0
  41. package/dist/cli/parse-args.d.ts.map +1 -0
  42. package/dist/cli/parse-args.js +43 -0
  43. package/dist/cli/parse-args.js.map +1 -0
  44. package/dist/cli/stable-instance-id.d.ts +8 -0
  45. package/dist/cli/stable-instance-id.d.ts.map +1 -0
  46. package/dist/cli/stable-instance-id.js +14 -0
  47. package/dist/cli/stable-instance-id.js.map +1 -0
  48. package/dist/config/project-config.d.ts +74 -7
  49. package/dist/config/project-config.d.ts.map +1 -1
  50. package/dist/config/project-config.js +123 -20
  51. package/dist/config/project-config.js.map +1 -1
  52. package/dist/map/adapter/acp-over-map.d.ts +17 -0
  53. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  54. package/dist/map/adapter/acp-over-map.js +384 -23
  55. package/dist/map/adapter/acp-over-map.js.map +1 -1
  56. package/dist/map/adapter/connection-manager.d.ts.map +1 -1
  57. package/dist/map/adapter/connection-manager.js +3 -0
  58. package/dist/map/adapter/connection-manager.js.map +1 -1
  59. package/dist/map/adapter/event-log.d.ts +87 -0
  60. package/dist/map/adapter/event-log.d.ts.map +1 -0
  61. package/dist/map/adapter/event-log.js +122 -0
  62. package/dist/map/adapter/event-log.js.map +1 -0
  63. package/dist/map/adapter/event-translator.js +6 -6
  64. package/dist/map/adapter/event-translator.js.map +1 -1
  65. package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
  66. package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
  67. package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
  68. package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
  69. package/dist/map/adapter/extensions/index.d.ts +10 -1
  70. package/dist/map/adapter/extensions/index.d.ts.map +1 -1
  71. package/dist/map/adapter/extensions/index.js +34 -0
  72. package/dist/map/adapter/extensions/index.js.map +1 -1
  73. package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
  74. package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
  75. package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
  76. package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
  77. package/dist/map/adapter/extensions/rename.d.ts +29 -0
  78. package/dist/map/adapter/extensions/rename.d.ts.map +1 -0
  79. package/dist/map/adapter/extensions/rename.js +49 -0
  80. package/dist/map/adapter/extensions/rename.js.map +1 -0
  81. package/dist/map/adapter/extensions/task.d.ts.map +1 -1
  82. package/dist/map/adapter/extensions/task.js +10 -0
  83. package/dist/map/adapter/extensions/task.js.map +1 -1
  84. package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
  85. package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
  86. package/dist/map/adapter/extensions/update-metadata.js +67 -0
  87. package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
  88. package/dist/map/adapter/index.d.ts +2 -1
  89. package/dist/map/adapter/index.d.ts.map +1 -1
  90. package/dist/map/adapter/index.js +8 -2
  91. package/dist/map/adapter/index.js.map +1 -1
  92. package/dist/map/adapter/interface.d.ts +2 -0
  93. package/dist/map/adapter/interface.d.ts.map +1 -1
  94. package/dist/map/adapter/map-adapter.d.ts +3 -0
  95. package/dist/map/adapter/map-adapter.d.ts.map +1 -1
  96. package/dist/map/adapter/map-adapter.js +258 -35
  97. package/dist/map/adapter/map-adapter.js.map +1 -1
  98. package/dist/map/adapter/subscription-manager.d.ts.map +1 -1
  99. package/dist/map/adapter/subscription-manager.js +5 -1
  100. package/dist/map/adapter/subscription-manager.js.map +1 -1
  101. package/dist/map/adapter/types.d.ts +2 -0
  102. package/dist/map/adapter/types.d.ts.map +1 -1
  103. package/dist/mcp/map-client.d.ts +39 -0
  104. package/dist/mcp/map-client.d.ts.map +1 -0
  105. package/dist/mcp/map-client.js +129 -0
  106. package/dist/mcp/map-client.js.map +1 -0
  107. package/dist/mcp/mcp-server.d.ts +14 -0
  108. package/dist/mcp/mcp-server.d.ts.map +1 -1
  109. package/dist/mcp/mcp-server.js +113 -85
  110. package/dist/mcp/mcp-server.js.map +1 -1
  111. package/dist/mcp/types.d.ts +9 -1
  112. package/dist/mcp/types.d.ts.map +1 -1
  113. package/dist/mcp/types.js.map +1 -1
  114. package/dist/metrics/metrics.js +1 -1
  115. package/dist/metrics/metrics.js.map +1 -1
  116. package/dist/roles/capabilities.d.ts +3 -1
  117. package/dist/roles/capabilities.d.ts.map +1 -1
  118. package/dist/roles/capabilities.js +17 -7
  119. package/dist/roles/capabilities.js.map +1 -1
  120. package/dist/roles/config-loader.d.ts +6 -6
  121. package/dist/roles/config-loader.d.ts.map +1 -1
  122. package/dist/roles/config-loader.js +6 -6
  123. package/dist/roles/config-loader.js.map +1 -1
  124. package/dist/roles/registry.d.ts +2 -2
  125. package/dist/roles/registry.js +2 -2
  126. package/dist/server/combined-server.d.ts +20 -0
  127. package/dist/server/combined-server.d.ts.map +1 -1
  128. package/dist/server/combined-server.js +107 -8
  129. package/dist/server/combined-server.js.map +1 -1
  130. package/dist/store/event-store.d.ts +2 -1
  131. package/dist/store/event-store.d.ts.map +1 -1
  132. package/dist/store/event-store.js +69 -20
  133. package/dist/store/event-store.js.map +1 -1
  134. package/dist/store/types/agents.d.ts +18 -0
  135. package/dist/store/types/agents.d.ts.map +1 -1
  136. package/dist/store/types/events.d.ts +1 -1
  137. package/dist/store/types/events.d.ts.map +1 -1
  138. package/dist/task/backend/index.d.ts +47 -29
  139. package/dist/task/backend/index.d.ts.map +1 -1
  140. package/dist/task/backend/index.js +109 -71
  141. package/dist/task/backend/index.js.map +1 -1
  142. package/dist/task/backend/memory.d.ts +1 -0
  143. package/dist/task/backend/memory.d.ts.map +1 -1
  144. package/dist/task/backend/memory.js +3 -0
  145. package/dist/task/backend/memory.js.map +1 -1
  146. package/dist/task/backend/opentasks/backend.d.ts +140 -0
  147. package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
  148. package/dist/task/backend/opentasks/backend.js +1023 -0
  149. package/dist/task/backend/opentasks/backend.js.map +1 -0
  150. package/dist/task/backend/opentasks/client.d.ts +337 -0
  151. package/dist/task/backend/opentasks/client.d.ts.map +1 -0
  152. package/dist/task/backend/opentasks/client.js +225 -0
  153. package/dist/task/backend/opentasks/client.js.map +1 -0
  154. package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
  155. package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
  156. package/dist/task/backend/opentasks/daemon-manager.js +195 -0
  157. package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
  158. package/dist/task/backend/opentasks/index.d.ts +21 -0
  159. package/dist/task/backend/opentasks/index.d.ts.map +1 -0
  160. package/dist/task/backend/opentasks/index.js +21 -0
  161. package/dist/task/backend/opentasks/index.js.map +1 -0
  162. package/dist/task/backend/opentasks/mapping.d.ts +48 -0
  163. package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
  164. package/dist/task/backend/opentasks/mapping.js +77 -0
  165. package/dist/task/backend/opentasks/mapping.js.map +1 -0
  166. package/dist/task/backend/types.d.ts +33 -53
  167. package/dist/task/backend/types.d.ts.map +1 -1
  168. package/dist/task/backend/types.js +7 -11
  169. package/dist/task/backend/types.js.map +1 -1
  170. package/dist/task/backend/unified-tool-provider.d.ts +57 -0
  171. package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
  172. package/dist/task/backend/unified-tool-provider.js +623 -0
  173. package/dist/task/backend/unified-tool-provider.js.map +1 -0
  174. package/dist/teams/team-loader.d.ts +2 -2
  175. package/dist/teams/team-loader.js +3 -3
  176. package/dist/teams/team-loader.js.map +1 -1
  177. package/dist/teams/team-runtime.d.ts.map +1 -1
  178. package/dist/teams/team-runtime.js +2 -0
  179. package/dist/teams/team-runtime.js.map +1 -1
  180. package/docs/architecture.md +7 -6
  181. package/docs/configuration.md +26 -62
  182. package/docs/implementation-details.md +5 -5
  183. package/docs/implementation-summary.md +17 -17
  184. package/docs/plan-self-driving-support.md +4 -4
  185. package/docs/spec-self-driving-support.md +10 -10
  186. package/docs/team-templates.md +2 -2
  187. package/docs/teams.md +3 -3
  188. package/docs/troubleshooting.md +10 -11
  189. package/package.json +6 -4
  190. package/src/__tests__/e2e/agent-spawn-visibility.e2e.test.ts +761 -0
  191. package/src/__tests__/e2e/full-agent-conflict-resolution.e2e.test.ts +2 -2
  192. package/src/__tests__/e2e/mcp-thin-client-bridge.e2e.test.ts +304 -0
  193. package/src/__tests__/e2e/mcp-tools-available.e2e.test.ts +324 -0
  194. package/src/__tests__/e2e/multi-agent.e2e.test.ts +5 -5
  195. package/src/__tests__/e2e/spawn-session-streaming.e2e.test.ts +563 -0
  196. package/src/acp/__tests__/integration.test.ts +56 -31
  197. package/src/acp/__tests__/macro-agent.test.ts +16 -7
  198. package/src/acp/macro-agent.ts +170 -36
  199. package/src/acp/types.ts +46 -1
  200. package/src/agent/__tests__/agent-manager.test.ts +228 -2
  201. package/src/agent/agent-manager.ts +714 -261
  202. package/src/agent/types.ts +3 -1
  203. package/src/api/server.ts +41 -7
  204. package/src/auth/__tests__/token.test.ts +100 -0
  205. package/src/auth/index.ts +1 -0
  206. package/src/auth/token.ts +82 -0
  207. package/src/cli/__tests__/acp.test.ts +1 -1
  208. package/src/cli/__tests__/stable-instance-id.test.ts +1 -1
  209. package/src/cli/acp.ts +130 -72
  210. package/src/cli/index.ts +120 -14
  211. package/src/cli/mcp.ts +311 -207
  212. package/src/cli/parse-args.ts +54 -0
  213. package/src/cli/stable-instance-id.ts +14 -0
  214. package/src/config/project-config.ts +190 -27
  215. package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
  216. package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +22 -4
  217. package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
  218. package/src/map/adapter/__tests__/acp-over-map-history.test.ts +263 -0
  219. package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +1 -1
  220. package/src/map/adapter/__tests__/event-broadcast.test.ts +420 -0
  221. package/src/map/adapter/__tests__/event-log.test.ts +527 -0
  222. package/src/map/adapter/__tests__/event-translator.test.ts +3 -3
  223. package/src/map/adapter/__tests__/extensions.test.ts +408 -0
  224. package/src/map/adapter/__tests__/map-adapter.test.ts +99 -0
  225. package/src/map/adapter/__tests__/mcp-bridge.test.ts +1187 -0
  226. package/src/map/adapter/__tests__/multi-client-broadcast.test.ts +711 -0
  227. package/src/map/adapter/__tests__/websocket-integration.test.ts +218 -0
  228. package/src/map/adapter/acp-over-map.ts +678 -66
  229. package/src/map/adapter/connection-manager.ts +3 -0
  230. package/src/map/adapter/event-log.ts +208 -0
  231. package/src/map/adapter/event-translator.ts +6 -6
  232. package/src/map/adapter/extensions/agent-lifecycle.ts +267 -0
  233. package/src/map/adapter/extensions/index.ts +60 -0
  234. package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
  235. package/src/map/adapter/extensions/task.ts +11 -0
  236. package/src/map/adapter/extensions/update-metadata.ts +126 -0
  237. package/src/map/adapter/index.ts +28 -0
  238. package/src/map/adapter/interface.ts +2 -0
  239. package/src/map/adapter/map-adapter.ts +312 -47
  240. package/src/map/adapter/subscription-manager.ts +5 -1
  241. package/src/map/adapter/types.ts +2 -0
  242. package/src/mcp/__tests__/map-client.test.ts +386 -0
  243. package/src/mcp/__tests__/mcp-server-thin-client.test.ts +368 -0
  244. package/src/mcp/__tests__/mcp-server.test.ts +100 -1
  245. package/src/mcp/map-client.ts +177 -0
  246. package/src/mcp/mcp-server.ts +191 -100
  247. package/src/mcp/types.ts +6 -1
  248. package/src/metrics/metrics.ts +1 -1
  249. package/src/monitor/__tests__/stale-agent-flow.integration.test.ts +1 -1
  250. package/src/roles/__tests__/config-loader.test.ts +7 -7
  251. package/src/roles/capabilities.ts +17 -7
  252. package/src/roles/config-loader.ts +6 -6
  253. package/src/roles/registry.ts +2 -2
  254. package/src/server/__tests__/combined-server.test.ts +94 -21
  255. package/src/server/combined-server.ts +189 -33
  256. package/src/steering/__tests__/steering-integration.test.ts +1 -1
  257. package/src/store/__tests__/event-store.test.ts +196 -1
  258. package/src/store/__tests__/instance.test.ts +3 -3
  259. package/src/store/event-store.ts +80 -21
  260. package/src/store/types/agents.ts +15 -0
  261. package/src/store/types/events.ts +1 -1
  262. package/src/task/backend/__tests__/create-task-backend.test.ts +225 -0
  263. package/src/task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test.ts +524 -0
  264. package/src/task/backend/__tests__/unified-tool-provider.test.ts +579 -0
  265. package/src/task/backend/index.ts +156 -106
  266. package/src/task/backend/memory.ts +4 -0
  267. package/src/task/backend/opentasks/__tests__/backend.test.ts +968 -0
  268. package/src/task/backend/opentasks/__tests__/daemon-manager.test.ts +406 -0
  269. package/src/task/backend/opentasks/__tests__/mapping.test.ts +84 -0
  270. package/src/task/backend/opentasks/__tests__/opentasks-backend.e2e.test.ts +1338 -0
  271. package/src/task/backend/opentasks/backend.ts +1323 -0
  272. package/src/task/backend/opentasks/client.ts +652 -0
  273. package/src/task/backend/opentasks/daemon-manager.ts +253 -0
  274. package/src/task/backend/opentasks/index.ts +69 -0
  275. package/src/task/backend/opentasks/mapping.ts +94 -0
  276. package/src/task/backend/types.ts +42 -66
  277. package/src/task/backend/unified-tool-provider.ts +779 -0
  278. package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
  279. package/src/teams/team-loader.ts +3 -3
  280. package/src/teams/team-runtime.ts +2 -0
  281. package/test_fixtures/README.md +2 -3
  282. package/test_fixtures/fixtures/index.ts +0 -3
  283. package/test_fixtures/fixtures/projects/project-with-specs.ts +7 -149
  284. package/test_fixtures/fixtures/repos/index.ts +1 -3
  285. package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -116
  286. package/test_fixtures/fixtures/repos/types.ts +0 -11
  287. package/test_fixtures/harness/__tests__/fixtures.test.ts +10 -102
  288. package/test_fixtures/harness/__tests__/temp-repo-and-simulator.test.ts +0 -33
  289. package/test_fixtures/harness/simulator/agent-simulator.ts +4 -4
  290. package/vitest.config.ts +1 -1
  291. package/vitest.e2e.config.ts +1 -1
  292. package/vitest.setup.ts +1 -30
  293. package/.macro-agent/teams/self-driving/prompts/grinder.md +0 -27
  294. package/.macro-agent/teams/self-driving/prompts/judge.md +0 -27
  295. package/.macro-agent/teams/self-driving/prompts/planner.md +0 -33
  296. package/.macro-agent/teams/self-driving/roles/grinder.yaml +0 -17
  297. package/.macro-agent/teams/self-driving/roles/judge.yaml +0 -24
  298. package/.macro-agent/teams/self-driving/roles/planner.yaml +0 -18
  299. package/.macro-agent/teams/self-driving/team.yaml +0 -103
  300. package/.macro-agent/teams/structured/prompts/developer.md +0 -26
  301. package/.macro-agent/teams/structured/prompts/lead.md +0 -25
  302. package/.macro-agent/teams/structured/prompts/reviewer.md +0 -24
  303. package/.macro-agent/teams/structured/roles/developer.yaml +0 -12
  304. package/.macro-agent/teams/structured/roles/lead.yaml +0 -11
  305. package/.macro-agent/teams/structured/roles/reviewer.yaml +0 -19
  306. package/.macro-agent/teams/structured/team.yaml +0 -89
  307. package/docs/sudocode-integration.md +0 -383
  308. package/src/task/backend/__tests__/backend-parity.test.ts +0 -451
  309. package/src/task/backend/__tests__/tool-provider-edge-cases.test.ts +0 -430
  310. package/src/task/backend/__tests__/tool-provider.test.ts +0 -983
  311. package/src/task/backend/sudocode/__tests__/backend-edge-cases.test.ts +0 -575
  312. package/src/task/backend/sudocode/__tests__/backend.test.ts +0 -1194
  313. package/src/task/backend/sudocode/__tests__/client-integration.test.ts +0 -418
  314. package/src/task/backend/sudocode/__tests__/client.test.ts +0 -345
  315. package/src/task/backend/sudocode/__tests__/e2e/backend.e2e.test.ts +0 -753
  316. package/src/task/backend/sudocode/__tests__/e2e/server-client.e2e.test.ts +0 -680
  317. package/src/task/backend/sudocode/__tests__/e2e-workflow.test.ts +0 -666
  318. package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts +0 -396
  319. package/src/task/backend/sudocode/__tests__/integration/sudocode-cli.integration.test.ts +0 -328
  320. package/src/task/backend/sudocode/__tests__/integration/test-utils.ts +0 -175
  321. package/src/task/backend/sudocode/__tests__/mapping-edge-cases.test.ts +0 -265
  322. package/src/task/backend/sudocode/__tests__/server-client.test.ts +0 -675
  323. package/src/task/backend/sudocode/__tests__/sync-policy-edge-cases.test.ts +0 -521
  324. package/src/task/backend/sudocode/__tests__/sync-policy.test.ts +0 -519
  325. package/src/task/backend/sudocode/__tests__/tools.test.ts +0 -471
  326. package/src/task/backend/sudocode/backend.ts +0 -1237
  327. package/src/task/backend/sudocode/client.ts +0 -515
  328. package/src/task/backend/sudocode/index.ts +0 -120
  329. package/src/task/backend/sudocode/mapping.ts +0 -93
  330. package/src/task/backend/sudocode/server-client.ts +0 -522
  331. package/src/task/backend/sudocode/standalone-client.ts +0 -623
  332. package/src/task/backend/sudocode/sync-policy.ts +0 -387
  333. package/src/task/backend/sudocode/tools.ts +0 -896
  334. package/src/task/backend/tool-provider.ts +0 -506
  335. package/test_fixtures/fixtures/sudocode/index.ts +0 -29
  336. package/test_fixtures/fixtures/sudocode/issues.ts +0 -185
  337. package/test_fixtures/fixtures/sudocode/specs.ts +0 -159
@@ -1,896 +0,0 @@
1
- /**
2
- * Sudocode Task Tool Provider
3
- *
4
- * Provides MCP tools for task operations using SudocodeTaskBackend.
5
- * Supports native sudocode tools, mapped task tools, or both.
6
- *
7
- * @module task/backend/sudocode/tools
8
- * @see s-8472 Pluggable Task Backend Integration with Sudocode
9
- * @see i-185b 7B.4: Implement SudocodeTaskToolProvider
10
- */
11
-
12
- import type { AgentId } from "../../../store/types/index.js";
13
- import type {
14
- TaskToolProvider,
15
- MCPToolDefinition,
16
- TaskFilter,
17
- TaskStatus,
18
- } from "../types.js";
19
- import type { SudocodeTaskBackend } from "./backend.js";
20
- import type { SudocodeClient, ListIssuesOptions } from "./client.js";
21
-
22
- // =============================================================================
23
- // Types
24
- // =============================================================================
25
-
26
- /**
27
- * Tool mode for SudocodeTaskToolProvider
28
- *
29
- * - `native`: Expose sudocode's native issue tools (default)
30
- * - `mapped`: Expose generic task tools that map to backend operations
31
- * - `both`: Expose both native and mapped tools
32
- */
33
- export type TaskToolMode = "native" | "mapped" | "both";
34
-
35
- /**
36
- * Context needed for tool execution
37
- */
38
- export interface SudocodeToolContext {
39
- /** The agent making the tool call */
40
- agent_id: AgentId;
41
- }
42
-
43
- /**
44
- * Factory function type for getting context
45
- */
46
- export type GetSudocodeToolContext = () => SudocodeToolContext;
47
-
48
- /**
49
- * Configuration for SudocodeTaskToolProvider
50
- */
51
- export interface SudocodeTaskToolProviderConfig {
52
- /** Tool mode (default: 'native') */
53
- mode?: TaskToolMode;
54
- }
55
-
56
- // =============================================================================
57
- // Native Tool Names (for exclusion)
58
- // =============================================================================
59
-
60
- const NATIVE_TOOL_NAMES = [
61
- "upsert_issue",
62
- "show_issue",
63
- "list_issues",
64
- "ready",
65
- "link",
66
- "add_feedback",
67
- ];
68
-
69
- const MAPPED_TOOL_NAMES = [
70
- "create_task",
71
- "get_task",
72
- "list_tasks",
73
- "list_ready_tasks",
74
- "get_task_blockers",
75
- "update_task_status",
76
- "add_blocker",
77
- "remove_blocker",
78
- "assign_task",
79
- "complete_task",
80
- ];
81
-
82
- // =============================================================================
83
- // SudocodeTaskToolProvider
84
- // =============================================================================
85
-
86
- /**
87
- * SudocodeTaskToolProvider
88
- *
89
- * Provides MCP tools for sudocode-backed task operations.
90
- * Supports multiple modes:
91
- * - `native`: Exposes sudocode's native issue tools (upsert_issue, show_issue, etc.)
92
- * - `mapped`: Exposes generic task tools that map to backend operations
93
- * - `both`: Exposes all tools from both modes
94
- */
95
- export class SudocodeTaskToolProvider implements TaskToolProvider {
96
- private readonly mode: TaskToolMode;
97
-
98
- constructor(
99
- private readonly backend: SudocodeTaskBackend,
100
- private readonly client: SudocodeClient,
101
- private readonly getContext: GetSudocodeToolContext,
102
- config?: SudocodeTaskToolProviderConfig
103
- ) {
104
- this.mode = config?.mode ?? "native";
105
- }
106
-
107
- /**
108
- * Get the MCP tools based on the configured mode
109
- */
110
- getTools(): MCPToolDefinition[] {
111
- if (this.mode === "native") {
112
- return this.getNativeTools();
113
- } else if (this.mode === "mapped") {
114
- return this.getMappedTools();
115
- } else {
116
- return [...this.getNativeTools(), ...this.getMappedTools()];
117
- }
118
- }
119
-
120
- /**
121
- * Get tools that should be excluded when this provider is active
122
- */
123
- getExcludedTools(): string[] {
124
- if (this.mode === "native") {
125
- // When using native tools, exclude generic task tools
126
- return MAPPED_TOOL_NAMES;
127
- } else if (this.mode === "mapped") {
128
- // When using mapped tools, exclude native sudocode tools
129
- return NATIVE_TOOL_NAMES;
130
- }
131
- // In 'both' mode, don't exclude anything
132
- return [];
133
- }
134
-
135
- // ─────────────────────────────────────────────────────────────────────────────
136
- // Native Sudocode Tools
137
- // ─────────────────────────────────────────────────────────────────────────────
138
-
139
- private getNativeTools(): MCPToolDefinition[] {
140
- return [
141
- this.upsertIssueTool(),
142
- this.showIssueTool(),
143
- this.listIssuesTool(),
144
- this.readyTool(),
145
- this.linkTool(),
146
- this.addFeedbackTool(),
147
- ];
148
- }
149
-
150
- private upsertIssueTool(): MCPToolDefinition {
151
- return {
152
- name: "upsert_issue",
153
- description: "Create or update a sudocode issue",
154
- schema: {
155
- type: "object",
156
- properties: {
157
- issue_id: {
158
- type: "string",
159
- description:
160
- "Issue ID (e.g., 'i-abc123'). Omit to create new issue.",
161
- },
162
- title: {
163
- type: "string",
164
- description: "Issue title (required when creating)",
165
- },
166
- content: {
167
- type: "string",
168
- description: "Issue content/description in markdown",
169
- },
170
- status: {
171
- type: "string",
172
- enum: ["open", "in_progress", "blocked", "closed"],
173
- description: "Issue status",
174
- },
175
- priority: {
176
- type: "number",
177
- minimum: 0,
178
- maximum: 4,
179
- description: "Priority (0=highest, 4=lowest)",
180
- },
181
- assignee: {
182
- type: "string",
183
- description: "Assignee identifier",
184
- },
185
- },
186
- },
187
- handler: async (params: unknown) => {
188
- const args = params as {
189
- issue_id?: string;
190
- title?: string;
191
- content?: string;
192
- status?: "open" | "in_progress" | "blocked" | "closed";
193
- priority?: number;
194
- assignee?: string;
195
- };
196
-
197
- if (!args.issue_id) {
198
- // Creating new issue - title is required
199
- if (!args.title) {
200
- throw new Error("title is required when creating a new issue");
201
- }
202
- }
203
-
204
- const issue = await this.client.updateIssue(
205
- args.issue_id ?? `i-new-${Date.now()}`,
206
- {
207
- title: args.title,
208
- content: args.content,
209
- status: args.status,
210
- priority: args.priority,
211
- assignee: args.assignee,
212
- }
213
- );
214
-
215
- return {
216
- id: issue.id,
217
- title: issue.title,
218
- status: issue.status,
219
- updated: true,
220
- };
221
- },
222
- };
223
- }
224
-
225
- private showIssueTool(): MCPToolDefinition {
226
- return {
227
- name: "show_issue",
228
- description: "Get details of a specific issue",
229
- schema: {
230
- type: "object",
231
- properties: {
232
- issue_id: {
233
- type: "string",
234
- description: "Issue ID (e.g., 'i-abc123')",
235
- },
236
- },
237
- required: ["issue_id"],
238
- },
239
- handler: async (params: unknown) => {
240
- const args = params as { issue_id: string };
241
-
242
- const issue = await this.client.getIssue(args.issue_id);
243
- if (!issue) {
244
- throw new Error(`Issue not found: ${args.issue_id}`);
245
- }
246
-
247
- return {
248
- id: issue.id,
249
- title: issue.title,
250
- content: issue.content,
251
- status: issue.status,
252
- priority: issue.priority,
253
- assignee: issue.assignee,
254
- created_at: issue.created_at,
255
- updated_at: issue.updated_at,
256
- };
257
- },
258
- };
259
- }
260
-
261
- private listIssuesTool(): MCPToolDefinition {
262
- return {
263
- name: "list_issues",
264
- description: "List and filter issues",
265
- schema: {
266
- type: "object",
267
- properties: {
268
- status: {
269
- type: "string",
270
- enum: ["open", "in_progress", "blocked", "closed"],
271
- description: "Filter by status",
272
- },
273
- priority: {
274
- type: "number",
275
- minimum: 0,
276
- maximum: 4,
277
- description: "Filter by priority",
278
- },
279
- search: {
280
- type: "string",
281
- description: "Search text in title/content",
282
- },
283
- archived: {
284
- type: "boolean",
285
- description: "Include archived issues (default: false)",
286
- },
287
- limit: {
288
- type: "number",
289
- description: "Maximum results (default: 50)",
290
- },
291
- },
292
- },
293
- handler: async (params: unknown) => {
294
- const args = params as ListIssuesOptions;
295
-
296
- const issues = await this.client.listIssues(args);
297
-
298
- return {
299
- issues: issues.map((issue) => ({
300
- id: issue.id,
301
- title: issue.title,
302
- status: issue.status,
303
- priority: issue.priority,
304
- })),
305
- total: issues.length,
306
- };
307
- },
308
- };
309
- }
310
-
311
- private readyTool(): MCPToolDefinition {
312
- return {
313
- name: "ready",
314
- description: "Get issues that are ready to work on (no blockers)",
315
- schema: {
316
- type: "object",
317
- properties: {},
318
- },
319
- handler: async () => {
320
- const issues = await this.client.getReadyIssues();
321
-
322
- return {
323
- issues: issues.map((issue) => ({
324
- id: issue.id,
325
- title: issue.title,
326
- status: issue.status,
327
- priority: issue.priority,
328
- })),
329
- total: issues.length,
330
- };
331
- },
332
- };
333
- }
334
-
335
- private linkTool(): MCPToolDefinition {
336
- return {
337
- name: "link",
338
- description: "Create a relationship between issues or specs",
339
- schema: {
340
- type: "object",
341
- properties: {
342
- from_id: {
343
- type: "string",
344
- description: "Source entity ID (issue or spec)",
345
- },
346
- to_id: {
347
- type: "string",
348
- description: "Target entity ID (issue or spec)",
349
- },
350
- type: {
351
- type: "string",
352
- enum: [
353
- "blocks",
354
- "implements",
355
- "references",
356
- "depends-on",
357
- "discovered-from",
358
- "related",
359
- ],
360
- description: "Relationship type",
361
- },
362
- },
363
- required: ["from_id", "to_id", "type"],
364
- },
365
- handler: async (params: unknown) => {
366
- const args = params as {
367
- from_id: string;
368
- to_id: string;
369
- type:
370
- | "blocks"
371
- | "implements"
372
- | "references"
373
- | "depends-on"
374
- | "discovered-from"
375
- | "related";
376
- };
377
-
378
- await this.client.createLink(args.from_id, args.to_id, args.type);
379
-
380
- return {
381
- from_id: args.from_id,
382
- to_id: args.to_id,
383
- type: args.type,
384
- created: true,
385
- };
386
- },
387
- };
388
- }
389
-
390
- private addFeedbackTool(): MCPToolDefinition {
391
- return {
392
- name: "add_feedback",
393
- description: "Add feedback to a spec or issue",
394
- schema: {
395
- type: "object",
396
- properties: {
397
- to_id: {
398
- type: "string",
399
- description: "Target spec or issue ID",
400
- },
401
- issue_id: {
402
- type: "string",
403
- description: "Issue providing the feedback (optional)",
404
- },
405
- type: {
406
- type: "string",
407
- enum: ["comment", "suggestion", "request"],
408
- description: "Feedback type",
409
- },
410
- content: {
411
- type: "string",
412
- description: "Feedback content in markdown",
413
- },
414
- line: {
415
- type: "number",
416
- description: "Line number to anchor feedback",
417
- },
418
- text: {
419
- type: "string",
420
- description: "Text to anchor feedback to",
421
- },
422
- },
423
- required: ["to_id", "content"],
424
- },
425
- handler: async (params: unknown) => {
426
- const args = params as {
427
- to_id: string;
428
- issue_id?: string;
429
- type?: "comment" | "suggestion" | "request";
430
- content: string;
431
- line?: number;
432
- text?: string;
433
- };
434
-
435
- await this.client.addFeedback(args.issue_id, args.to_id, {
436
- type: args.type ?? "comment",
437
- content: args.content,
438
- anchor:
439
- args.line || args.text
440
- ? { line: args.line, text: args.text }
441
- : undefined,
442
- });
443
-
444
- return {
445
- to_id: args.to_id,
446
- added: true,
447
- };
448
- },
449
- };
450
- }
451
-
452
- // ─────────────────────────────────────────────────────────────────────────────
453
- // Mapped Task Tools
454
- // ─────────────────────────────────────────────────────────────────────────────
455
-
456
- private getMappedTools(): MCPToolDefinition[] {
457
- return [
458
- this.createTaskTool(),
459
- this.getTaskTool(),
460
- this.listTasksTool(),
461
- this.listReadyTasksTool(),
462
- this.getTaskBlockersTool(),
463
- this.updateTaskStatusTool(),
464
- this.addBlockerTool(),
465
- this.removeBlockerTool(),
466
- this.assignTaskTool(),
467
- this.completeTaskTool(),
468
- ];
469
- }
470
-
471
- private createTaskTool(): MCPToolDefinition {
472
- return {
473
- name: "create_task",
474
- description: "Create a new task (optionally bound to a sudocode issue)",
475
- schema: {
476
- type: "object",
477
- properties: {
478
- description: {
479
- type: "string",
480
- description: "Task description",
481
- },
482
- parent_task: {
483
- type: "string",
484
- description: "Parent task ID for subtasks",
485
- },
486
- external_id: {
487
- type: "string",
488
- description: "Sudocode issue ID to bind to",
489
- },
490
- },
491
- required: ["description"],
492
- },
493
- handler: async (params: unknown) => {
494
- const args = params as {
495
- description: string;
496
- parent_task?: string;
497
- external_id?: string;
498
- };
499
- const context = this.getContext();
500
-
501
- const task = await this.backend.create({
502
- description: args.description,
503
- created_by: context.agent_id,
504
- parent_task: args.parent_task,
505
- external_id: args.external_id,
506
- });
507
-
508
- return {
509
- task_id: task.id,
510
- status: task.status,
511
- external_id: task.external_id,
512
- created_at: task.created_at,
513
- };
514
- },
515
- };
516
- }
517
-
518
- private getTaskTool(): MCPToolDefinition {
519
- return {
520
- name: "get_task",
521
- description: "Get details of a specific task",
522
- schema: {
523
- type: "object",
524
- properties: {
525
- task_id: {
526
- type: "string",
527
- description: "Task ID",
528
- },
529
- },
530
- required: ["task_id"],
531
- },
532
- handler: async (params: unknown) => {
533
- const args = params as { task_id: string };
534
-
535
- const task = await this.backend.get(args.task_id);
536
- if (!task) {
537
- throw new Error(`Task not found: ${args.task_id}`);
538
- }
539
-
540
- return {
541
- id: task.id,
542
- description: task.description,
543
- status: task.status,
544
- isBlocked: task.isBlocked,
545
- external_id: task.external_id,
546
- assigned_agent: task.assigned_agent,
547
- parent_task: task.parent_task,
548
- blockers: task.blockers ?? [],
549
- created_at: task.created_at,
550
- started_at: task.started_at,
551
- completed_at: task.completed_at,
552
- };
553
- },
554
- };
555
- }
556
-
557
- private listTasksTool(): MCPToolDefinition {
558
- return {
559
- name: "list_tasks",
560
- description: "List tasks with optional filtering",
561
- schema: {
562
- type: "object",
563
- properties: {
564
- status: {
565
- type: "string",
566
- enum: ["pending", "assigned", "in_progress", "completed", "failed"],
567
- description: "Filter by task status",
568
- },
569
- assigned_agent: {
570
- type: "string",
571
- description: "Filter by assigned agent",
572
- },
573
- parent_task: {
574
- type: "string",
575
- description: "Filter by parent task",
576
- },
577
- root_only: {
578
- type: "boolean",
579
- description: "Only return root tasks (no parent)",
580
- },
581
- include_blocked: {
582
- type: "boolean",
583
- description: "Include blocked tasks (default: true)",
584
- },
585
- },
586
- },
587
- handler: async (params: unknown) => {
588
- const args = params as {
589
- status?: TaskStatus;
590
- assigned_agent?: string;
591
- parent_task?: string;
592
- root_only?: boolean;
593
- include_blocked?: boolean;
594
- };
595
-
596
- const filter: TaskFilter = {};
597
- if (args.status) filter.status = args.status;
598
- if (args.assigned_agent) filter.assigned_agent = args.assigned_agent;
599
- if (args.parent_task) filter.parent_task = args.parent_task;
600
- if (args.root_only) filter.rootTasksOnly = true;
601
- if (args.include_blocked !== undefined)
602
- filter.includeBlocked = args.include_blocked;
603
-
604
- const tasks = await this.backend.list(filter);
605
-
606
- return {
607
- tasks: tasks.map((t) => ({
608
- id: t.id,
609
- description: t.description,
610
- status: t.status,
611
- isBlocked: t.isBlocked,
612
- external_id: t.external_id,
613
- assigned_agent: t.assigned_agent,
614
- })),
615
- total: tasks.length,
616
- };
617
- },
618
- };
619
- }
620
-
621
- private listReadyTasksTool(): MCPToolDefinition {
622
- return {
623
- name: "list_ready_tasks",
624
- description:
625
- "List tasks that are ready to work on (pending/assigned, no blockers)",
626
- schema: {
627
- type: "object",
628
- properties: {
629
- assigned_agent: {
630
- type: "string",
631
- description: "Filter by assigned agent",
632
- },
633
- parent_task: {
634
- type: "string",
635
- description: "Filter by parent task",
636
- },
637
- },
638
- },
639
- handler: async (params: unknown) => {
640
- const args = params as {
641
- assigned_agent?: string;
642
- parent_task?: string;
643
- };
644
-
645
- const filter: TaskFilter = {};
646
- if (args.assigned_agent) filter.assigned_agent = args.assigned_agent;
647
- if (args.parent_task) filter.parent_task = args.parent_task;
648
-
649
- const tasks = await this.backend.listReady(filter);
650
-
651
- return {
652
- tasks: tasks.map((t) => ({
653
- id: t.id,
654
- description: t.description,
655
- status: t.status,
656
- external_id: t.external_id,
657
- assigned_agent: t.assigned_agent,
658
- })),
659
- total: tasks.length,
660
- };
661
- },
662
- };
663
- }
664
-
665
- private getTaskBlockersTool(): MCPToolDefinition {
666
- return {
667
- name: "get_task_blockers",
668
- description: "Get tasks that block a specific task",
669
- schema: {
670
- type: "object",
671
- properties: {
672
- task_id: {
673
- type: "string",
674
- description: "Task ID",
675
- },
676
- },
677
- required: ["task_id"],
678
- },
679
- handler: async (params: unknown) => {
680
- const args = params as { task_id: string };
681
-
682
- const blockers = await this.backend.getBlockers(args.task_id);
683
-
684
- return {
685
- task_id: args.task_id,
686
- blockers: blockers.map((t) => ({
687
- id: t.id,
688
- description: t.description,
689
- status: t.status,
690
- isCompleted: t.status === "completed",
691
- })),
692
- isBlocked: blockers.some((t) => t.status !== "completed"),
693
- };
694
- },
695
- };
696
- }
697
-
698
- private updateTaskStatusTool(): MCPToolDefinition {
699
- return {
700
- name: "update_task_status",
701
- description: "Update the status of a task",
702
- schema: {
703
- type: "object",
704
- properties: {
705
- task_id: {
706
- type: "string",
707
- description: "Task ID",
708
- },
709
- status: {
710
- type: "string",
711
- enum: ["pending", "assigned", "in_progress", "completed", "failed"],
712
- description: "New status",
713
- },
714
- },
715
- required: ["task_id", "status"],
716
- },
717
- handler: async (params: unknown) => {
718
- const args = params as { task_id: string; status: TaskStatus };
719
-
720
- const task = await this.backend.update(args.task_id, {
721
- status: args.status,
722
- });
723
-
724
- return {
725
- task_id: task.id,
726
- status: task.status,
727
- updated: true,
728
- };
729
- },
730
- };
731
- }
732
-
733
- private addBlockerTool(): MCPToolDefinition {
734
- return {
735
- name: "add_blocker",
736
- description: "Add a blocking dependency to a task",
737
- schema: {
738
- type: "object",
739
- properties: {
740
- task_id: {
741
- type: "string",
742
- description: "Task that will be blocked",
743
- },
744
- blocker_id: {
745
- type: "string",
746
- description: "Task that blocks the first task",
747
- },
748
- },
749
- required: ["task_id", "blocker_id"],
750
- },
751
- handler: async (params: unknown) => {
752
- const args = params as { task_id: string; blocker_id: string };
753
-
754
- await this.backend.addBlocker(args.task_id, args.blocker_id);
755
-
756
- return {
757
- task_id: args.task_id,
758
- blocker_id: args.blocker_id,
759
- added: true,
760
- };
761
- },
762
- };
763
- }
764
-
765
- private removeBlockerTool(): MCPToolDefinition {
766
- return {
767
- name: "remove_blocker",
768
- description: "Remove a blocking dependency from a task",
769
- schema: {
770
- type: "object",
771
- properties: {
772
- task_id: {
773
- type: "string",
774
- description: "Task to remove blocker from",
775
- },
776
- blocker_id: {
777
- type: "string",
778
- description: "Blocker task to remove",
779
- },
780
- },
781
- required: ["task_id", "blocker_id"],
782
- },
783
- handler: async (params: unknown) => {
784
- const args = params as { task_id: string; blocker_id: string };
785
-
786
- await this.backend.removeBlocker(args.task_id, args.blocker_id);
787
-
788
- return {
789
- task_id: args.task_id,
790
- blocker_id: args.blocker_id,
791
- removed: true,
792
- };
793
- },
794
- };
795
- }
796
-
797
- private assignTaskTool(): MCPToolDefinition {
798
- return {
799
- name: "assign_task",
800
- description: "Assign a task to an agent",
801
- schema: {
802
- type: "object",
803
- properties: {
804
- task_id: {
805
- type: "string",
806
- description: "Task ID",
807
- },
808
- agent_id: {
809
- type: "string",
810
- description: "Agent ID (defaults to calling agent)",
811
- },
812
- role: {
813
- type: "string",
814
- description: "Optional role for the assignment",
815
- },
816
- },
817
- required: ["task_id"],
818
- },
819
- handler: async (params: unknown) => {
820
- const args = params as {
821
- task_id: string;
822
- agent_id?: string;
823
- role?: string;
824
- };
825
- const context = this.getContext();
826
-
827
- const agentId = args.agent_id ?? context.agent_id;
828
- await this.backend.assign(args.task_id, agentId, { role: args.role });
829
-
830
- return {
831
- task_id: args.task_id,
832
- assigned_agent: agentId,
833
- assigned: true,
834
- };
835
- },
836
- };
837
- }
838
-
839
- private completeTaskTool(): MCPToolDefinition {
840
- return {
841
- name: "complete_task",
842
- description: "Mark a task as completed with optional outputs",
843
- schema: {
844
- type: "object",
845
- properties: {
846
- task_id: {
847
- type: "string",
848
- description: "Task ID",
849
- },
850
- summary: {
851
- type: "string",
852
- description: "Summary of work done",
853
- },
854
- outputs: {
855
- type: "object",
856
- description: "Output data from the task",
857
- },
858
- },
859
- required: ["task_id"],
860
- },
861
- handler: async (params: unknown) => {
862
- const args = params as {
863
- task_id: string;
864
- summary?: string;
865
- outputs?: Record<string, unknown>;
866
- };
867
-
868
- await this.backend.complete(args.task_id, {
869
- summary: args.summary,
870
- data: args.outputs,
871
- });
872
-
873
- return {
874
- task_id: args.task_id,
875
- completed: true,
876
- };
877
- },
878
- };
879
- }
880
- }
881
-
882
- // =============================================================================
883
- // Factory Function
884
- // =============================================================================
885
-
886
- /**
887
- * Create a SudocodeTaskToolProvider
888
- */
889
- export function createSudocodeTaskToolProvider(
890
- backend: SudocodeTaskBackend,
891
- client: SudocodeClient,
892
- getContext: GetSudocodeToolContext,
893
- config?: SudocodeTaskToolProviderConfig
894
- ): SudocodeTaskToolProvider {
895
- return new SudocodeTaskToolProvider(backend, client, getContext, config);
896
- }