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
@@ -1,345 +0,0 @@
1
- /**
2
- * SudocodeClient Interface Tests
3
- *
4
- * Tests for the SudocodeClient interface types and factory function.
5
- */
6
-
7
- import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
8
- import {
9
- checkServerHealth,
10
- createSudocodeClient,
11
- DEFAULT_CLIENT_CONFIG,
12
- type SudocodeClientConfig,
13
- type SudocodeClient,
14
- type IssueChangeEvent,
15
- } from "../client.js";
16
-
17
- // Mock fetch for server health checks
18
- const mockFetch = vi.fn();
19
- vi.stubGlobal("fetch", mockFetch);
20
-
21
- // Mock WebSocket
22
- class MockWebSocket {
23
- static instances: MockWebSocket[] = [];
24
- onopen: (() => void) | null = null;
25
- onclose: (() => void) | null = null;
26
- onerror: ((error: unknown) => void) | null = null;
27
- onmessage: ((event: { data: string }) => void) | null = null;
28
-
29
- constructor(public url: string) {
30
- MockWebSocket.instances.push(this);
31
- // Simulate async connection
32
- setTimeout(() => {
33
- if (this.onopen) this.onopen();
34
- }, 0);
35
- }
36
-
37
- close() {
38
- // Simulate close
39
- }
40
-
41
- static clearInstances() {
42
- MockWebSocket.instances = [];
43
- }
44
- }
45
-
46
- vi.stubGlobal("WebSocket", MockWebSocket);
47
-
48
- describe("SudocodeClient", () => {
49
- beforeEach(() => {
50
- vi.clearAllMocks();
51
- MockWebSocket.clearInstances();
52
- });
53
-
54
- afterEach(() => {
55
- vi.restoreAllMocks();
56
- });
57
-
58
- describe("DEFAULT_CLIENT_CONFIG", () => {
59
- it("should have expected default values", () => {
60
- expect(DEFAULT_CLIENT_CONFIG.serverUrl).toBe("http://localhost:3001");
61
- expect(DEFAULT_CLIENT_CONFIG.wsUrl).toBe("ws://localhost:3001/ws");
62
- expect(DEFAULT_CLIENT_CONFIG.autoDetect.timeout).toBe(2000);
63
- expect(DEFAULT_CLIENT_CONFIG.autoDetect.preferManaged).toBe(true);
64
- });
65
- });
66
-
67
- describe("checkServerHealth", () => {
68
- it("should return true when server responds with ok", async () => {
69
- mockFetch.mockResolvedValueOnce({ ok: true });
70
-
71
- const result = await checkServerHealth("http://localhost:3001");
72
-
73
- expect(result).toBe(true);
74
- expect(mockFetch).toHaveBeenCalledWith(
75
- "http://localhost:3001/health",
76
- expect.objectContaining({ signal: expect.any(AbortSignal) })
77
- );
78
- });
79
-
80
- it("should return false when server responds with error", async () => {
81
- mockFetch.mockResolvedValueOnce({ ok: false });
82
-
83
- const result = await checkServerHealth("http://localhost:3001");
84
-
85
- expect(result).toBe(false);
86
- });
87
-
88
- it("should return false when fetch throws", async () => {
89
- mockFetch.mockRejectedValueOnce(new Error("Connection refused"));
90
-
91
- const result = await checkServerHealth("http://localhost:3001");
92
-
93
- expect(result).toBe(false);
94
- });
95
-
96
- it("should return false when request times out", async () => {
97
- // Simulate timeout by never resolving
98
- mockFetch.mockImplementationOnce(
99
- () =>
100
- new Promise((_, reject) => {
101
- setTimeout(() => reject(new Error("Aborted")), 100);
102
- })
103
- );
104
-
105
- const result = await checkServerHealth("http://localhost:3001", 50);
106
-
107
- expect(result).toBe(false);
108
- });
109
- });
110
-
111
- describe("createSudocodeClient", () => {
112
- describe("managed mode", () => {
113
- it("should create a ServerClient in managed mode", async () => {
114
- const config: SudocodeClientConfig = {
115
- mode: "managed",
116
- serverUrl: "http://localhost:3001",
117
- };
118
-
119
- const client = await createSudocodeClient(config);
120
-
121
- try {
122
- // Verify client implements the interface
123
- expect(typeof client.getIssue).toBe("function");
124
- expect(typeof client.listIssues).toBe("function");
125
- expect(typeof client.getReadyIssues).toBe("function");
126
- expect(typeof client.updateIssue).toBe("function");
127
- expect(typeof client.createLink).toBe("function");
128
- expect(typeof client.removeLink).toBe("function");
129
- expect(typeof client.getBlockers).toBe("function");
130
- expect(typeof client.getBlocking).toBe("function");
131
- expect(typeof client.getSpec).toBe("function");
132
- expect(typeof client.listSpecs).toBe("function");
133
- expect(typeof client.addFeedback).toBe("function");
134
- expect(typeof client.onIssueChange).toBe("function");
135
- expect(typeof client.isReady).toBe("function");
136
- expect(typeof client.close).toBe("function");
137
-
138
- // Verify WebSocket was created with correct URL
139
- expect(MockWebSocket.instances).toHaveLength(1);
140
- expect(MockWebSocket.instances[0].url).toBe("ws://localhost:3001/ws");
141
- } finally {
142
- client.close();
143
- }
144
- });
145
-
146
- it("should use custom wsUrl if provided", async () => {
147
- const config: SudocodeClientConfig = {
148
- mode: "managed",
149
- serverUrl: "http://localhost:3001",
150
- wsUrl: "ws://custom.example.com/websocket",
151
- };
152
-
153
- const client = await createSudocodeClient(config);
154
-
155
- try {
156
- expect(MockWebSocket.instances).toHaveLength(1);
157
- expect(MockWebSocket.instances[0].url).toBe(
158
- "ws://custom.example.com/websocket"
159
- );
160
- } finally {
161
- client.close();
162
- }
163
- });
164
- });
165
-
166
- describe("standalone mode", () => {
167
- it("should create a StandaloneClient", async () => {
168
- // Create a temp directory for the test
169
- const { mkdtempSync, rmSync } = await import("fs");
170
- const { tmpdir } = await import("os");
171
- const { join } = await import("path");
172
- const tmpDir = mkdtempSync(join(tmpdir(), "sudocode-client-test-"));
173
-
174
- try {
175
- const config: SudocodeClientConfig = {
176
- mode: "standalone",
177
- projectPath: tmpDir,
178
- };
179
-
180
- const client = await createSudocodeClient(config);
181
-
182
- try {
183
- expect(client.isReady()).toBe(true);
184
- expect(typeof client.getIssue).toBe("function");
185
- expect(typeof client.listIssues).toBe("function");
186
- } finally {
187
- client.close();
188
- }
189
- } finally {
190
- rmSync(tmpDir, { recursive: true, force: true });
191
- }
192
- });
193
- });
194
-
195
- describe("auto mode", () => {
196
- it("should use managed mode when server is available and preferManaged is true", async () => {
197
- mockFetch.mockResolvedValueOnce({ ok: true });
198
-
199
- const config: SudocodeClientConfig = {
200
- mode: "auto",
201
- autoDetect: { preferManaged: true },
202
- };
203
-
204
- const client = await createSudocodeClient(config);
205
-
206
- try {
207
- expect(mockFetch).toHaveBeenCalled();
208
- // Should have created a ServerClient (WebSocket was created)
209
- expect(MockWebSocket.instances).toHaveLength(1);
210
- } finally {
211
- client.close();
212
- }
213
- });
214
-
215
- it("should fall back to standalone when server is unavailable", async () => {
216
- mockFetch.mockRejectedValueOnce(new Error("Connection refused"));
217
-
218
- // Create a temp directory for the test
219
- const { mkdtempSync, rmSync } = await import("fs");
220
- const { tmpdir } = await import("os");
221
- const { join } = await import("path");
222
- const tmpDir = mkdtempSync(join(tmpdir(), "sudocode-client-test-"));
223
-
224
- try {
225
- const config: SudocodeClientConfig = {
226
- mode: "auto",
227
- projectPath: tmpDir,
228
- };
229
-
230
- const client = await createSudocodeClient(config);
231
-
232
- try {
233
- expect(mockFetch).toHaveBeenCalled();
234
- // Should have fallen back to StandaloneClient (no WebSocket created)
235
- expect(MockWebSocket.instances).toHaveLength(0);
236
- expect(client.isReady()).toBe(true);
237
- } finally {
238
- client.close();
239
- }
240
- } finally {
241
- rmSync(tmpDir, { recursive: true, force: true });
242
- }
243
- });
244
-
245
- it("should use standalone when preferManaged is false", async () => {
246
- mockFetch.mockResolvedValueOnce({ ok: true });
247
-
248
- // Create a temp directory for the test
249
- const { mkdtempSync, rmSync } = await import("fs");
250
- const { tmpdir } = await import("os");
251
- const { join } = await import("path");
252
- const tmpDir = mkdtempSync(join(tmpdir(), "sudocode-client-test-"));
253
-
254
- try {
255
- const config: SudocodeClientConfig = {
256
- mode: "auto",
257
- autoDetect: { preferManaged: false },
258
- projectPath: tmpDir,
259
- };
260
-
261
- const client = await createSudocodeClient(config);
262
-
263
- try {
264
- // Should have used StandaloneClient despite server being available
265
- expect(MockWebSocket.instances).toHaveLength(0);
266
- expect(client.isReady()).toBe(true);
267
- } finally {
268
- client.close();
269
- }
270
- } finally {
271
- rmSync(tmpDir, { recursive: true, force: true });
272
- }
273
- });
274
- });
275
- });
276
-
277
- describe("Type definitions", () => {
278
- it("should have correct IssueChangeEvent types", () => {
279
- // Type-level test: ensure the type is correctly defined
280
- const event: IssueChangeEvent = {
281
- type: "created",
282
- issueId: "i-abc123",
283
- issue: {
284
- id: "i-abc123",
285
- uuid: "uuid-123",
286
- title: "Test Issue",
287
- content: "Test content",
288
- status: "open",
289
- priority: 1,
290
- created_at: "2024-01-01T00:00:00Z",
291
- updated_at: "2024-01-01T00:00:00Z",
292
- },
293
- };
294
-
295
- expect(event.type).toBe("created");
296
- expect(event.issueId).toBe("i-abc123");
297
- });
298
-
299
- it("should support all IssueChangeType values", () => {
300
- const types: IssueChangeEvent["type"][] = [
301
- "created",
302
- "updated",
303
- "deleted",
304
- "status_changed",
305
- "blocked",
306
- "unblocked",
307
- ];
308
-
309
- expect(types).toHaveLength(6);
310
- });
311
- });
312
- });
313
-
314
- describe("SudocodeClient interface contract", () => {
315
- // These are type-level tests to ensure the interface is correctly defined
316
- // They don't actually run code but verify the type structure
317
-
318
- it("should define all required methods", () => {
319
- // This is a compile-time check - if the interface is wrong, TypeScript will error
320
- const methodNames: (keyof SudocodeClient)[] = [
321
- // Issue operations
322
- "getIssue",
323
- "listIssues",
324
- "getReadyIssues",
325
- "updateIssue",
326
- // Relationship operations
327
- "createLink",
328
- "removeLink",
329
- "getBlockers",
330
- "getBlocking",
331
- // Spec operations
332
- "getSpec",
333
- "listSpecs",
334
- // Feedback operations
335
- "addFeedback",
336
- // Event subscription
337
- "onIssueChange",
338
- // Lifecycle
339
- "isReady",
340
- "close",
341
- ];
342
-
343
- expect(methodNames).toHaveLength(14);
344
- });
345
- });