macro-agent 0.0.11 → 0.0.12

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 (408) hide show
  1. package/.macro-agent/teams/self-driving/prompts/grinder.md +27 -0
  2. package/.macro-agent/teams/self-driving/prompts/judge.md +27 -0
  3. package/.macro-agent/teams/self-driving/prompts/planner.md +33 -0
  4. package/.macro-agent/teams/self-driving/roles/grinder.yaml +17 -0
  5. package/.macro-agent/teams/self-driving/roles/judge.yaml +24 -0
  6. package/.macro-agent/teams/self-driving/roles/planner.yaml +18 -0
  7. package/.macro-agent/teams/self-driving/team.yaml +103 -0
  8. package/.macro-agent/teams/structured/prompts/developer.md +26 -0
  9. package/.macro-agent/teams/structured/prompts/lead.md +25 -0
  10. package/.macro-agent/teams/structured/prompts/reviewer.md +24 -0
  11. package/.macro-agent/teams/structured/roles/developer.yaml +12 -0
  12. package/.macro-agent/teams/structured/roles/lead.yaml +11 -0
  13. package/.macro-agent/teams/structured/roles/reviewer.yaml +19 -0
  14. package/.macro-agent/teams/structured/team.yaml +89 -0
  15. package/.sudocode/issues.jsonl +6 -0
  16. package/.sudocode/specs.jsonl +7 -0
  17. package/CLAUDE.md +110 -30
  18. package/README.md +60 -3
  19. package/dist/acp/macro-agent.d.ts +4 -0
  20. package/dist/acp/macro-agent.d.ts.map +1 -1
  21. package/dist/acp/macro-agent.js +50 -4
  22. package/dist/acp/macro-agent.js.map +1 -1
  23. package/dist/acp/session-mapper.d.ts +20 -1
  24. package/dist/acp/session-mapper.d.ts.map +1 -1
  25. package/dist/acp/session-mapper.js +90 -1
  26. package/dist/acp/session-mapper.js.map +1 -1
  27. package/dist/acp/types.d.ts +24 -1
  28. package/dist/acp/types.d.ts.map +1 -1
  29. package/dist/acp/types.js.map +1 -1
  30. package/dist/agent/agent-manager.d.ts +25 -1
  31. package/dist/agent/agent-manager.d.ts.map +1 -1
  32. package/dist/agent/agent-manager.js +93 -7
  33. package/dist/agent/agent-manager.js.map +1 -1
  34. package/dist/agent/types.d.ts +22 -0
  35. package/dist/agent/types.d.ts.map +1 -1
  36. package/dist/agent/types.js.map +1 -1
  37. package/dist/agent-detection/command-builder.d.ts +30 -0
  38. package/dist/agent-detection/command-builder.d.ts.map +1 -0
  39. package/dist/agent-detection/command-builder.js +71 -0
  40. package/dist/agent-detection/command-builder.js.map +1 -0
  41. package/dist/agent-detection/detector.d.ts +84 -0
  42. package/dist/agent-detection/detector.d.ts.map +1 -0
  43. package/dist/agent-detection/detector.js +240 -0
  44. package/dist/agent-detection/detector.js.map +1 -0
  45. package/dist/agent-detection/index.d.ts +12 -0
  46. package/dist/agent-detection/index.d.ts.map +1 -0
  47. package/dist/agent-detection/index.js +14 -0
  48. package/dist/agent-detection/index.js.map +1 -0
  49. package/dist/agent-detection/registry.d.ts +53 -0
  50. package/dist/agent-detection/registry.d.ts.map +1 -0
  51. package/dist/agent-detection/registry.js +177 -0
  52. package/dist/agent-detection/registry.js.map +1 -0
  53. package/dist/agent-detection/types.d.ts +121 -0
  54. package/dist/agent-detection/types.d.ts.map +1 -0
  55. package/dist/agent-detection/types.js +20 -0
  56. package/dist/agent-detection/types.js.map +1 -0
  57. package/dist/api/server.d.ts.map +1 -1
  58. package/dist/api/server.js +95 -0
  59. package/dist/api/server.js.map +1 -1
  60. package/dist/cli/index.js +29 -0
  61. package/dist/cli/index.js.map +1 -1
  62. package/dist/cli/mcp.js +38 -0
  63. package/dist/cli/mcp.js.map +1 -1
  64. package/dist/config/index.d.ts +2 -0
  65. package/dist/config/index.d.ts.map +1 -0
  66. package/dist/config/index.js +2 -0
  67. package/dist/config/index.js.map +1 -0
  68. package/dist/config/project-config.d.ts +46 -0
  69. package/dist/config/project-config.d.ts.map +1 -0
  70. package/dist/config/project-config.js +68 -0
  71. package/dist/config/project-config.js.map +1 -0
  72. package/dist/lifecycle/cascade.d.ts +1 -1
  73. package/dist/lifecycle/cascade.d.ts.map +1 -1
  74. package/dist/lifecycle/handlers/index.d.ts +4 -0
  75. package/dist/lifecycle/handlers/index.d.ts.map +1 -1
  76. package/dist/lifecycle/handlers/index.js +2 -0
  77. package/dist/lifecycle/handlers/index.js.map +1 -1
  78. package/dist/lifecycle/handlers/worker.d.ts +4 -0
  79. package/dist/lifecycle/handlers/worker.d.ts.map +1 -1
  80. package/dist/lifecycle/handlers/worker.js +35 -3
  81. package/dist/lifecycle/handlers/worker.js.map +1 -1
  82. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  83. package/dist/map/adapter/acp-over-map.js +32 -2
  84. package/dist/map/adapter/acp-over-map.js.map +1 -1
  85. package/dist/map/adapter/event-translator.d.ts.map +1 -1
  86. package/dist/map/adapter/event-translator.js +1 -0
  87. package/dist/map/adapter/event-translator.js.map +1 -1
  88. package/dist/map/adapter/extensions/agent-detection.d.ts +49 -0
  89. package/dist/map/adapter/extensions/agent-detection.d.ts.map +1 -0
  90. package/dist/map/adapter/extensions/agent-detection.js +91 -0
  91. package/dist/map/adapter/extensions/agent-detection.js.map +1 -0
  92. package/dist/map/adapter/extensions/index.d.ts +10 -1
  93. package/dist/map/adapter/extensions/index.d.ts.map +1 -1
  94. package/dist/map/adapter/extensions/index.js +39 -0
  95. package/dist/map/adapter/extensions/index.js.map +1 -1
  96. package/dist/map/adapter/extensions/resume.d.ts +47 -0
  97. package/dist/map/adapter/extensions/resume.d.ts.map +1 -0
  98. package/dist/map/adapter/extensions/resume.js +59 -0
  99. package/dist/map/adapter/extensions/resume.js.map +1 -0
  100. package/dist/map/adapter/extensions/workspace-files.d.ts +42 -0
  101. package/dist/map/adapter/extensions/workspace-files.d.ts.map +1 -0
  102. package/dist/map/adapter/extensions/workspace-files.js +338 -0
  103. package/dist/map/adapter/extensions/workspace-files.js.map +1 -0
  104. package/dist/mcp/mcp-server.d.ts +6 -0
  105. package/dist/mcp/mcp-server.d.ts.map +1 -1
  106. package/dist/mcp/mcp-server.js +45 -0
  107. package/dist/mcp/mcp-server.js.map +1 -1
  108. package/dist/mcp/tools/claim_task.d.ts +35 -0
  109. package/dist/mcp/tools/claim_task.d.ts.map +1 -0
  110. package/dist/mcp/tools/claim_task.js +58 -0
  111. package/dist/mcp/tools/claim_task.js.map +1 -0
  112. package/dist/mcp/tools/done.d.ts +11 -2
  113. package/dist/mcp/tools/done.d.ts.map +1 -1
  114. package/dist/mcp/tools/done.js +15 -10
  115. package/dist/mcp/tools/done.js.map +1 -1
  116. package/dist/mcp/tools/list_claimable_tasks.d.ts +38 -0
  117. package/dist/mcp/tools/list_claimable_tasks.d.ts.map +1 -0
  118. package/dist/mcp/tools/list_claimable_tasks.js +63 -0
  119. package/dist/mcp/tools/list_claimable_tasks.js.map +1 -0
  120. package/dist/mcp/tools/unclaim_task.d.ts +31 -0
  121. package/dist/mcp/tools/unclaim_task.d.ts.map +1 -0
  122. package/dist/mcp/tools/unclaim_task.js +47 -0
  123. package/dist/mcp/tools/unclaim_task.js.map +1 -0
  124. package/dist/metrics/index.d.ts +2 -0
  125. package/dist/metrics/index.d.ts.map +1 -0
  126. package/dist/metrics/index.js +2 -0
  127. package/dist/metrics/index.js.map +1 -0
  128. package/dist/metrics/metrics.d.ts +79 -0
  129. package/dist/metrics/metrics.d.ts.map +1 -0
  130. package/dist/metrics/metrics.js +166 -0
  131. package/dist/metrics/metrics.js.map +1 -0
  132. package/dist/roles/capabilities.d.ts +1 -0
  133. package/dist/roles/capabilities.d.ts.map +1 -1
  134. package/dist/roles/capabilities.js +3 -0
  135. package/dist/roles/capabilities.js.map +1 -1
  136. package/dist/roles/types.d.ts +1 -1
  137. package/dist/roles/types.d.ts.map +1 -1
  138. package/dist/router/message-router.d.ts +41 -0
  139. package/dist/router/message-router.d.ts.map +1 -1
  140. package/dist/router/message-router.js +136 -5
  141. package/dist/router/message-router.js.map +1 -1
  142. package/dist/store/event-store.d.ts +8 -1
  143. package/dist/store/event-store.d.ts.map +1 -1
  144. package/dist/store/event-store.js +120 -4
  145. package/dist/store/event-store.js.map +1 -1
  146. package/dist/store/types/agents.d.ts +1 -1
  147. package/dist/store/types/agents.d.ts.map +1 -1
  148. package/dist/store/types/events.d.ts +1 -1
  149. package/dist/store/types/events.d.ts.map +1 -1
  150. package/dist/store/types/events.js.map +1 -1
  151. package/dist/store/types/index.d.ts +1 -0
  152. package/dist/store/types/index.d.ts.map +1 -1
  153. package/dist/store/types/index.js +1 -0
  154. package/dist/store/types/index.js.map +1 -1
  155. package/dist/store/types/sessions.d.ts +44 -0
  156. package/dist/store/types/sessions.d.ts.map +1 -0
  157. package/dist/store/types/sessions.js +9 -0
  158. package/dist/store/types/sessions.js.map +1 -0
  159. package/dist/store/types/tasks.d.ts +2 -0
  160. package/dist/store/types/tasks.d.ts.map +1 -1
  161. package/dist/task/backend/memory.d.ts +4 -1
  162. package/dist/task/backend/memory.d.ts.map +1 -1
  163. package/dist/task/backend/memory.js +81 -0
  164. package/dist/task/backend/memory.js.map +1 -1
  165. package/dist/task/backend/types.d.ts +30 -0
  166. package/dist/task/backend/types.d.ts.map +1 -1
  167. package/dist/task/backend/types.js.map +1 -1
  168. package/dist/teams/index.d.ts +4 -0
  169. package/dist/teams/index.d.ts.map +1 -0
  170. package/dist/teams/index.js +4 -0
  171. package/dist/teams/index.js.map +1 -0
  172. package/dist/teams/team-loader.d.ts +20 -0
  173. package/dist/teams/team-loader.d.ts.map +1 -0
  174. package/dist/teams/team-loader.js +293 -0
  175. package/dist/teams/team-loader.js.map +1 -0
  176. package/dist/teams/team-runtime.d.ts +139 -0
  177. package/dist/teams/team-runtime.d.ts.map +1 -0
  178. package/dist/teams/team-runtime.js +613 -0
  179. package/dist/teams/team-runtime.js.map +1 -0
  180. package/dist/teams/types.d.ts +266 -0
  181. package/dist/teams/types.d.ts.map +1 -0
  182. package/dist/teams/types.js +20 -0
  183. package/dist/teams/types.js.map +1 -0
  184. package/dist/workspace/dataplane-adapter.d.ts +1 -1
  185. package/dist/workspace/dataplane-adapter.d.ts.map +1 -1
  186. package/dist/workspace/dataplane-adapter.js +1 -1
  187. package/dist/workspace/dataplane-adapter.js.map +1 -1
  188. package/dist/workspace/index.d.ts +1 -1
  189. package/dist/workspace/index.d.ts.map +1 -1
  190. package/dist/workspace/strategies/index.d.ts +6 -0
  191. package/dist/workspace/strategies/index.d.ts.map +1 -0
  192. package/dist/workspace/strategies/index.js +5 -0
  193. package/dist/workspace/strategies/index.js.map +1 -0
  194. package/dist/workspace/strategies/optimistic.d.ts +26 -0
  195. package/dist/workspace/strategies/optimistic.d.ts.map +1 -0
  196. package/dist/workspace/strategies/optimistic.js +121 -0
  197. package/dist/workspace/strategies/optimistic.js.map +1 -0
  198. package/dist/workspace/strategies/queue.d.ts +26 -0
  199. package/dist/workspace/strategies/queue.d.ts.map +1 -0
  200. package/dist/workspace/strategies/queue.js +67 -0
  201. package/dist/workspace/strategies/queue.js.map +1 -0
  202. package/dist/workspace/strategies/registry.d.ts +37 -0
  203. package/dist/workspace/strategies/registry.d.ts.map +1 -0
  204. package/dist/workspace/strategies/registry.js +63 -0
  205. package/dist/workspace/strategies/registry.js.map +1 -0
  206. package/dist/workspace/strategies/trunk.d.ts +20 -0
  207. package/dist/workspace/strategies/trunk.d.ts.map +1 -0
  208. package/dist/workspace/strategies/trunk.js +108 -0
  209. package/dist/workspace/strategies/trunk.js.map +1 -0
  210. package/dist/workspace/strategies/types.d.ts +104 -0
  211. package/dist/workspace/strategies/types.d.ts.map +1 -0
  212. package/dist/workspace/strategies/types.js +11 -0
  213. package/dist/workspace/strategies/types.js.map +1 -0
  214. package/dist/workspace/types.d.ts +1 -1
  215. package/dist/workspace/types.d.ts.map +1 -1
  216. package/dist/workspace/workspace-manager.d.ts +1 -1
  217. package/dist/workspace/workspace-manager.d.ts.map +1 -1
  218. package/docs/implementation-details.md +1127 -0
  219. package/docs/implementation-summary.md +448 -0
  220. package/docs/plan-self-driving-support.md +433 -0
  221. package/docs/spec-self-driving-support.md +462 -0
  222. package/docs/team-templates.md +860 -0
  223. package/docs/teams.md +233 -0
  224. package/package.json +4 -2
  225. package/src/acp/__tests__/integration.test.ts +161 -1
  226. package/src/acp/__tests__/macro-agent.test.ts +95 -0
  227. package/src/acp/__tests__/session-persistence.test.ts +276 -0
  228. package/src/acp/macro-agent.ts +79 -7
  229. package/src/acp/session-mapper.ts +108 -1
  230. package/src/acp/types.ts +33 -1
  231. package/src/agent/agent-manager.ts +158 -6
  232. package/src/agent/types.ts +27 -0
  233. package/src/agent-detection/__tests__/command-builder.test.ts +336 -0
  234. package/src/agent-detection/__tests__/detector.test.ts +768 -0
  235. package/src/agent-detection/__tests__/registry.test.ts +254 -0
  236. package/src/agent-detection/command-builder.ts +90 -0
  237. package/src/agent-detection/detector.ts +307 -0
  238. package/src/agent-detection/index.ts +36 -0
  239. package/src/agent-detection/registry.ts +200 -0
  240. package/src/agent-detection/types.ts +184 -0
  241. package/src/api/server.ts +110 -0
  242. package/src/cli/index.ts +44 -0
  243. package/src/cli/mcp.ts +47 -0
  244. package/src/config/index.ts +9 -0
  245. package/src/config/project-config.ts +107 -0
  246. package/src/lifecycle/cascade.ts +1 -1
  247. package/src/lifecycle/handlers/index.ts +8 -0
  248. package/src/lifecycle/handlers/worker.ts +48 -3
  249. package/src/map/adapter/__tests__/extensions.test.ts +359 -0
  250. package/src/map/adapter/__tests__/workspace-files.test.ts +673 -0
  251. package/src/map/adapter/acp-over-map.ts +45 -2
  252. package/src/map/adapter/event-translator.ts +1 -0
  253. package/src/map/adapter/extensions/agent-detection.ts +201 -0
  254. package/src/map/adapter/extensions/index.ts +63 -0
  255. package/src/map/adapter/extensions/resume.ts +114 -0
  256. package/src/map/adapter/extensions/workspace-files.ts +449 -0
  257. package/src/mcp/mcp-server.ts +67 -0
  258. package/src/mcp/tools/claim_task.ts +86 -0
  259. package/src/mcp/tools/done.ts +24 -10
  260. package/src/mcp/tools/list_claimable_tasks.ts +93 -0
  261. package/src/mcp/tools/unclaim_task.ts +71 -0
  262. package/src/metrics/index.ts +9 -0
  263. package/src/metrics/metrics.ts +280 -0
  264. package/src/roles/capabilities.ts +3 -0
  265. package/src/roles/types.ts +2 -1
  266. package/src/router/__tests__/message-router.test.ts +561 -0
  267. package/src/router/message-router.ts +223 -6
  268. package/src/store/event-store.ts +151 -3
  269. package/src/store/types/agents.ts +1 -1
  270. package/src/store/types/events.ts +2 -1
  271. package/src/store/types/index.ts +1 -0
  272. package/src/store/types/sessions.ts +53 -0
  273. package/src/store/types/tasks.ts +3 -0
  274. package/src/task/backend/memory.ts +116 -0
  275. package/src/task/backend/types.ts +43 -0
  276. package/src/teams/__tests__/cross-subsystem.integration.test.ts +983 -0
  277. package/src/teams/__tests__/e2e/team-runtime.e2e.test.ts +553 -0
  278. package/src/teams/__tests__/team-system.test.ts +1280 -0
  279. package/src/teams/index.ts +13 -0
  280. package/src/teams/team-loader.ts +434 -0
  281. package/src/teams/team-runtime.ts +727 -0
  282. package/src/teams/types.ts +377 -0
  283. package/src/workspace/dataplane-adapter.ts +1 -1
  284. package/src/workspace/index.ts +1 -1
  285. package/src/workspace/strategies/index.ts +18 -0
  286. package/src/workspace/strategies/optimistic.ts +136 -0
  287. package/src/workspace/strategies/queue.ts +81 -0
  288. package/src/workspace/strategies/registry.ts +89 -0
  289. package/src/workspace/strategies/trunk.ts +123 -0
  290. package/src/workspace/strategies/types.ts +145 -0
  291. package/src/workspace/types.ts +1 -1
  292. package/src/workspace/workspace-manager.ts +1 -1
  293. package/.claude/settings.local.json +0 -59
  294. package/dist/map/utils/address-translation.d.ts +0 -99
  295. package/dist/map/utils/address-translation.d.ts.map +0 -1
  296. package/dist/map/utils/address-translation.js +0 -285
  297. package/dist/map/utils/address-translation.js.map +0 -1
  298. package/dist/map/utils/index.d.ts +0 -7
  299. package/dist/map/utils/index.d.ts.map +0 -1
  300. package/dist/map/utils/index.js +0 -7
  301. package/dist/map/utils/index.js.map +0 -1
  302. package/references/acp-factory-ref/CHANGELOG.md +0 -33
  303. package/references/acp-factory-ref/LICENSE +0 -21
  304. package/references/acp-factory-ref/README.md +0 -341
  305. package/references/acp-factory-ref/package-lock.json +0 -3102
  306. package/references/acp-factory-ref/package.json +0 -96
  307. package/references/acp-factory-ref/python/CHANGELOG.md +0 -33
  308. package/references/acp-factory-ref/python/LICENSE +0 -21
  309. package/references/acp-factory-ref/python/Makefile +0 -57
  310. package/references/acp-factory-ref/python/README.md +0 -253
  311. package/references/acp-factory-ref/python/pyproject.toml +0 -73
  312. package/references/acp-factory-ref/python/tests/__init__.py +0 -0
  313. package/references/acp-factory-ref/python/tests/e2e/__init__.py +0 -1
  314. package/references/acp-factory-ref/python/tests/e2e/test_codex_e2e.py +0 -349
  315. package/references/acp-factory-ref/python/tests/e2e/test_gemini_e2e.py +0 -165
  316. package/references/acp-factory-ref/python/tests/e2e/test_opencode_e2e.py +0 -296
  317. package/references/acp-factory-ref/python/tests/test_client_handler.py +0 -543
  318. package/references/acp-factory-ref/python/tests/test_pushable.py +0 -199
  319. package/references/claude-code-acp/.github/workflows/ci.yml +0 -45
  320. package/references/claude-code-acp/.github/workflows/publish.yml +0 -34
  321. package/references/claude-code-acp/.prettierrc.json +0 -4
  322. package/references/claude-code-acp/CHANGELOG.md +0 -249
  323. package/references/claude-code-acp/LICENSE +0 -222
  324. package/references/claude-code-acp/README.md +0 -53
  325. package/references/claude-code-acp/docs/RELEASES.md +0 -24
  326. package/references/claude-code-acp/eslint.config.js +0 -48
  327. package/references/claude-code-acp/package-lock.json +0 -4570
  328. package/references/claude-code-acp/package.json +0 -88
  329. package/references/claude-code-acp/scripts/release.sh +0 -119
  330. package/references/claude-code-acp/src/acp-agent.ts +0 -2065
  331. package/references/claude-code-acp/src/index.ts +0 -26
  332. package/references/claude-code-acp/src/lib.ts +0 -38
  333. package/references/claude-code-acp/src/mcp-server.ts +0 -911
  334. package/references/claude-code-acp/src/settings.ts +0 -522
  335. package/references/claude-code-acp/src/tests/.claude/commands/quick-math.md +0 -5
  336. package/references/claude-code-acp/src/tests/.claude/commands/say-hello.md +0 -6
  337. package/references/claude-code-acp/src/tests/acp-agent-fork.test.ts +0 -479
  338. package/references/claude-code-acp/src/tests/acp-agent.test.ts +0 -1502
  339. package/references/claude-code-acp/src/tests/extract-lines.test.ts +0 -103
  340. package/references/claude-code-acp/src/tests/fork-session.test.ts +0 -335
  341. package/references/claude-code-acp/src/tests/replace-and-calculate-location.test.ts +0 -334
  342. package/references/claude-code-acp/src/tests/settings.test.ts +0 -617
  343. package/references/claude-code-acp/src/tests/skills-options.test.ts +0 -187
  344. package/references/claude-code-acp/src/tests/tools.test.ts +0 -318
  345. package/references/claude-code-acp/src/tests/typescript-declarations.test.ts +0 -558
  346. package/references/claude-code-acp/src/tools.ts +0 -819
  347. package/references/claude-code-acp/src/utils.ts +0 -171
  348. package/references/claude-code-acp/tsconfig.json +0 -18
  349. package/references/claude-code-acp/vitest.config.ts +0 -19
  350. package/references/multi-agent-protocol/.sudocode/issues.jsonl +0 -111
  351. package/references/multi-agent-protocol/.sudocode/specs.jsonl +0 -13
  352. package/references/multi-agent-protocol/LICENSE +0 -21
  353. package/references/multi-agent-protocol/README.md +0 -113
  354. package/references/multi-agent-protocol/docs/00-design-specification.md +0 -496
  355. package/references/multi-agent-protocol/docs/01-open-questions.md +0 -1050
  356. package/references/multi-agent-protocol/docs/02-wire-protocol.md +0 -296
  357. package/references/multi-agent-protocol/docs/03-streaming-semantics.md +0 -252
  358. package/references/multi-agent-protocol/docs/04-error-handling.md +0 -231
  359. package/references/multi-agent-protocol/docs/05-connection-model.md +0 -244
  360. package/references/multi-agent-protocol/docs/06-visibility-permissions.md +0 -243
  361. package/references/multi-agent-protocol/docs/07-federation.md +0 -259
  362. package/references/multi-agent-protocol/docs/08-macro-agent-migration.md +0 -253
  363. package/references/multi-agent-protocol/docs/09-authentication.md +0 -680
  364. package/references/multi-agent-protocol/docs/10-mail-protocol.md +0 -553
  365. package/references/multi-agent-protocol/docs/agent-iam-integration.md +0 -877
  366. package/references/multi-agent-protocol/docs/agentic-mesh-integration-draft.md +0 -459
  367. package/references/multi-agent-protocol/docs/git-transport-draft.md +0 -251
  368. package/references/multi-agent-protocol/docs-site/Gemfile +0 -22
  369. package/references/multi-agent-protocol/docs-site/README.md +0 -82
  370. package/references/multi-agent-protocol/docs-site/_config.yml +0 -91
  371. package/references/multi-agent-protocol/docs-site/_includes/head_custom.html +0 -20
  372. package/references/multi-agent-protocol/docs-site/_sass/color_schemes/map.scss +0 -42
  373. package/references/multi-agent-protocol/docs-site/_sass/custom/custom.scss +0 -34
  374. package/references/multi-agent-protocol/docs-site/examples/full-integration.md +0 -510
  375. package/references/multi-agent-protocol/docs-site/examples/index.md +0 -138
  376. package/references/multi-agent-protocol/docs-site/examples/simple-chat.md +0 -282
  377. package/references/multi-agent-protocol/docs-site/examples/task-queue.md +0 -399
  378. package/references/multi-agent-protocol/docs-site/getting-started/index.md +0 -98
  379. package/references/multi-agent-protocol/docs-site/getting-started/installation.md +0 -219
  380. package/references/multi-agent-protocol/docs-site/getting-started/overview.md +0 -172
  381. package/references/multi-agent-protocol/docs-site/getting-started/quickstart.md +0 -237
  382. package/references/multi-agent-protocol/docs-site/index.md +0 -136
  383. package/references/multi-agent-protocol/docs-site/protocol/authentication.md +0 -391
  384. package/references/multi-agent-protocol/docs-site/protocol/connection-model.md +0 -376
  385. package/references/multi-agent-protocol/docs-site/protocol/design.md +0 -284
  386. package/references/multi-agent-protocol/docs-site/protocol/error-handling.md +0 -312
  387. package/references/multi-agent-protocol/docs-site/protocol/federation.md +0 -449
  388. package/references/multi-agent-protocol/docs-site/protocol/index.md +0 -129
  389. package/references/multi-agent-protocol/docs-site/protocol/permissions.md +0 -398
  390. package/references/multi-agent-protocol/docs-site/protocol/streaming.md +0 -353
  391. package/references/multi-agent-protocol/docs-site/protocol/wire-protocol.md +0 -369
  392. package/references/multi-agent-protocol/docs-site/sdk/api/agent.md +0 -357
  393. package/references/multi-agent-protocol/docs-site/sdk/api/client.md +0 -380
  394. package/references/multi-agent-protocol/docs-site/sdk/api/index.md +0 -62
  395. package/references/multi-agent-protocol/docs-site/sdk/api/server.md +0 -453
  396. package/references/multi-agent-protocol/docs-site/sdk/api/types.md +0 -468
  397. package/references/multi-agent-protocol/docs-site/sdk/guides/agent.md +0 -375
  398. package/references/multi-agent-protocol/docs-site/sdk/guides/authentication.md +0 -405
  399. package/references/multi-agent-protocol/docs-site/sdk/guides/client.md +0 -352
  400. package/references/multi-agent-protocol/docs-site/sdk/guides/index.md +0 -89
  401. package/references/multi-agent-protocol/docs-site/sdk/guides/server.md +0 -360
  402. package/references/multi-agent-protocol/docs-site/sdk/guides/testing.md +0 -446
  403. package/references/multi-agent-protocol/docs-site/sdk/guides/transports.md +0 -363
  404. package/references/multi-agent-protocol/docs-site/sdk/index.md +0 -206
  405. package/references/multi-agent-protocol/package-lock.json +0 -3886
  406. package/references/multi-agent-protocol/package.json +0 -56
  407. package/references/multi-agent-protocol/schema/meta.json +0 -467
  408. package/references/multi-agent-protocol/schema/schema.json +0 -2558
@@ -1,543 +0,0 @@
1
- """Tests for ACPClientHandler."""
2
-
3
- import asyncio
4
- import tempfile
5
- from pathlib import Path
6
- from unittest.mock import AsyncMock
7
-
8
- import pytest
9
-
10
- from acp_factory.client_handler import ACPClientHandler
11
- from acp_factory.types import ClientHandlers
12
-
13
-
14
- def create_permission_request(
15
- options: list[dict[str, str]],
16
- session_id: str = "test-session",
17
- ) -> tuple[str, dict, list[dict]]:
18
- """Helper to create permission request parameters."""
19
- tool_call = {
20
- "toolCallId": "tool-1",
21
- "title": "Test Tool",
22
- "status": "pending",
23
- }
24
- formatted_options = [
25
- {"kind": opt["kind"], "optionId": opt["optionId"], "name": opt["name"]}
26
- for opt in options
27
- ]
28
- return session_id, tool_call, formatted_options
29
-
30
-
31
- class TestACPClientHandlerRequestPermission:
32
- """Tests for permission request handling."""
33
-
34
- @pytest.mark.asyncio
35
- async def test_should_auto_approve_by_selecting_allow_once_option(self) -> None:
36
- """Auto-approve mode selects allow_once option."""
37
- handler = ACPClientHandler(permission_mode="auto-approve")
38
-
39
- session_id, tool_call, options = create_permission_request([
40
- {"kind": "allow_once", "optionId": "allow", "name": "Allow"},
41
- {"kind": "reject_once", "optionId": "reject", "name": "Reject"},
42
- ])
43
-
44
- result = await handler.request_permission(session_id, tool_call, options)
45
-
46
- assert result["outcome"] == {"outcome": "selected", "optionId": "allow"}
47
-
48
- @pytest.mark.asyncio
49
- async def test_should_auto_approve_by_selecting_allow_always_option(self) -> None:
50
- """Auto-approve mode selects allow_always option."""
51
- handler = ACPClientHandler(permission_mode="auto-approve")
52
-
53
- session_id, tool_call, options = create_permission_request([
54
- {"kind": "reject_once", "optionId": "reject", "name": "Reject"},
55
- {"kind": "allow_always", "optionId": "allow-all", "name": "Allow Always"},
56
- ])
57
-
58
- result = await handler.request_permission(session_id, tool_call, options)
59
-
60
- assert result["outcome"] == {"outcome": "selected", "optionId": "allow-all"}
61
-
62
- @pytest.mark.asyncio
63
- async def test_should_auto_deny_by_selecting_reject_once_option(self) -> None:
64
- """Auto-deny mode selects reject_once option."""
65
- handler = ACPClientHandler(permission_mode="auto-deny")
66
-
67
- session_id, tool_call, options = create_permission_request([
68
- {"kind": "allow_once", "optionId": "allow", "name": "Allow"},
69
- {"kind": "reject_once", "optionId": "reject", "name": "Reject"},
70
- ])
71
-
72
- result = await handler.request_permission(session_id, tool_call, options)
73
-
74
- assert result["outcome"] == {"outcome": "selected", "optionId": "reject"}
75
-
76
- @pytest.mark.asyncio
77
- async def test_should_auto_deny_by_selecting_reject_always_option(self) -> None:
78
- """Auto-deny mode selects reject_always option."""
79
- handler = ACPClientHandler(permission_mode="auto-deny")
80
-
81
- session_id, tool_call, options = create_permission_request([
82
- {"kind": "allow_once", "optionId": "allow", "name": "Allow"},
83
- {"kind": "reject_always", "optionId": "reject-all", "name": "Reject Always"},
84
- ])
85
-
86
- result = await handler.request_permission(session_id, tool_call, options)
87
-
88
- assert result["outcome"] == {"outcome": "selected", "optionId": "reject-all"}
89
-
90
- @pytest.mark.asyncio
91
- async def test_should_use_callback_handler_in_callback_mode(self) -> None:
92
- """Callback mode delegates to handler."""
93
- mock_handler = AsyncMock(return_value={
94
- "outcome": {"outcome": "selected", "optionId": "custom"},
95
- })
96
-
97
- handlers = ClientHandlers(on_permission_request=mock_handler)
98
- handler = ACPClientHandler(handlers=handlers, permission_mode="callback")
99
-
100
- session_id, tool_call, options = create_permission_request([
101
- {"kind": "allow_once", "optionId": "allow", "name": "Allow"},
102
- ])
103
-
104
- result = await handler.request_permission(session_id, tool_call, options)
105
-
106
- mock_handler.assert_called_once()
107
- assert result["outcome"] == {"outcome": "selected", "optionId": "custom"}
108
-
109
- @pytest.mark.asyncio
110
- async def test_should_fallback_to_first_option_when_no_matching_option(self) -> None:
111
- """Falls back to first option when no matching option found."""
112
- handler = ACPClientHandler(permission_mode="auto-approve")
113
-
114
- # Only reject options available
115
- session_id, tool_call, options = create_permission_request([
116
- {"kind": "reject_once", "optionId": "reject", "name": "Reject"},
117
- {"kind": "reject_always", "optionId": "reject-all", "name": "Reject Always"},
118
- ])
119
-
120
- result = await handler.request_permission(session_id, tool_call, options)
121
-
122
- # Should fallback to first option
123
- assert result["outcome"] == {"outcome": "selected", "optionId": "reject"}
124
-
125
-
126
- class TestACPClientHandlerInteractivePermission:
127
- """Tests for interactive permission mode."""
128
-
129
- @pytest.mark.asyncio
130
- async def test_should_emit_permission_request_to_session_stream(self) -> None:
131
- """Interactive mode emits permission request to stream."""
132
- handler = ACPClientHandler(permission_mode="interactive")
133
- stream = handler.get_session_stream("session-1")
134
-
135
- session_id, tool_call, options = create_permission_request(
136
- [
137
- {"kind": "allow_once", "optionId": "allow", "name": "Allow"},
138
- {"kind": "reject_once", "optionId": "reject", "name": "Reject"},
139
- ],
140
- session_id="session-1",
141
- )
142
-
143
- # Start permission request (will block until responded)
144
- permission_task = asyncio.create_task(
145
- handler.request_permission(session_id, tool_call, options)
146
- )
147
-
148
- # Get the emitted update from the stream
149
- update = await stream.__anext__()
150
-
151
- assert update.session_update == "permission_request"
152
- assert update.request_id.startswith("perm-")
153
- assert update.session_id == "session-1"
154
- assert update.tool_call["toolCallId"] == "tool-1"
155
- assert len(update.options) == 2
156
-
157
- # Respond to unblock the promise
158
- handler.respond_to_permission(update.request_id, "allow")
159
- result = await permission_task
160
-
161
- assert result["outcome"] == {"outcome": "selected", "optionId": "allow"}
162
-
163
- @pytest.mark.asyncio
164
- async def test_should_handle_respond_to_permission_correctly(self) -> None:
165
- """respond_to_permission resolves pending request."""
166
- handler = ACPClientHandler(permission_mode="interactive")
167
- handler.get_session_stream("session-1") # Initialize stream
168
-
169
- session_id, tool_call, options = create_permission_request(
170
- [
171
- {"kind": "allow_once", "optionId": "allow", "name": "Allow"},
172
- {"kind": "reject_once", "optionId": "reject", "name": "Reject"},
173
- ],
174
- session_id="session-1",
175
- )
176
-
177
- permission_task = asyncio.create_task(
178
- handler.request_permission(session_id, tool_call, options)
179
- )
180
-
181
- # Wait a tick for the update to be pushed
182
- await asyncio.sleep(0.01)
183
-
184
- # Get pending permission IDs
185
- pending_ids = handler.get_pending_permission_ids("session-1")
186
- assert len(pending_ids) == 1
187
-
188
- # Respond with reject
189
- handler.respond_to_permission(pending_ids[0], "reject")
190
- result = await permission_task
191
-
192
- assert result["outcome"] == {"outcome": "selected", "optionId": "reject"}
193
-
194
- @pytest.mark.asyncio
195
- async def test_should_handle_cancel_permission_correctly(self) -> None:
196
- """cancel_permission cancels the pending request."""
197
- handler = ACPClientHandler(permission_mode="interactive")
198
- handler.get_session_stream("session-1")
199
-
200
- session_id, tool_call, options = create_permission_request(
201
- [{"kind": "allow_once", "optionId": "allow", "name": "Allow"}],
202
- session_id="session-1",
203
- )
204
-
205
- permission_task = asyncio.create_task(
206
- handler.request_permission(session_id, tool_call, options)
207
- )
208
-
209
- await asyncio.sleep(0.01)
210
-
211
- pending_ids = handler.get_pending_permission_ids("session-1")
212
- handler.cancel_permission(pending_ids[0])
213
-
214
- result = await permission_task
215
- assert result["outcome"] == {"outcome": "cancelled"}
216
-
217
- def test_should_throw_error_when_responding_to_nonexistent_permission(self) -> None:
218
- """Throws error when responding to non-existent permission."""
219
- handler = ACPClientHandler(permission_mode="interactive")
220
-
221
- with pytest.raises(ValueError, match="No pending permission request with ID"):
222
- handler.respond_to_permission("non-existent", "allow")
223
-
224
- def test_should_throw_error_when_cancelling_nonexistent_permission(self) -> None:
225
- """Throws error when cancelling non-existent permission."""
226
- handler = ACPClientHandler(permission_mode="interactive")
227
-
228
- with pytest.raises(ValueError, match="No pending permission request with ID"):
229
- handler.cancel_permission("non-existent")
230
-
231
- @pytest.mark.asyncio
232
- async def test_should_track_has_pending_permissions_correctly(self) -> None:
233
- """has_pending_permissions reflects state correctly."""
234
- handler = ACPClientHandler(permission_mode="interactive")
235
- handler.get_session_stream("session-1")
236
-
237
- assert handler.has_pending_permissions() is False
238
-
239
- session_id, tool_call, options = create_permission_request(
240
- [{"kind": "allow_once", "optionId": "allow", "name": "Allow"}],
241
- session_id="session-1",
242
- )
243
-
244
- permission_task = asyncio.create_task(
245
- handler.request_permission(session_id, tool_call, options)
246
- )
247
-
248
- await asyncio.sleep(0.01)
249
- assert handler.has_pending_permissions() is True
250
-
251
- pending_ids = handler.get_pending_permission_ids("session-1")
252
- handler.respond_to_permission(pending_ids[0], "allow")
253
- await permission_task
254
-
255
- assert handler.has_pending_permissions() is False
256
-
257
- @pytest.mark.asyncio
258
- async def test_should_handle_multiple_pending_permissions_for_different_sessions(
259
- self,
260
- ) -> None:
261
- """Multiple pending permissions for different sessions work correctly."""
262
- handler = ACPClientHandler(permission_mode="interactive")
263
- handler.get_session_stream("session-1")
264
- handler.get_session_stream("session-2")
265
-
266
- _, tool_call1, options1 = create_permission_request(
267
- [{"kind": "allow_once", "optionId": "allow", "name": "Allow"}],
268
- session_id="session-1",
269
- )
270
- _, tool_call2, options2 = create_permission_request(
271
- [{"kind": "allow_once", "optionId": "allow", "name": "Allow"}],
272
- session_id="session-2",
273
- )
274
-
275
- task1 = asyncio.create_task(
276
- handler.request_permission("session-1", tool_call1, options1)
277
- )
278
- task2 = asyncio.create_task(
279
- handler.request_permission("session-2", tool_call2, options2)
280
- )
281
-
282
- await asyncio.sleep(0.01)
283
-
284
- assert len(handler.get_pending_permission_ids("session-1")) == 1
285
- assert len(handler.get_pending_permission_ids("session-2")) == 1
286
-
287
- # Respond to session-1
288
- ids1 = handler.get_pending_permission_ids("session-1")
289
- handler.respond_to_permission(ids1[0], "allow")
290
- await task1
291
-
292
- assert len(handler.get_pending_permission_ids("session-1")) == 0
293
- assert len(handler.get_pending_permission_ids("session-2")) == 1
294
-
295
- # Respond to session-2
296
- ids2 = handler.get_pending_permission_ids("session-2")
297
- handler.respond_to_permission(ids2[0], "allow")
298
- await task2
299
-
300
-
301
- class TestACPClientHandlerSessionUpdate:
302
- """Tests for session update handling."""
303
-
304
- @pytest.mark.asyncio
305
- async def test_should_push_updates_to_session_stream(self) -> None:
306
- """Session updates are pushed to stream."""
307
- handler = ACPClientHandler()
308
-
309
- update = {
310
- "sessionUpdate": "agent_message_chunk",
311
- "content": {"type": "text", "text": "Hello"},
312
- }
313
-
314
- # Get stream before pushing
315
- stream = handler.get_session_stream("session-1")
316
-
317
- # Push update
318
- await handler.session_update("session-1", update)
319
-
320
- # End stream
321
- handler.end_session_stream("session-1")
322
-
323
- # Collect results
324
- results = []
325
- async for item in stream:
326
- results.append(item)
327
-
328
- assert len(results) == 1
329
- assert results[0] == update
330
-
331
- @pytest.mark.asyncio
332
- async def test_should_handle_multiple_sessions_independently(self) -> None:
333
- """Multiple sessions have independent streams."""
334
- handler = ACPClientHandler()
335
-
336
- stream1 = handler.get_session_stream("session-1")
337
- stream2 = handler.get_session_stream("session-2")
338
-
339
- await handler.session_update(
340
- "session-1",
341
- {"sessionUpdate": "agent_message_chunk", "content": {"type": "text", "text": "S1"}},
342
- )
343
- await handler.session_update(
344
- "session-2",
345
- {"sessionUpdate": "agent_message_chunk", "content": {"type": "text", "text": "S2"}},
346
- )
347
-
348
- handler.end_session_stream("session-1")
349
- handler.end_session_stream("session-2")
350
-
351
- results1 = []
352
- async for item in stream1:
353
- results1.append(item)
354
-
355
- results2 = []
356
- async for item in stream2:
357
- results2.append(item)
358
-
359
- assert len(results1) == 1
360
- assert len(results2) == 1
361
- assert results1[0]["content"]["text"] == "S1"
362
- assert results2[0]["content"]["text"] == "S2"
363
-
364
-
365
- class TestACPClientHandlerFileOperations:
366
- """Tests for file operations."""
367
-
368
- @pytest.mark.asyncio
369
- async def test_should_use_custom_handler_for_read(self) -> None:
370
- """Custom handler is used for file read."""
371
- mock_read = AsyncMock(return_value="custom content")
372
- handlers = ClientHandlers(on_file_read=mock_read)
373
- handler = ACPClientHandler(handlers=handlers)
374
-
375
- result = await handler.read_text_file("/test/file.txt", "s1")
376
-
377
- mock_read.assert_called_once_with("/test/file.txt")
378
- assert result["content"] == "custom content"
379
-
380
- @pytest.mark.asyncio
381
- async def test_should_read_from_filesystem_by_default(self) -> None:
382
- """Default file read uses filesystem."""
383
- handler = ACPClientHandler()
384
-
385
- with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f:
386
- f.write("test content")
387
- temp_path = f.name
388
-
389
- try:
390
- result = await handler.read_text_file(temp_path, "s1")
391
- assert result["content"] == "test content"
392
- finally:
393
- Path(temp_path).unlink()
394
-
395
- @pytest.mark.asyncio
396
- async def test_should_throw_error_when_file_read_fails(self) -> None:
397
- """Throws error when file read fails."""
398
- handler = ACPClientHandler()
399
-
400
- with pytest.raises(RuntimeError, match="Failed to read file"):
401
- await handler.read_text_file("/nonexistent/path/file.txt", "s1")
402
-
403
- @pytest.mark.asyncio
404
- async def test_should_use_custom_handler_for_write(self) -> None:
405
- """Custom handler is used for file write."""
406
- mock_write = AsyncMock()
407
- handlers = ClientHandlers(on_file_write=mock_write)
408
- handler = ACPClientHandler(handlers=handlers)
409
-
410
- result = await handler.write_text_file("/test/file.txt", "test content", "s1")
411
-
412
- mock_write.assert_called_once_with("/test/file.txt", "test content")
413
- assert result == {}
414
-
415
- @pytest.mark.asyncio
416
- async def test_should_write_to_filesystem_by_default(self) -> None:
417
- """Default file write uses filesystem."""
418
- handler = ACPClientHandler()
419
-
420
- with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f:
421
- temp_path = f.name
422
-
423
- try:
424
- await handler.write_text_file(temp_path, "written content", "s1")
425
- assert Path(temp_path).read_text() == "written content"
426
- finally:
427
- Path(temp_path).unlink()
428
-
429
-
430
- class TestACPClientHandlerTerminalOperations:
431
- """Tests for terminal operations."""
432
-
433
- @pytest.mark.asyncio
434
- async def test_should_throw_error_when_create_terminal_handler_not_provided(
435
- self,
436
- ) -> None:
437
- """Throws error when create_terminal handler not provided."""
438
- handler = ACPClientHandler()
439
-
440
- with pytest.raises(RuntimeError, match="no on_terminal_create handler provided"):
441
- await handler.create_terminal("ls", "s1", cwd="/tmp")
442
-
443
- @pytest.mark.asyncio
444
- async def test_should_throw_error_when_terminal_output_handler_not_provided(
445
- self,
446
- ) -> None:
447
- """Throws error when terminal_output handler not provided."""
448
- handler = ACPClientHandler()
449
-
450
- with pytest.raises(RuntimeError, match="no on_terminal_output handler provided"):
451
- await handler.terminal_output("s1", "term-1")
452
-
453
- @pytest.mark.asyncio
454
- async def test_should_throw_error_when_kill_terminal_handler_not_provided(
455
- self,
456
- ) -> None:
457
- """Throws error when kill_terminal handler not provided."""
458
- handler = ACPClientHandler()
459
-
460
- with pytest.raises(RuntimeError, match="no on_terminal_kill handler provided"):
461
- await handler.kill_terminal("s1", "term-1")
462
-
463
- @pytest.mark.asyncio
464
- async def test_should_throw_error_when_release_terminal_handler_not_provided(
465
- self,
466
- ) -> None:
467
- """Throws error when release_terminal handler not provided."""
468
- handler = ACPClientHandler()
469
-
470
- with pytest.raises(RuntimeError, match="no on_terminal_release handler provided"):
471
- await handler.release_terminal("s1", "term-1")
472
-
473
- @pytest.mark.asyncio
474
- async def test_should_throw_error_when_wait_for_terminal_exit_handler_not_provided(
475
- self,
476
- ) -> None:
477
- """Throws error when wait_for_terminal_exit handler not provided."""
478
- handler = ACPClientHandler()
479
-
480
- with pytest.raises(
481
- RuntimeError, match="no on_terminal_wait_for_exit handler provided"
482
- ):
483
- await handler.wait_for_terminal_exit("s1", "term-1")
484
-
485
- @pytest.mark.asyncio
486
- async def test_should_delegate_to_create_terminal_handler(self) -> None:
487
- """Delegates to create_terminal handler."""
488
- mock_create = AsyncMock(return_value={"terminalId": "term-123"})
489
- handlers = ClientHandlers(on_terminal_create=mock_create)
490
- handler = ACPClientHandler(handlers=handlers)
491
-
492
- result = await handler.create_terminal("ls", "s1", cwd="/tmp")
493
-
494
- mock_create.assert_called_once()
495
- assert result == {"terminalId": "term-123"}
496
-
497
- @pytest.mark.asyncio
498
- async def test_should_delegate_to_terminal_output_handler(self) -> None:
499
- """Delegates to terminal_output handler."""
500
- mock_output = AsyncMock(return_value="output text")
501
- handlers = ClientHandlers(on_terminal_output=mock_output)
502
- handler = ACPClientHandler(handlers=handlers)
503
-
504
- result = await handler.terminal_output("s1", "term-1")
505
-
506
- mock_output.assert_called_once_with("term-1")
507
- assert result == {"output": "output text", "truncated": False}
508
-
509
- @pytest.mark.asyncio
510
- async def test_should_delegate_to_wait_for_terminal_exit_handler(self) -> None:
511
- """Delegates to wait_for_terminal_exit handler."""
512
- mock_wait = AsyncMock(return_value=0)
513
- handlers = ClientHandlers(on_terminal_wait_for_exit=mock_wait)
514
- handler = ACPClientHandler(handlers=handlers)
515
-
516
- result = await handler.wait_for_terminal_exit("s1", "term-1")
517
-
518
- mock_wait.assert_called_once_with("term-1")
519
- assert result == {"exitCode": 0}
520
-
521
- @pytest.mark.asyncio
522
- async def test_should_delegate_to_kill_terminal_handler(self) -> None:
523
- """Delegates to kill_terminal handler."""
524
- mock_kill = AsyncMock()
525
- handlers = ClientHandlers(on_terminal_kill=mock_kill)
526
- handler = ACPClientHandler(handlers=handlers)
527
-
528
- result = await handler.kill_terminal("s1", "term-1")
529
-
530
- mock_kill.assert_called_once_with("term-1")
531
- assert result == {}
532
-
533
- @pytest.mark.asyncio
534
- async def test_should_delegate_to_release_terminal_handler(self) -> None:
535
- """Delegates to release_terminal handler."""
536
- mock_release = AsyncMock()
537
- handlers = ClientHandlers(on_terminal_release=mock_release)
538
- handler = ACPClientHandler(handlers=handlers)
539
-
540
- result = await handler.release_terminal("s1", "term-1")
541
-
542
- mock_release.assert_called_once_with("term-1")
543
- assert result == {}