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
@@ -0,0 +1,652 @@
1
+ /**
2
+ * OpenTasks Client Interface
3
+ *
4
+ * Defines the client interface for communicating with the OpenTasks daemon.
5
+ * This abstracts over the IPC transport so the backend doesn't depend on
6
+ * opentasks internals.
7
+ *
8
+ * @module task/backend/opentasks/client
9
+ */
10
+
11
+ import { OpenTasksClient as OTClient } from "opentasks";
12
+
13
+ // =============================================================================
14
+ // OpenTasks Data Types (mirrored from opentasks schema)
15
+ // =============================================================================
16
+
17
+ /**
18
+ * OpenTasks issue node.
19
+ * Represents an actionable work item in the OpenTasks graph.
20
+ */
21
+ export interface OpenTasksIssue {
22
+ id: string;
23
+ uuid: string;
24
+ type: "task";
25
+ title: string;
26
+ content?: string;
27
+ status: string;
28
+ assignee?: string;
29
+ closed_at?: string;
30
+ priority?: number;
31
+ tags?: string[];
32
+ parent_id?: string;
33
+ created_at: string;
34
+ updated_at: string;
35
+ claimed_by?: string;
36
+ claimed_at?: string;
37
+ lock_until?: string;
38
+ archived?: boolean;
39
+ archived_at?: string;
40
+ metadata?: Record<string, unknown>;
41
+ source?: string;
42
+ branch?: string;
43
+ }
44
+
45
+ /**
46
+ * OpenTasks edge (relationship between nodes).
47
+ */
48
+ export interface OpenTasksEdge {
49
+ id: string;
50
+ uuid: string;
51
+ from_id: string;
52
+ to_id: string;
53
+ type: string;
54
+ created_at: string;
55
+ created_by?: string;
56
+ metadata?: Record<string, unknown>;
57
+ }
58
+
59
+ /**
60
+ * Reduced node summary from queries.
61
+ */
62
+ export interface OpenTasksNodeSummary {
63
+ id: string;
64
+ type: string;
65
+ title: string;
66
+ status?: string;
67
+ priority?: number;
68
+ archived: boolean;
69
+ }
70
+
71
+ // =============================================================================
72
+ // Client Configuration
73
+ // =============================================================================
74
+
75
+ /**
76
+ * Configuration for the OpenTasks client
77
+ */
78
+ export interface OpenTasksClientConfig {
79
+ /** Path to the daemon Unix socket */
80
+ socketPath?: string;
81
+
82
+ /** Auto-connect on first request (default: true) */
83
+ autoConnect?: boolean;
84
+
85
+ /** Request timeout in milliseconds (default: 30000) */
86
+ timeout?: number;
87
+ }
88
+
89
+ // =============================================================================
90
+ // Input Types
91
+ // =============================================================================
92
+
93
+ /**
94
+ * Input for creating a new issue in OpenTasks
95
+ */
96
+ export interface CreateIssueInput {
97
+ title: string;
98
+ content?: string;
99
+ status?: string;
100
+ assignee?: string;
101
+ priority?: number;
102
+ tags?: string[];
103
+ parent_id?: string;
104
+ metadata?: Record<string, unknown>;
105
+ }
106
+
107
+ /**
108
+ * Input for updating an issue in OpenTasks
109
+ */
110
+ export interface UpdateIssueInput {
111
+ title?: string;
112
+ content?: string;
113
+ status?: string;
114
+ assignee?: string | null;
115
+ priority?: number;
116
+ tags?: string[];
117
+ parent_id?: string | null;
118
+ archived?: boolean;
119
+ metadata?: Record<string, unknown>;
120
+ }
121
+
122
+ // =============================================================================
123
+ // Task Lifecycle Types (mirrors opentasks tools.task interface)
124
+ // =============================================================================
125
+
126
+ /**
127
+ * Semantic task actions supported by TaskManageable providers
128
+ */
129
+ export type TaskAction = "start" | "complete" | "block" | "reopen" | "close";
130
+
131
+ /**
132
+ * Parameters for the tools.task IPC method.
133
+ * Exactly one operation must be specified.
134
+ */
135
+ export interface TaskParams {
136
+ /** Transition a task's status using a semantic action */
137
+ transition?: {
138
+ /** Task ID or provider URI */
139
+ id: string;
140
+ /** Semantic action */
141
+ action: TaskAction;
142
+ };
143
+
144
+ /** Get tasks ready to work on (federated across TaskManageable providers) */
145
+ ready?: {
146
+ /** Only query these providers (by name). Omit to query all. */
147
+ providers?: string[];
148
+ /** Maximum results */
149
+ limit?: number;
150
+ /** Filter by tags */
151
+ tags?: string[];
152
+ /** Filter by minimum priority */
153
+ priority?: number;
154
+ /** Filter by assignee */
155
+ assignee?: string;
156
+ };
157
+
158
+ /** Assign a task to an owner */
159
+ assign?: {
160
+ /** Task ID or provider URI */
161
+ id: string;
162
+ /** Assignee identifier */
163
+ assignee: string;
164
+ };
165
+
166
+ /** Get valid next actions for a task in its current state */
167
+ validActions?: {
168
+ /** Task ID or provider URI */
169
+ id: string;
170
+ };
171
+
172
+ /** Return full objects instead of summaries (default: false) */
173
+ verbose?: boolean;
174
+ }
175
+
176
+ /**
177
+ * Result from tools.task operations
178
+ */
179
+ export interface TaskResult {
180
+ /** Whether the operation succeeded */
181
+ success: boolean;
182
+ /** Result data (shape depends on operation) */
183
+ data?: TaskTransitionData | TaskReadyData | TaskAssignData | TaskValidActionsData;
184
+ /** Error message if operation failed */
185
+ error?: string;
186
+ }
187
+
188
+ export interface TaskTransitionData {
189
+ type: "transition";
190
+ node: TaskNodeSummary;
191
+ provider: string;
192
+ action: string;
193
+ }
194
+
195
+ export interface TaskReadyData {
196
+ type: "ready";
197
+ items: TaskNodeSummary[];
198
+ total: number;
199
+ }
200
+
201
+ export interface TaskAssignData {
202
+ type: "assign";
203
+ node: TaskNodeSummary;
204
+ provider: string;
205
+ }
206
+
207
+ export interface TaskValidActionsData {
208
+ type: "validActions";
209
+ actions: string[];
210
+ }
211
+
212
+ /**
213
+ * Node summary returned by task operations
214
+ */
215
+ export interface TaskNodeSummary {
216
+ id: string;
217
+ type: string;
218
+ title: string;
219
+ status?: string;
220
+ priority?: number;
221
+ archived: boolean;
222
+ }
223
+
224
+ /**
225
+ * Provider summary from provider.list
226
+ */
227
+ export interface ProviderSummary {
228
+ name: string;
229
+ schemes: string[];
230
+ capabilities: Record<string, boolean>;
231
+ isDefault: boolean;
232
+ taskCapabilities?: {
233
+ actions: TaskAction[];
234
+ supportsAssignment: boolean;
235
+ supportsReadyQuery: boolean;
236
+ statusModel: string[];
237
+ };
238
+ }
239
+
240
+ // =============================================================================
241
+ // Event Types
242
+ // =============================================================================
243
+
244
+ /**
245
+ * Issue change event types
246
+ */
247
+ export type IssueChangeType =
248
+ | "created"
249
+ | "updated"
250
+ | "deleted"
251
+ | "status_changed";
252
+
253
+ /**
254
+ * Issue change event
255
+ */
256
+ export interface IssueChangeEvent {
257
+ type: IssueChangeType;
258
+ issueId: string;
259
+ issue?: OpenTasksIssue;
260
+ previousIssue?: OpenTasksIssue;
261
+ }
262
+
263
+ /**
264
+ * Callback for issue change events
265
+ */
266
+ export type IssueChangeCallback = (event: IssueChangeEvent) => void;
267
+
268
+ /**
269
+ * Unsubscribe function
270
+ */
271
+ export type ClientUnsubscribe = () => void;
272
+
273
+ // =============================================================================
274
+ // OpenTasksClient Interface
275
+ // =============================================================================
276
+
277
+ /**
278
+ * Client interface for interacting with the OpenTasks daemon.
279
+ *
280
+ * This defines only the operations needed by the macro-agent task backend.
281
+ * It can be implemented by:
282
+ * - The opentasks package's OpenTasksClient (when available)
283
+ * - A custom IPC client
284
+ * - A mock for testing
285
+ */
286
+ export interface OpenTasksClient {
287
+ // ─── Issue CRUD ──────────────────────────────────────────────
288
+
289
+ /** Create a new issue */
290
+ createIssue(input: CreateIssueInput): Promise<OpenTasksIssue>;
291
+
292
+ /** Get an issue by ID */
293
+ getIssue(id: string): Promise<OpenTasksIssue | null>;
294
+
295
+ /** Update an issue */
296
+ updateIssue(id: string, updates: UpdateIssueInput): Promise<OpenTasksIssue>;
297
+
298
+ /** Delete an issue (soft delete / archive) */
299
+ deleteIssue(id: string): Promise<void>;
300
+
301
+ /** List issues with optional filters */
302
+ listIssues(filter?: {
303
+ status?: string | string[];
304
+ assignee?: string;
305
+ tags?: string[];
306
+ parent_id?: string;
307
+ archived?: boolean;
308
+ limit?: number;
309
+ }): Promise<OpenTasksIssue[]>;
310
+
311
+ // ─── Ready / Claimable Queries ───────────────────────────────
312
+
313
+ /** Get issues that are ready to work on (no blocking dependencies) */
314
+ getReadyIssues(options?: {
315
+ tags?: string[];
316
+ assignee?: string;
317
+ limit?: number;
318
+ }): Promise<OpenTasksNodeSummary[]>;
319
+
320
+ // ─── Relationship Operations ─────────────────────────────────
321
+
322
+ /** Create an edge between two nodes */
323
+ createEdge(
324
+ fromId: string,
325
+ toId: string,
326
+ type: string
327
+ ): Promise<OpenTasksEdge>;
328
+
329
+ /** Remove an edge between two nodes */
330
+ removeEdge(
331
+ fromId: string,
332
+ toId: string,
333
+ type: string
334
+ ): Promise<void>;
335
+
336
+ /** Get nodes that block the given node */
337
+ getBlockers(nodeId: string): Promise<OpenTasksNodeSummary[]>;
338
+
339
+ /** Get nodes that the given node blocks */
340
+ getBlocking(nodeId: string): Promise<OpenTasksNodeSummary[]>;
341
+
342
+ // ─── Task Lifecycle (provider-agnostic via tools.task) ──────
343
+
344
+ /** Execute a task lifecycle operation (tools.task IPC) */
345
+ task(params: TaskParams): Promise<TaskResult>;
346
+
347
+ /** Transition a task's status using a semantic action */
348
+ taskTransition(id: string, action: TaskAction): Promise<TaskResult>;
349
+
350
+ /** Get tasks ready to work on across all TaskManageable providers */
351
+ taskReady(options?: TaskParams["ready"]): Promise<TaskResult>;
352
+
353
+ /** Assign a task to an owner */
354
+ taskAssign(id: string, assignee: string): Promise<TaskResult>;
355
+
356
+ /** Get valid next actions for a task in its current state */
357
+ taskValidActions(id: string): Promise<TaskResult>;
358
+
359
+ // ─── Provider Introspection ───────────────────────────────
360
+
361
+ /** List all registered providers and their capabilities */
362
+ listProviders(): Promise<ProviderSummary[]>;
363
+
364
+ // ─── Lifecycle ───────────────────────────────────────────────
365
+
366
+ /** Check if the client is connected */
367
+ isConnected(): boolean;
368
+
369
+ /** Connect to the daemon */
370
+ connect(): Promise<void>;
371
+
372
+ /** Disconnect from the daemon */
373
+ disconnect(): void;
374
+ }
375
+
376
+ // =============================================================================
377
+ // IPC-based Client Implementation
378
+ // =============================================================================
379
+
380
+ /**
381
+ * Default OpenTasks client implementation using the opentasks package.
382
+ *
383
+ * Wraps the opentasks client library to implement the OpenTasksClient interface.
384
+ */
385
+ export class IPCOpenTasksClient implements OpenTasksClient {
386
+ private client: any = null;
387
+ private readonly config: OpenTasksClientConfig;
388
+
389
+ constructor(config?: OpenTasksClientConfig) {
390
+ this.config = {
391
+ autoConnect: true,
392
+ timeout: 30000,
393
+ ...config,
394
+ };
395
+ }
396
+
397
+ async connect(): Promise<void> {
398
+ if (this.client?.connected) return;
399
+
400
+ try {
401
+ this.client = new OTClient({
402
+ socketPath: this.config.socketPath,
403
+ autoConnect: false,
404
+ timeout: this.config.timeout,
405
+ });
406
+ await this.client.connect();
407
+ } catch (error: any) {
408
+ throw new OpenTasksClientError(
409
+ `Failed to connect to OpenTasks daemon: ${error.message}`,
410
+ "CONNECTION_FAILED"
411
+ );
412
+ }
413
+ }
414
+
415
+ disconnect(): void {
416
+ if (this.client) {
417
+ this.client.disconnect();
418
+ this.client = null;
419
+ }
420
+ }
421
+
422
+ isConnected(): boolean {
423
+ return this.client?.connected ?? false;
424
+ }
425
+
426
+ private async ensureConnected(): Promise<void> {
427
+ if (this.isConnected()) return;
428
+ if (this.config.autoConnect) {
429
+ await this.connect();
430
+ return;
431
+ }
432
+ throw new OpenTasksClientError(
433
+ "Not connected to OpenTasks daemon",
434
+ "NOT_CONNECTED"
435
+ );
436
+ }
437
+
438
+ async createIssue(input: CreateIssueInput): Promise<OpenTasksIssue> {
439
+ await this.ensureConnected();
440
+ return this.client.createNode({
441
+ type: "task",
442
+ title: input.title,
443
+ content: input.content,
444
+ status: input.status ?? "open",
445
+ assignee: input.assignee,
446
+ priority: input.priority,
447
+ tags: input.tags,
448
+ parent_id: input.parent_id,
449
+ metadata: input.metadata,
450
+ }) as Promise<OpenTasksIssue>;
451
+ }
452
+
453
+ async getIssue(id: string): Promise<OpenTasksIssue | null> {
454
+ await this.ensureConnected();
455
+ try {
456
+ const node = await this.client.getNode(id);
457
+ if (!node || (node as any).type !== "task") return null;
458
+ return node as OpenTasksIssue;
459
+ } catch {
460
+ return null;
461
+ }
462
+ }
463
+
464
+ async updateIssue(
465
+ id: string,
466
+ updates: UpdateIssueInput
467
+ ): Promise<OpenTasksIssue> {
468
+ await this.ensureConnected();
469
+ return this.client.updateNode(id, updates) as Promise<OpenTasksIssue>;
470
+ }
471
+
472
+ async deleteIssue(id: string): Promise<void> {
473
+ await this.ensureConnected();
474
+ await this.client.deleteNode(id, { hard: false });
475
+ }
476
+
477
+ async listIssues(filter?: {
478
+ status?: string | string[];
479
+ assignee?: string;
480
+ tags?: string[];
481
+ parent_id?: string;
482
+ archived?: boolean;
483
+ limit?: number;
484
+ }): Promise<OpenTasksIssue[]> {
485
+ await this.ensureConnected();
486
+ const result = await this.client.query({
487
+ nodes: {
488
+ type: "task",
489
+ status: filter?.status,
490
+ assignee: filter?.assignee,
491
+ tags: filter?.tags,
492
+ parent_id: filter?.parent_id,
493
+ archived: filter?.archived ?? false,
494
+ limit: filter?.limit ?? 100,
495
+ },
496
+ verbose: true,
497
+ });
498
+ return (result.items ?? []) as OpenTasksIssue[];
499
+ }
500
+
501
+ async getReadyIssues(options?: {
502
+ tags?: string[];
503
+ assignee?: string;
504
+ limit?: number;
505
+ }): Promise<OpenTasksNodeSummary[]> {
506
+ await this.ensureConnected();
507
+ const result = await this.client.query({
508
+ ready: {
509
+ tags: options?.tags,
510
+ assignee: options?.assignee,
511
+ limit: options?.limit,
512
+ },
513
+ });
514
+ return (result.items ?? []) as OpenTasksNodeSummary[];
515
+ }
516
+
517
+ async createEdge(
518
+ fromId: string,
519
+ toId: string,
520
+ type: string
521
+ ): Promise<OpenTasksEdge> {
522
+ await this.ensureConnected();
523
+ const result = await this.client.link({
524
+ fromId,
525
+ toId,
526
+ type,
527
+ });
528
+ return {
529
+ id: result.edgeId ?? "",
530
+ uuid: "",
531
+ from_id: fromId,
532
+ to_id: toId,
533
+ type,
534
+ created_at: new Date().toISOString(),
535
+ };
536
+ }
537
+
538
+ async removeEdge(
539
+ fromId: string,
540
+ toId: string,
541
+ type: string
542
+ ): Promise<void> {
543
+ await this.ensureConnected();
544
+ await this.client.link({
545
+ fromId,
546
+ toId,
547
+ type,
548
+ remove: true,
549
+ });
550
+ }
551
+
552
+ async getBlockers(nodeId: string): Promise<OpenTasksNodeSummary[]> {
553
+ await this.ensureConnected();
554
+ const result = await this.client.query({
555
+ blockers: {
556
+ nodeId,
557
+ activeOnly: true,
558
+ },
559
+ });
560
+ return (result.items ?? []) as OpenTasksNodeSummary[];
561
+ }
562
+
563
+ async getBlocking(nodeId: string): Promise<OpenTasksNodeSummary[]> {
564
+ await this.ensureConnected();
565
+ const result = await this.client.query({
566
+ blocking: {
567
+ nodeId,
568
+ activeOnly: true,
569
+ },
570
+ });
571
+ return (result.items ?? []) as OpenTasksNodeSummary[];
572
+ }
573
+
574
+ // ─── Task Lifecycle (tools.task) ──────────────────────────────
575
+
576
+ async task(params: TaskParams): Promise<TaskResult> {
577
+ await this.ensureConnected();
578
+ return this.client.call("tools.task", params) as Promise<TaskResult>;
579
+ }
580
+
581
+ async taskTransition(id: string, action: TaskAction): Promise<TaskResult> {
582
+ return this.task({ transition: { id, action } });
583
+ }
584
+
585
+ async taskReady(options?: TaskParams["ready"]): Promise<TaskResult> {
586
+ return this.task({ ready: options ?? {} });
587
+ }
588
+
589
+ async taskAssign(id: string, assignee: string): Promise<TaskResult> {
590
+ return this.task({ assign: { id, assignee } });
591
+ }
592
+
593
+ async taskValidActions(id: string): Promise<TaskResult> {
594
+ return this.task({ validActions: { id } });
595
+ }
596
+
597
+ // ─── Provider Introspection ─────────────────────────────────
598
+
599
+ async listProviders(): Promise<ProviderSummary[]> {
600
+ await this.ensureConnected();
601
+ const result = await this.client.call("provider.list", {}) as {
602
+ providers: ProviderSummary[];
603
+ };
604
+ return result.providers ?? [];
605
+ }
606
+
607
+ // ─── Generic IPC Call ──────────────────────────────────────
608
+
609
+ async call(method: string, params: Record<string, unknown>): Promise<unknown> {
610
+ await this.ensureConnected();
611
+ return this.client.call(method, params);
612
+ }
613
+ }
614
+
615
+ // =============================================================================
616
+ // Error Types
617
+ // =============================================================================
618
+
619
+ /**
620
+ * Error thrown by OpenTasks client operations
621
+ */
622
+ export class OpenTasksClientError extends Error {
623
+ constructor(
624
+ message: string,
625
+ public readonly code:
626
+ | "NOT_CONNECTED"
627
+ | "CONNECTION_FAILED"
628
+ | "REQUEST_FAILED"
629
+ | "NOT_FOUND"
630
+ ) {
631
+ super(message);
632
+ this.name = "OpenTasksClientError";
633
+ }
634
+ }
635
+
636
+ // =============================================================================
637
+ // Factory
638
+ // =============================================================================
639
+
640
+ /**
641
+ * Create an OpenTasks client.
642
+ *
643
+ * @param config - Client configuration
644
+ * @returns An OpenTasksClient instance
645
+ */
646
+ export async function createOpenTasksClient(
647
+ config?: OpenTasksClientConfig
648
+ ): Promise<OpenTasksClient> {
649
+ const client = new IPCOpenTasksClient(config);
650
+ await client.connect();
651
+ return client;
652
+ }