macro-agent 0.0.17 → 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 (338) 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 +17 -0
  6. package/dist/acp/macro-agent.d.ts.map +1 -1
  7. package/dist/acp/macro-agent.js +183 -55
  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 +23 -0
  53. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  54. package/dist/map/adapter/acp-over-map.js +482 -55
  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 +4 -0
  95. package/dist/map/adapter/map-adapter.d.ts.map +1 -1
  96. package/dist/map/adapter/map-adapter.js +302 -30
  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 +7 -1
  131. package/dist/store/event-store.d.ts.map +1 -1
  132. package/dist/store/event-store.js +91 -8
  133. package/dist/store/event-store.js.map +1 -1
  134. package/dist/store/types/agents.d.ts +23 -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__/history.test.ts +8 -4
  197. package/src/acp/__tests__/integration.test.ts +56 -31
  198. package/src/acp/__tests__/macro-agent.test.ts +16 -7
  199. package/src/acp/macro-agent.ts +230 -62
  200. package/src/acp/types.ts +46 -1
  201. package/src/agent/__tests__/agent-manager.test.ts +228 -2
  202. package/src/agent/agent-manager.ts +714 -261
  203. package/src/agent/types.ts +3 -1
  204. package/src/api/server.ts +41 -7
  205. package/src/auth/__tests__/token.test.ts +100 -0
  206. package/src/auth/index.ts +1 -0
  207. package/src/auth/token.ts +82 -0
  208. package/src/cli/__tests__/acp.test.ts +1 -1
  209. package/src/cli/__tests__/stable-instance-id.test.ts +1 -1
  210. package/src/cli/acp.ts +130 -72
  211. package/src/cli/index.ts +120 -14
  212. package/src/cli/mcp.ts +311 -207
  213. package/src/cli/parse-args.ts +54 -0
  214. package/src/cli/stable-instance-id.ts +14 -0
  215. package/src/config/project-config.ts +190 -27
  216. package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
  217. package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +820 -0
  218. package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
  219. package/src/map/adapter/__tests__/acp-over-map-history.test.ts +724 -2
  220. package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +1 -1
  221. package/src/map/adapter/__tests__/event-broadcast.test.ts +420 -0
  222. package/src/map/adapter/__tests__/event-log.test.ts +527 -0
  223. package/src/map/adapter/__tests__/event-translator.test.ts +3 -3
  224. package/src/map/adapter/__tests__/extensions.test.ts +408 -0
  225. package/src/map/adapter/__tests__/map-adapter.test.ts +99 -0
  226. package/src/map/adapter/__tests__/mcp-bridge.test.ts +1187 -0
  227. package/src/map/adapter/__tests__/multi-client-broadcast.test.ts +711 -0
  228. package/src/map/adapter/__tests__/websocket-integration.test.ts +218 -0
  229. package/src/map/adapter/acp-over-map.ts +777 -92
  230. package/src/map/adapter/connection-manager.ts +3 -0
  231. package/src/map/adapter/event-log.ts +208 -0
  232. package/src/map/adapter/event-translator.ts +6 -6
  233. package/src/map/adapter/extensions/agent-lifecycle.ts +267 -0
  234. package/src/map/adapter/extensions/index.ts +60 -0
  235. package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
  236. package/src/map/adapter/extensions/task.ts +11 -0
  237. package/src/map/adapter/extensions/update-metadata.ts +126 -0
  238. package/src/map/adapter/index.ts +28 -0
  239. package/src/map/adapter/interface.ts +2 -0
  240. package/src/map/adapter/map-adapter.ts +373 -38
  241. package/src/map/adapter/subscription-manager.ts +5 -1
  242. package/src/map/adapter/types.ts +2 -0
  243. package/src/mcp/__tests__/map-client.test.ts +386 -0
  244. package/src/mcp/__tests__/mcp-server-thin-client.test.ts +368 -0
  245. package/src/mcp/__tests__/mcp-server.test.ts +100 -1
  246. package/src/mcp/map-client.ts +177 -0
  247. package/src/mcp/mcp-server.ts +191 -100
  248. package/src/mcp/types.ts +6 -1
  249. package/src/metrics/metrics.ts +1 -1
  250. package/src/monitor/__tests__/stale-agent-flow.integration.test.ts +1 -1
  251. package/src/roles/__tests__/config-loader.test.ts +7 -7
  252. package/src/roles/capabilities.ts +17 -7
  253. package/src/roles/config-loader.ts +6 -6
  254. package/src/roles/registry.ts +2 -2
  255. package/src/server/__tests__/combined-server.test.ts +94 -21
  256. package/src/server/combined-server.ts +189 -33
  257. package/src/steering/__tests__/steering-integration.test.ts +1 -1
  258. package/src/store/__tests__/event-store.test.ts +236 -1
  259. package/src/store/__tests__/instance.test.ts +3 -3
  260. package/src/store/event-store.ts +109 -8
  261. package/src/store/types/agents.ts +16 -0
  262. package/src/store/types/events.ts +1 -1
  263. package/src/task/backend/__tests__/create-task-backend.test.ts +225 -0
  264. package/src/task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test.ts +524 -0
  265. package/src/task/backend/__tests__/unified-tool-provider.test.ts +579 -0
  266. package/src/task/backend/index.ts +156 -106
  267. package/src/task/backend/memory.ts +4 -0
  268. package/src/task/backend/opentasks/__tests__/backend.test.ts +968 -0
  269. package/src/task/backend/opentasks/__tests__/daemon-manager.test.ts +406 -0
  270. package/src/task/backend/opentasks/__tests__/mapping.test.ts +84 -0
  271. package/src/task/backend/opentasks/__tests__/opentasks-backend.e2e.test.ts +1338 -0
  272. package/src/task/backend/opentasks/backend.ts +1323 -0
  273. package/src/task/backend/opentasks/client.ts +652 -0
  274. package/src/task/backend/opentasks/daemon-manager.ts +253 -0
  275. package/src/task/backend/opentasks/index.ts +69 -0
  276. package/src/task/backend/opentasks/mapping.ts +94 -0
  277. package/src/task/backend/types.ts +42 -66
  278. package/src/task/backend/unified-tool-provider.ts +779 -0
  279. package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
  280. package/src/teams/team-loader.ts +3 -3
  281. package/src/teams/team-runtime.ts +2 -0
  282. package/test_fixtures/README.md +2 -3
  283. package/test_fixtures/fixtures/index.ts +0 -3
  284. package/test_fixtures/fixtures/projects/project-with-specs.ts +7 -149
  285. package/test_fixtures/fixtures/repos/index.ts +1 -3
  286. package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -116
  287. package/test_fixtures/fixtures/repos/types.ts +0 -11
  288. package/test_fixtures/harness/__tests__/fixtures.test.ts +10 -102
  289. package/test_fixtures/harness/__tests__/temp-repo-and-simulator.test.ts +0 -33
  290. package/test_fixtures/harness/simulator/agent-simulator.ts +4 -4
  291. package/vitest.config.ts +1 -1
  292. package/vitest.e2e.config.ts +1 -1
  293. package/vitest.setup.ts +1 -30
  294. package/.macro-agent/teams/self-driving/prompts/grinder.md +0 -27
  295. package/.macro-agent/teams/self-driving/prompts/judge.md +0 -27
  296. package/.macro-agent/teams/self-driving/prompts/planner.md +0 -33
  297. package/.macro-agent/teams/self-driving/roles/grinder.yaml +0 -17
  298. package/.macro-agent/teams/self-driving/roles/judge.yaml +0 -24
  299. package/.macro-agent/teams/self-driving/roles/planner.yaml +0 -18
  300. package/.macro-agent/teams/self-driving/team.yaml +0 -103
  301. package/.macro-agent/teams/structured/prompts/developer.md +0 -26
  302. package/.macro-agent/teams/structured/prompts/lead.md +0 -25
  303. package/.macro-agent/teams/structured/prompts/reviewer.md +0 -24
  304. package/.macro-agent/teams/structured/roles/developer.yaml +0 -12
  305. package/.macro-agent/teams/structured/roles/lead.yaml +0 -11
  306. package/.macro-agent/teams/structured/roles/reviewer.yaml +0 -19
  307. package/.macro-agent/teams/structured/team.yaml +0 -89
  308. package/docs/sudocode-integration.md +0 -383
  309. package/src/task/backend/__tests__/backend-parity.test.ts +0 -451
  310. package/src/task/backend/__tests__/tool-provider-edge-cases.test.ts +0 -430
  311. package/src/task/backend/__tests__/tool-provider.test.ts +0 -983
  312. package/src/task/backend/sudocode/__tests__/backend-edge-cases.test.ts +0 -575
  313. package/src/task/backend/sudocode/__tests__/backend.test.ts +0 -1194
  314. package/src/task/backend/sudocode/__tests__/client-integration.test.ts +0 -418
  315. package/src/task/backend/sudocode/__tests__/client.test.ts +0 -345
  316. package/src/task/backend/sudocode/__tests__/e2e/backend.e2e.test.ts +0 -753
  317. package/src/task/backend/sudocode/__tests__/e2e/server-client.e2e.test.ts +0 -680
  318. package/src/task/backend/sudocode/__tests__/e2e-workflow.test.ts +0 -666
  319. package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts +0 -396
  320. package/src/task/backend/sudocode/__tests__/integration/sudocode-cli.integration.test.ts +0 -328
  321. package/src/task/backend/sudocode/__tests__/integration/test-utils.ts +0 -175
  322. package/src/task/backend/sudocode/__tests__/mapping-edge-cases.test.ts +0 -265
  323. package/src/task/backend/sudocode/__tests__/server-client.test.ts +0 -675
  324. package/src/task/backend/sudocode/__tests__/sync-policy-edge-cases.test.ts +0 -521
  325. package/src/task/backend/sudocode/__tests__/sync-policy.test.ts +0 -519
  326. package/src/task/backend/sudocode/__tests__/tools.test.ts +0 -471
  327. package/src/task/backend/sudocode/backend.ts +0 -1237
  328. package/src/task/backend/sudocode/client.ts +0 -515
  329. package/src/task/backend/sudocode/index.ts +0 -120
  330. package/src/task/backend/sudocode/mapping.ts +0 -93
  331. package/src/task/backend/sudocode/server-client.ts +0 -522
  332. package/src/task/backend/sudocode/standalone-client.ts +0 -623
  333. package/src/task/backend/sudocode/sync-policy.ts +0 -387
  334. package/src/task/backend/sudocode/tools.ts +0 -896
  335. package/src/task/backend/tool-provider.ts +0 -506
  336. package/test_fixtures/fixtures/sudocode/index.ts +0 -29
  337. package/test_fixtures/fixtures/sudocode/issues.ts +0 -185
  338. 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
+ }