commandmate 0.22.2 → 0.23.0

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 (476) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +108 -108
  3. package/.next/app-path-routes-manifest.json +21 -21
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +12 -12
  6. package/.next/required-server-files.json +1 -1
  7. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  8. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/app/update-check/route.js +1 -1
  10. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/assistant/conversation/route.js +1 -1
  12. package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
  13. package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
  14. package/.next/server/app/api/assistant/current-output/route.js +1 -1
  15. package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
  16. package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/assistant/messages/route.js +1 -1
  18. package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
  19. package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
  20. package/.next/server/app/api/assistant/session/route.js +1 -1
  21. package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
  22. package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/assistant/start/route.js +1 -1
  24. package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
  25. package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/assistant/terminal/route.js +3 -3
  27. package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
  28. package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
  29. package/.next/server/app/api/assistant/tools/route.js +1 -1
  30. package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
  31. package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
  32. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/daily-summary/route.js +1 -1
  36. package/.next/server/app/api/daily-summary/route.js.nft.json +1 -1
  37. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  38. package/.next/server/app/api/daily-summary/status/route.js +1 -1
  39. package/.next/server/app/api/daily-summary/status/route.js.nft.json +1 -1
  40. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  41. package/.next/server/app/api/external-apps/[id]/health/route.js +1 -1
  42. package/.next/server/app/api/external-apps/[id]/health/route.js.nft.json +1 -1
  43. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/external-apps/[id]/route.js +1 -1
  45. package/.next/server/app/api/external-apps/[id]/route.js.nft.json +1 -1
  46. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  47. package/.next/server/app/api/external-apps/route.js +1 -1
  48. package/.next/server/app/api/external-apps/route.js.nft.json +1 -1
  49. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/fs/browse/route.js +1 -1
  51. package/.next/server/app/api/fs/browse/route.js.nft.json +1 -1
  52. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  53. package/.next/server/app/api/fs/recent-paths/route.js +1 -1
  54. package/.next/server/app/api/fs/recent-paths/route.js.nft.json +1 -1
  55. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/hooks/agent-event/route.js +1 -1
  57. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  58. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/hooks/claude-done/route.js +1 -1
  60. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  61. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  63. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  64. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  65. package/.next/server/app/api/metrics/vibe/route.js +1 -1
  66. package/.next/server/app/api/metrics/vibe/route.js.nft.json +1 -1
  67. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  68. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/push/subscriptions/route.js +1 -1
  70. package/.next/server/app/api/push/subscriptions/route.js.nft.json +1 -1
  71. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  72. package/.next/server/app/api/push/vapid/route.js +1 -1
  73. package/.next/server/app/api/push/vapid/route.js.nft.json +1 -1
  74. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  75. package/.next/server/app/api/repositories/[id]/route.js +1 -1
  76. package/.next/server/app/api/repositories/[id]/route.js.nft.json +1 -1
  77. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  78. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route.js +1 -1
  79. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route.js.nft.json +1 -1
  80. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/repositories/[id]/todos/route.js +1 -1
  82. package/.next/server/app/api/repositories/[id]/todos/route.js.nft.json +1 -1
  83. package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  85. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  86. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/repositories/clone/route.js +1 -1
  88. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  89. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/repositories/excluded/route.js +1 -1
  91. package/.next/server/app/api/repositories/excluded/route.js.nft.json +1 -1
  92. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/repositories/restore/route.js +1 -1
  94. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  95. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/repositories/route.js +1 -1
  97. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  98. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/repositories/scan/route.js +1 -1
  100. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  101. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/repositories/sync/route.js +1 -1
  103. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  104. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/repositories/validate-path/route.js +1 -1
  106. package/.next/server/app/api/repositories/validate-path/route.js.nft.json +1 -1
  107. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/sidebar/group-order/route.js +1 -1
  109. package/.next/server/app/api/sidebar/group-order/route.js.nft.json +1 -1
  110. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  112. package/.next/server/app/api/skills/installations/route.js +1 -1
  113. package/.next/server/app/api/skills/installations/route.js.nft.json +1 -1
  114. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/skills/operations/route.js +1 -1
  116. package/.next/server/app/api/skills/operations/route.js.nft.json +1 -1
  117. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  118. package/.next/server/app/api/skills/reindex/route.js +1 -1
  119. package/.next/server/app/api/skills/reindex/route.js.nft.json +1 -1
  120. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  122. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/tasks/[taskId]/cancel/route.js +1 -4
  124. package/.next/server/app/api/tasks/[taskId]/cancel/route.js.nft.json +1 -1
  125. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/tasks/[taskId]/route.js +1 -4
  127. package/.next/server/app/api/tasks/[taskId]/route.js.nft.json +1 -1
  128. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/templates/[id]/route.js +1 -1
  130. package/.next/server/app/api/templates/[id]/route.js.nft.json +1 -1
  131. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/templates/route.js +1 -1
  133. package/.next/server/app/api/templates/route.js.nft.json +1 -1
  134. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/todos/route.js +1 -1
  136. package/.next/server/app/api/todos/route.js.nft.json +1 -1
  137. package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
  138. package/.next/server/app/api/verification/runs/[runId]/route.js +1 -1
  139. package/.next/server/app/api/verification/runs/[runId]/route.js.nft.json +1 -1
  140. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/verification/runs/route.js +1 -1
  142. package/.next/server/app/api/verification/runs/route.js.nft.json +1 -1
  143. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  146. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  149. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js.nft.json +1 -1
  152. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +2 -2
  154. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js.nft.json +1 -1
  155. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  158. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js.nft.json +1 -1
  161. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +2 -2
  163. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js.nft.json +1 -1
  164. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js.nft.json +1 -1
  167. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/git/branch/create/route.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/git/branch/create/route.js.nft.json +1 -1
  170. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route.js.nft.json +1 -1
  173. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/git/branches/route.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/git/branches/route.js.nft.json +1 -1
  176. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  177. package/.next/server/app/api/worktrees/[id]/git/checkout/route.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/git/checkout/route.js.nft.json +1 -1
  179. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  180. package/.next/server/app/api/worktrees/[id]/git/commit/route.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/git/commit/route.js.nft.json +1 -1
  182. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/git/diff/route.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/git/diff/route.js.nft.json +1 -1
  185. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  186. package/.next/server/app/api/worktrees/[id]/git/fetch/route.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/git/fetch/route.js.nft.json +1 -1
  188. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/git/log/route.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/git/log/route.js.nft.json +1 -1
  191. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/git/pull/route.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/git/pull/route.js.nft.json +1 -1
  194. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/git/push/route.js +1 -1
  196. package/.next/server/app/api/worktrees/[id]/git/push/route.js.nft.json +1 -1
  197. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/git/reset/route.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/git/reset/route.js.nft.json +1 -1
  200. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/git/revert/route.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/git/revert/route.js.nft.json +1 -1
  203. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route.js.nft.json +1 -1
  206. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  207. package/.next/server/app/api/worktrees/[id]/git/stage/route.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/git/stage/route.js.nft.json +1 -1
  209. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/git/staged/route.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/git/staged/route.js.nft.json +1 -1
  212. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route.js.nft.json +1 -1
  215. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route.js +1 -1
  217. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route.js.nft.json +1 -1
  218. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  219. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route.js +1 -1
  220. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route.js.nft.json +1 -1
  221. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  222. package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js +1 -1
  223. package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js.nft.json +1 -1
  224. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  225. package/.next/server/app/api/worktrees/[id]/git/stash/route.js +1 -1
  226. package/.next/server/app/api/worktrees/[id]/git/stash/route.js.nft.json +1 -1
  227. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/api/worktrees/[id]/git/status/route.js +1 -1
  229. package/.next/server/app/api/worktrees/[id]/git/status/route.js.nft.json +1 -1
  230. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  231. package/.next/server/app/api/worktrees/[id]/git/unstage/route.js +1 -1
  232. package/.next/server/app/api/worktrees/[id]/git/unstage/route.js.nft.json +1 -1
  233. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  234. package/.next/server/app/api/worktrees/[id]/git/working-diff/route.js +1 -1
  235. package/.next/server/app/api/worktrees/[id]/git/working-diff/route.js.nft.json +1 -1
  236. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  237. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  238. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  239. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  240. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  241. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  242. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  243. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js +1 -1
  244. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js.nft.json +1 -1
  245. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  246. package/.next/server/app/api/worktrees/[id]/logs/route.js +1 -1
  247. package/.next/server/app/api/worktrees/[id]/logs/route.js.nft.json +1 -1
  248. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  249. package/.next/server/app/api/worktrees/[id]/marp-render/route.js +3 -3
  250. package/.next/server/app/api/worktrees/[id]/marp-render/route.js.nft.json +1 -1
  251. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  252. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -1
  253. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js.nft.json +1 -1
  254. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  255. package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -1
  256. package/.next/server/app/api/worktrees/[id]/memos/route.js.nft.json +1 -1
  257. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  258. package/.next/server/app/api/worktrees/[id]/messages/route.js +1 -1
  259. package/.next/server/app/api/worktrees/[id]/messages/route.js.nft.json +1 -1
  260. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  261. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  262. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  263. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  264. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  265. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  266. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  267. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  268. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  269. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  270. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +2 -2
  271. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +1 -1
  272. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  273. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +1 -1
  274. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +1 -1
  275. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  276. package/.next/server/app/api/worktrees/[id]/schedules/route.js +3 -3
  277. package/.next/server/app/api/worktrees/[id]/schedules/route.js.nft.json +1 -1
  278. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  279. package/.next/server/app/api/worktrees/[id]/search/route.js +1 -1
  280. package/.next/server/app/api/worktrees/[id]/search/route.js.nft.json +1 -1
  281. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  282. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  283. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  284. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  285. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +1 -1
  286. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  287. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  288. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route.js +1 -1
  289. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route.js.nft.json +1 -1
  290. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  291. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route.js +1 -1
  292. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route.js.nft.json +1 -1
  293. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  294. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route.js +1 -1
  295. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route.js.nft.json +1 -1
  296. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  297. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route.js +1 -1
  298. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route.js.nft.json +1 -1
  299. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  300. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route.js +1 -1
  301. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route.js.nft.json +1 -1
  302. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  303. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route.js +1 -1
  304. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route.js.nft.json +1 -1
  305. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  306. package/.next/server/app/api/worktrees/[id]/skills/route.js +1 -1
  307. package/.next/server/app/api/worktrees/[id]/skills/route.js.nft.json +1 -1
  308. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  309. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  310. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js.nft.json +1 -1
  311. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  312. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  313. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  314. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  315. package/.next/server/app/api/worktrees/[id]/start-polling/route.js +1 -1
  316. package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +1 -1
  317. package/.next/server/app/api/worktrees/[id]/start-polling/route_client-reference-manifest.js +1 -1
  318. package/.next/server/app/api/worktrees/[id]/tasks/route.js +2 -2
  319. package/.next/server/app/api/worktrees/[id]/tasks/route.js.nft.json +1 -1
  320. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  321. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
  322. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  323. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  324. package/.next/server/app/api/worktrees/[id]/timers/history/route.js +1 -1
  325. package/.next/server/app/api/worktrees/[id]/timers/history/route.js.nft.json +1 -1
  326. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  327. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  328. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  329. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  330. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js +1 -1
  331. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js.nft.json +1 -1
  332. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  333. package/.next/server/app/api/worktrees/[id]/todos/route.js +1 -1
  334. package/.next/server/app/api/worktrees/[id]/todos/route.js.nft.json +1 -1
  335. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  336. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js +1 -1
  337. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js.nft.json +1 -1
  338. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  339. package/.next/server/app/api/worktrees/[id]/tree/route.js +1 -1
  340. package/.next/server/app/api/worktrees/[id]/tree/route.js.nft.json +1 -1
  341. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  342. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route.js +1 -1
  343. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route.js.nft.json +1 -1
  344. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  345. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -4
  346. package/.next/server/app/api/worktrees/[id]/verify/route.js.nft.json +1 -1
  347. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  348. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route.js +1 -1
  349. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route.js.nft.json +1 -1
  350. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  351. package/.next/server/app/api/worktrees/[id]/verify/runs/route.js +1 -1
  352. package/.next/server/app/api/worktrees/[id]/verify/runs/route.js.nft.json +1 -1
  353. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  354. package/.next/server/app/api/worktrees/[id]/viewed/route.js +1 -1
  355. package/.next/server/app/api/worktrees/[id]/viewed/route.js.nft.json +1 -1
  356. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  357. package/.next/server/app/api/worktrees/route.js +1 -1
  358. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  359. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  360. package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  361. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  362. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  363. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  364. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  365. package/.next/server/app/page_client-reference-manifest.js +1 -1
  366. package/.next/server/app/proxy/[...path]/route.js +1 -1
  367. package/.next/server/app/proxy/[...path]/route.js.nft.json +1 -1
  368. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  369. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  370. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  371. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  372. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  373. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  374. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  375. package/.next/server/app/worktrees/[id]/files/[...path]/page.js +1 -1
  376. package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +1 -1
  377. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  378. package/.next/server/app/worktrees/[id]/page.js +2 -2
  379. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  380. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  381. package/.next/server/app/worktrees/[id]/terminal/page.js +1 -1
  382. package/.next/server/app/worktrees/[id]/terminal/page.js.nft.json +1 -1
  383. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  384. package/.next/server/app-paths-manifest.json +21 -21
  385. package/.next/server/chunks/1029.js +1 -1
  386. package/.next/server/chunks/1068.js +1 -1
  387. package/.next/server/chunks/2119.js +1 -1
  388. package/.next/server/chunks/2404.js +1 -1
  389. package/.next/server/chunks/2445.js +1 -1
  390. package/.next/server/chunks/2546.js +1 -1
  391. package/.next/server/chunks/3241.js +1 -0
  392. package/.next/server/chunks/3417.js +1 -1
  393. package/.next/server/chunks/406.js +10 -6
  394. package/.next/server/chunks/4444.js +1 -1
  395. package/.next/server/chunks/5959.js +4 -5
  396. package/.next/server/chunks/5998.js +1 -12
  397. package/.next/server/chunks/6130.js +1 -1
  398. package/.next/server/chunks/6274.js +3 -3
  399. package/.next/server/chunks/6401.js +1 -1
  400. package/.next/server/chunks/6781.js +1 -0
  401. package/.next/server/chunks/7458.js +6 -0
  402. package/.next/server/chunks/{3753.js → 7970.js} +57 -32
  403. package/.next/server/chunks/8536.js +1 -1
  404. package/.next/server/chunks/8807.js +180 -127
  405. package/.next/server/chunks/9058.js +1 -1
  406. package/.next/server/chunks/9067.js +1 -1
  407. package/.next/server/chunks/9360.js +1 -1
  408. package/.next/server/chunks/9687.js +2 -2
  409. package/.next/server/middleware-manifest.json +5 -5
  410. package/.next/server/pages/500.html +1 -1
  411. package/.next/server/server-reference-manifest.json +1 -1
  412. package/.next/server/src/middleware.js.map +1 -1
  413. package/.next/static/chunks/{6488-53a3e1d78e4fe8f7.js → 6488-95ba9d24a76f0cc5.js} +1 -1
  414. package/.next/static/chunks/app/worktrees/[id]/{page-6dc0b8c4e808ea3e.js → page-966a451ae7b0903a.js} +1 -1
  415. package/.next/trace +12 -12
  416. package/dist/server/src/config/log-config.js +10 -1
  417. package/dist/server/src/config/safe-directory.js +103 -0
  418. package/dist/server/src/config/system-directories.js +74 -9
  419. package/dist/server/src/lib/cli-tools/antigravity.js +19 -2
  420. package/dist/server/src/lib/cli-tools/codex.js +95 -1
  421. package/dist/server/src/lib/cli-tools/copilot.js +30 -1
  422. package/dist/server/src/lib/cli-tools/gemini.js +28 -2
  423. package/dist/server/src/lib/cli-tools/opencode.js +51 -2
  424. package/dist/server/src/lib/git/git-default-branch.js +59 -0
  425. package/dist/server/src/lib/hooks/agent-event-service.js +205 -0
  426. package/dist/server/src/lib/hooks/agent-event-types.js +7 -86
  427. package/dist/server/src/lib/hooks/hook-settings-generator.js +26 -11
  428. package/dist/server/src/lib/hooks/permission-decision-service.js +269 -0
  429. package/dist/server/src/lib/hooks/sources/abstain.js +78 -0
  430. package/dist/server/src/lib/hooks/sources/antigravity/hooks-config.js +372 -0
  431. package/dist/server/src/lib/hooks/sources/antigravity/source.js +225 -0
  432. package/dist/server/src/lib/hooks/sources/antigravity/tool-id.js +16 -0
  433. package/dist/server/src/lib/hooks/sources/claude/source.js +143 -0
  434. package/dist/server/src/lib/hooks/sources/claude/tool-id.js +18 -0
  435. package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +465 -0
  436. package/dist/server/src/lib/hooks/sources/codex/source.js +138 -0
  437. package/dist/server/src/lib/hooks/sources/codex/tool-id.js +15 -0
  438. package/dist/server/src/lib/hooks/sources/copilot/hook-settings.js +473 -0
  439. package/dist/server/src/lib/hooks/sources/copilot/source.js +210 -0
  440. package/dist/server/src/lib/hooks/sources/copilot/tool-id.js +15 -0
  441. package/dist/server/src/lib/hooks/sources/define-source.js +169 -0
  442. package/dist/server/src/lib/hooks/sources/event-mapper.js +157 -0
  443. package/dist/server/src/lib/hooks/sources/gemini/event-vocabulary.js +102 -0
  444. package/dist/server/src/lib/hooks/sources/gemini/settings-generator.js +315 -0
  445. package/dist/server/src/lib/hooks/sources/gemini/shared-config-tree.js +103 -0
  446. package/dist/server/src/lib/hooks/sources/gemini/source.js +151 -0
  447. package/dist/server/src/lib/hooks/sources/gemini/tool-id.js +17 -0
  448. package/dist/server/src/lib/hooks/sources/hook-event-vocabulary.js +111 -0
  449. package/dist/server/src/lib/hooks/sources/index.js +62 -0
  450. package/dist/server/src/lib/hooks/sources/legacy-relay.js +84 -0
  451. package/dist/server/src/lib/hooks/sources/opencode/client.js +299 -0
  452. package/dist/server/src/lib/hooks/sources/opencode/ingest.js +261 -0
  453. package/dist/server/src/lib/hooks/sources/opencode/mappers.js +154 -0
  454. package/dist/server/src/lib/hooks/sources/opencode/payloads.js +189 -0
  455. package/dist/server/src/lib/hooks/sources/opencode/ports.js +295 -0
  456. package/dist/server/src/lib/hooks/sources/opencode/runtime.js +159 -0
  457. package/dist/server/src/lib/hooks/sources/opencode/source.js +250 -0
  458. package/dist/server/src/lib/hooks/sources/opencode/subscription.js +422 -0
  459. package/dist/server/src/lib/hooks/sources/opencode/tool-id.js +14 -0
  460. package/dist/server/src/lib/hooks/sources/opencode/turn-gate.js +193 -0
  461. package/dist/server/src/lib/hooks/sources/pending-decisions.js +127 -0
  462. package/dist/server/src/lib/hooks/sources/registry.js +111 -0
  463. package/dist/server/src/lib/hooks/sources/types.js +46 -0
  464. package/dist/server/src/lib/session/agent-session-lifecycle.js +82 -0
  465. package/dist/server/src/lib/session/claude-session.js +10 -3
  466. package/dist/server/src/lib/tasks/contract-message.js +175 -0
  467. package/dist/server/src/lib/verification/env-clean-gate.js +320 -0
  468. package/dist/server/src/lib/verification/env-snapshot.js +474 -0
  469. package/dist/server/src/lib/verification/gate-runner.js +802 -0
  470. package/dist/server/src/lib/verification/scope-gate.js +402 -0
  471. package/dist/server/src/lib/verification/verify-config.js +281 -0
  472. package/package.json +1 -1
  473. package/scripts/hooks/cmate-agent-event.sh +73 -3
  474. package/.next/server/chunks/8856.js +0 -4
  475. /package/.next/static/{XpKfn5x6H-mtTaXI9yNmb → wH6K6QNPHSdATFkVoIcy3}/_buildManifest.js +0 -0
  476. /package/.next/static/{XpKfn5x6H-mtTaXI9yNmb → wH6K6QNPHSdATFkVoIcy3}/_ssgManifest.js +0 -0
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ /**
3
+ * The hook spellings and payload field names that several agent CLIs happen to
4
+ * share (Issue #1759, S1/S2 lifted out of `agent-event-types`).
5
+ *
6
+ * `agent-event-types` used to carry `CLAUDE_HOOK_EVENT_NAMES` and
7
+ * `extractClaudeEventDetail` next to the seven-word vocabulary. That put one
8
+ * tool's spelling inside the module every tool-agnostic consumer imports, and
9
+ * the predictable next move — a Phase 4-2 implementer adding `BeforeTool` to
10
+ * the same table — is exactly the copy-paste Epic #1720 exists to stop. The
11
+ * words stayed in `agent-event-types`; the spellings moved here, where a source
12
+ * *chooses* them.
13
+ *
14
+ * The table below is not "Claude's table". #1757 §8.1 measured all four new
15
+ * tools, and Claude, codex and copilot spell these events identically; gemini
16
+ * renames half of them (`BeforeTool` / `AfterTool` / `BeforeAgent` /
17
+ * `AfterAgent`) and antigravity ships no event-name field at all. So this is
18
+ * the CamelCase dialect three tools share, and a source that speaks a different
19
+ * one brings its own mappers.
20
+ *
21
+ * @module lib/hooks/sources/hook-event-vocabulary
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.TOOL_CALL_ID_FIELDS = exports.SESSION_ID_FIELDS = exports.CAMEL_CASE_HOOK_EVENT_NAMES = void 0;
25
+ exports.extractSnakeCaseEventDetail = extractSnakeCaseEventDetail;
26
+ const event_mapper_1 = require("./event-mapper");
27
+ /**
28
+ * `hook_event_name` values, in the CamelCase dialect Claude / codex / copilot
29
+ * share, mapped onto the seven words.
30
+ *
31
+ * Only the events CommandMate registers appear. An unmapped name is refused
32
+ * rather than filed under something adjacent — the whole value of a structured
33
+ * event is that it says precisely what happened.
34
+ *
35
+ * `PermissionRequest` is deliberately absent: its response body is a decision
36
+ * the agent obeys, which is the opposite contract to the fire-and-forget event
37
+ * route (#1724). It travels through {@link AgentEventSource.encodeVerdict}.
38
+ *
39
+ * `PostToolUse` is here on the strength of a measurement taken for #1726 rather
40
+ * than of the #1721 spike, which recorded it as unobserved. Driving a live
41
+ * Claude v2.1.223 session on 2026-08-06 with a `PostToolUse` hook registered:
42
+ *
43
+ * ```
44
+ * 15:36:04.112 PreToolUse AskUserQuestion (picker drawn)
45
+ * 15:36:10.127 Notification permission_prompt (picker still up)
46
+ * 15:36:28.643 PostToolUse AskUserQuestion (the human answered)
47
+ * 15:36:29.992 Stop
48
+ * ```
49
+ *
50
+ * It fires, and it is the precise signal — "this tool call is over" — where
51
+ * `Stop` is "the turn is over" and can be minutes later if the agent keeps
52
+ * working after the answer.
53
+ */
54
+ exports.CAMEL_CASE_HOOK_EVENT_NAMES = {
55
+ Stop: 'stop',
56
+ SubagentStop: 'stop',
57
+ Notification: 'notification',
58
+ SessionStart: 'session_start',
59
+ SessionEnd: 'session_end',
60
+ UserPromptSubmit: 'user_prompt_submit',
61
+ // Issue #1726. Injected with matcher `AskUserQuestion`, so in practice these
62
+ // only ever arrive for that tool — but a receiver re-reads `tool_name` rather
63
+ // than trusting the matcher, because a user's own settings.json is
64
+ // concatenated with the injected one and may register a wider matcher.
65
+ PreToolUse: 'pre_tool_use',
66
+ PostToolUse: 'post_tool_use',
67
+ };
68
+ /**
69
+ * Payload keys that carry the agent's own session id, in preference order
70
+ * (#1757 R4).
71
+ *
72
+ * `session_id` covers Claude, codex, copilot and gemini; `conversationId` is
73
+ * antigravity's protojson spelling of the same thing. Never an identity key —
74
+ * `/clear` mints a new one while the instance is unchanged (#1721).
75
+ */
76
+ exports.SESSION_ID_FIELDS = ['session_id', 'conversationId'];
77
+ /**
78
+ * Payload keys that correlate one tool call (#1757 R5).
79
+ *
80
+ * `tool_use_id` is Claude's and codex's; it is absent from `PermissionRequest`
81
+ * on both (D2), so nothing may require it.
82
+ */
83
+ exports.TOOL_CALL_ID_FIELDS = ['tool_use_id'];
84
+ /**
85
+ * The event's subtype for a snake_case payload, or null when it has none.
86
+ *
87
+ * Each event spells this differently and none of them share a field:
88
+ *
89
+ * - `Notification` → `notification_type` (`permission_prompt` / `idle_prompt`).
90
+ * This is also what a `Notification` matcher is tested against — **not**
91
+ * `message`, which is English prose for a human (#1721 D3).
92
+ * - `SessionEnd` → `reason` (`clear` / `prompt_input_exit` / …)
93
+ * - `SessionStart` → `source` (`startup` / `clear` / …)
94
+ * - `PreToolUse` / `PostToolUse` → `tool_name` (`AskUserQuestion`), Issue #1726
95
+ *
96
+ * `stop` and `user_prompt_submit` have no subtype, so they answer null.
97
+ */
98
+ function extractSnakeCaseEventDetail(event, payload) {
99
+ const field = event === 'notification'
100
+ ? 'notification_type'
101
+ : event === 'session_end'
102
+ ? 'reason'
103
+ : event === 'session_start'
104
+ ? 'source'
105
+ : event === 'pre_tool_use' || event === 'post_tool_use'
106
+ ? 'tool_name'
107
+ : null;
108
+ if (field === null)
109
+ return null;
110
+ return (0, event_mapper_1.boundDetail)((0, event_mapper_1.readStringField)(payload, field));
111
+ }
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ /**
3
+ * `AgentEventSource` — the public surface (Issue #1759).
4
+ *
5
+ * Import from here rather than from the files underneath. Importing `./registry`
6
+ * is what registers the built-in sources, so this barrel is also the guarantee
7
+ * that a caller who reached for the types got the implementations too.
8
+ *
9
+ * The spec this implements is `docs/design/agent-event-source-interface.md`,
10
+ * which also carries the checklist for adding a tool.
11
+ *
12
+ * @module lib/hooks/sources
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.OPENCODE_CLI_TOOL_ID = exports.CODEX_CLI_TOOL_ID = exports.ANTIGRAVITY_CLI_TOOL_ID = exports.GEMINI_CLI_TOOL_ID = exports.COPILOT_CLI_TOOL_ID = exports.CLAUDE_CLI_TOOL_ID = exports.isAbstainSafe = exports.describeNoDecision = exports.describeAbstain = exports.resetPendingDecisions = exports.openDecisionSlot = exports.listOpenDecisions = exports.closeDecisionSlot = exports.answerPendingDecision = exports.TOOL_CALL_ID_FIELDS = exports.SESSION_ID_FIELDS = exports.extractSnakeCaseEventDetail = exports.CAMEL_CASE_HOOK_EVENT_NAMES = exports.whenNamed = exports.runEventMappers = exports.resetUnknownEventTallies = exports.readStringField = exports.readNestedString = exports.readFirstStringField = exports.isPlainObject = exports.getUnknownEventTally = exports.fromNameTable = exports.boundDetail = exports.definePushHookSource = exports.definePullEventSource = exports.unregisterAgentEventSource = exports.registerAgentEventSource = exports.listAgentEventSources = exports.hasAgentEventSource = exports.getAgentEventSource = void 0;
16
+ var registry_1 = require("./registry");
17
+ Object.defineProperty(exports, "getAgentEventSource", { enumerable: true, get: function () { return registry_1.getAgentEventSource; } });
18
+ Object.defineProperty(exports, "hasAgentEventSource", { enumerable: true, get: function () { return registry_1.hasAgentEventSource; } });
19
+ Object.defineProperty(exports, "listAgentEventSources", { enumerable: true, get: function () { return registry_1.listAgentEventSources; } });
20
+ Object.defineProperty(exports, "registerAgentEventSource", { enumerable: true, get: function () { return registry_1.registerAgentEventSource; } });
21
+ Object.defineProperty(exports, "unregisterAgentEventSource", { enumerable: true, get: function () { return registry_1.unregisterAgentEventSource; } });
22
+ var define_source_1 = require("./define-source");
23
+ Object.defineProperty(exports, "definePullEventSource", { enumerable: true, get: function () { return define_source_1.definePullEventSource; } });
24
+ Object.defineProperty(exports, "definePushHookSource", { enumerable: true, get: function () { return define_source_1.definePushHookSource; } });
25
+ var event_mapper_1 = require("./event-mapper");
26
+ Object.defineProperty(exports, "boundDetail", { enumerable: true, get: function () { return event_mapper_1.boundDetail; } });
27
+ Object.defineProperty(exports, "fromNameTable", { enumerable: true, get: function () { return event_mapper_1.fromNameTable; } });
28
+ Object.defineProperty(exports, "getUnknownEventTally", { enumerable: true, get: function () { return event_mapper_1.getUnknownEventTally; } });
29
+ Object.defineProperty(exports, "isPlainObject", { enumerable: true, get: function () { return event_mapper_1.isPlainObject; } });
30
+ Object.defineProperty(exports, "readFirstStringField", { enumerable: true, get: function () { return event_mapper_1.readFirstStringField; } });
31
+ Object.defineProperty(exports, "readNestedString", { enumerable: true, get: function () { return event_mapper_1.readNestedString; } });
32
+ Object.defineProperty(exports, "readStringField", { enumerable: true, get: function () { return event_mapper_1.readStringField; } });
33
+ Object.defineProperty(exports, "resetUnknownEventTallies", { enumerable: true, get: function () { return event_mapper_1.resetUnknownEventTallies; } });
34
+ Object.defineProperty(exports, "runEventMappers", { enumerable: true, get: function () { return event_mapper_1.runEventMappers; } });
35
+ Object.defineProperty(exports, "whenNamed", { enumerable: true, get: function () { return event_mapper_1.whenNamed; } });
36
+ var hook_event_vocabulary_1 = require("./hook-event-vocabulary");
37
+ Object.defineProperty(exports, "CAMEL_CASE_HOOK_EVENT_NAMES", { enumerable: true, get: function () { return hook_event_vocabulary_1.CAMEL_CASE_HOOK_EVENT_NAMES; } });
38
+ Object.defineProperty(exports, "extractSnakeCaseEventDetail", { enumerable: true, get: function () { return hook_event_vocabulary_1.extractSnakeCaseEventDetail; } });
39
+ Object.defineProperty(exports, "SESSION_ID_FIELDS", { enumerable: true, get: function () { return hook_event_vocabulary_1.SESSION_ID_FIELDS; } });
40
+ Object.defineProperty(exports, "TOOL_CALL_ID_FIELDS", { enumerable: true, get: function () { return hook_event_vocabulary_1.TOOL_CALL_ID_FIELDS; } });
41
+ var pending_decisions_1 = require("./pending-decisions");
42
+ Object.defineProperty(exports, "answerPendingDecision", { enumerable: true, get: function () { return pending_decisions_1.answerPendingDecision; } });
43
+ Object.defineProperty(exports, "closeDecisionSlot", { enumerable: true, get: function () { return pending_decisions_1.closeDecisionSlot; } });
44
+ Object.defineProperty(exports, "listOpenDecisions", { enumerable: true, get: function () { return pending_decisions_1.listOpenDecisions; } });
45
+ Object.defineProperty(exports, "openDecisionSlot", { enumerable: true, get: function () { return pending_decisions_1.openDecisionSlot; } });
46
+ Object.defineProperty(exports, "resetPendingDecisions", { enumerable: true, get: function () { return pending_decisions_1.resetPendingDecisions; } });
47
+ var abstain_1 = require("./abstain");
48
+ Object.defineProperty(exports, "describeAbstain", { enumerable: true, get: function () { return abstain_1.describeAbstain; } });
49
+ Object.defineProperty(exports, "describeNoDecision", { enumerable: true, get: function () { return abstain_1.describeNoDecision; } });
50
+ Object.defineProperty(exports, "isAbstainSafe", { enumerable: true, get: function () { return abstain_1.isAbstainSafe; } });
51
+ var tool_id_1 = require("./claude/tool-id");
52
+ Object.defineProperty(exports, "CLAUDE_CLI_TOOL_ID", { enumerable: true, get: function () { return tool_id_1.CLAUDE_CLI_TOOL_ID; } });
53
+ var tool_id_2 = require("./copilot/tool-id");
54
+ Object.defineProperty(exports, "COPILOT_CLI_TOOL_ID", { enumerable: true, get: function () { return tool_id_2.COPILOT_CLI_TOOL_ID; } });
55
+ var tool_id_3 = require("./gemini/tool-id");
56
+ Object.defineProperty(exports, "GEMINI_CLI_TOOL_ID", { enumerable: true, get: function () { return tool_id_3.GEMINI_CLI_TOOL_ID; } });
57
+ var tool_id_4 = require("./antigravity/tool-id");
58
+ Object.defineProperty(exports, "ANTIGRAVITY_CLI_TOOL_ID", { enumerable: true, get: function () { return tool_id_4.ANTIGRAVITY_CLI_TOOL_ID; } });
59
+ var tool_id_5 = require("./codex/tool-id");
60
+ Object.defineProperty(exports, "CODEX_CLI_TOOL_ID", { enumerable: true, get: function () { return tool_id_5.CODEX_CLI_TOOL_ID; } });
61
+ var tool_id_6 = require("./opencode/tool-id");
62
+ Object.defineProperty(exports, "OPENCODE_CLI_TOOL_ID", { enumerable: true, get: function () { return tool_id_6.OPENCODE_CLI_TOOL_ID; } });
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ /**
3
+ * The source used for a tool that has no source yet (Issue #1759).
4
+ *
5
+ * `POST /api/hooks/agent-event` has accepted `{"tool":"codex","event":"stop"}`
6
+ * since #1549, from hooks operators wired up by hand following
7
+ * `docs/user-guide/agent-event-hooks.md`. Those requests work today, and Phase
8
+ * 4-1 is a refactor: if asking the registry for an unregistered tool returned
9
+ * nothing, every one of them would start failing on the day this abstraction
10
+ * landed, for a reason that has nothing to do with what changed.
11
+ *
12
+ * So an unregistered tool gets this: the CamelCase name table and the
13
+ * snake_case subtype extraction that the receiver applied to every tool before
14
+ * the abstraction existed, which is exactly the behaviour being preserved. It
15
+ * is *not* a claim that the table is right for that tool — gemini spells four
16
+ * of the seven differently and antigravity spells none of them — only that a
17
+ * hook posting `{"event":"stop"}` keeps working while its tool waits for Phase
18
+ * 4-2…4-5.
19
+ *
20
+ * Its capabilities say so: `supportedEvents` is empty, which is the honest
21
+ * answer to "what does this tool emit?" when nobody has measured it. A caller
22
+ * that consults capabilities gets "unknown", not a confident wrong answer.
23
+ *
24
+ * Registering a real source for a tool replaces this automatically; there is no
25
+ * list to remove it from.
26
+ *
27
+ * @module lib/hooks/sources/legacy-relay
28
+ */
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.createLegacyRelaySource = createLegacyRelaySource;
31
+ const ask_user_question_payload_1 = require("../../../lib/hooks/ask-user-question-payload");
32
+ const permission_request_payload_1 = require("../../../lib/hooks/permission-request-payload");
33
+ const source_1 = require("./claude/source");
34
+ const define_source_1 = require("./define-source");
35
+ const event_mapper_1 = require("./event-mapper");
36
+ const hook_event_vocabulary_1 = require("./hook-event-vocabulary");
37
+ /**
38
+ * Build the compatibility source for one tool.
39
+ *
40
+ * @param cliToolId - The tool nobody has written a source for yet
41
+ */
42
+ function createLegacyRelaySource(cliToolId) {
43
+ return (0, define_source_1.definePushHookSource)({
44
+ cliToolId,
45
+ // The conservative reading, and the one that is true of the relay path this
46
+ // stands in for: a hook whose server does not answer is fail-open on every
47
+ // tool measured so far (#1757 §1.2). It is stated rather than inherited so
48
+ // that a tool where it is false — antigravity — cannot quietly ride on it;
49
+ // that tool gets a real source in Phase 4-4, with its own value.
50
+ noDecision: { kind: 'proceeds' },
51
+ capabilities: {
52
+ // Deliberately empty. Nothing has been measured for this tool through
53
+ // this path, and an empty list reads as "unknown" where a copy of
54
+ // Claude's list would read as a promise.
55
+ supportedEvents: [],
56
+ configScope: 'none',
57
+ decisionTimeoutSeconds: null,
58
+ },
59
+ mappers: (0, event_mapper_1.fromNameTable)(hook_event_vocabulary_1.CAMEL_CASE_HOOK_EVENT_NAMES),
60
+ nativeEventNameFields: ['hook_event_name'],
61
+ conversationIdFields: hook_event_vocabulary_1.SESSION_ID_FIELDS,
62
+ toolCallIdFields: hook_event_vocabulary_1.TOOL_CALL_ID_FIELDS,
63
+ extractDetail: hook_event_vocabulary_1.extractSnakeCaseEventDetail,
64
+ // Both receivers applied these parsers to every tool before #1759, so both
65
+ // stay wired here. They are strict — a payload that is not in Claude's
66
+ // shape answers null, which becomes "no structured data" / "no decision" —
67
+ // so applying them to a tool whose shape is unknown costs nothing and
68
+ // changes no behaviour that existed on the day this file landed.
69
+ parsePermissionRequest: (payload) => (0, permission_request_payload_1.parsePermissionRequestPayload)(payload),
70
+ parseQuestion: (payload) => (0, ask_user_question_payload_1.parseAskUserQuestionPayload)(payload),
71
+ // Likewise the verdict body: the permission receiver emitted Claude's shape
72
+ // for whatever tool reached it. **A real source must override this.**
73
+ // antigravity in particular reads an empty object as a denial and stops the
74
+ // tool call (#1757 P10), so Phase 4-4 has to encode abstention positively
75
+ // rather than inherit anything from here.
76
+ encodeVerdict: source_1.encodeClaudeVerdict,
77
+ // CommandMate does not inject config for these tools; their `startSession`
78
+ // in `src/lib/cli-tools/<tool>.ts` launches them bare.
79
+ prepareLaunch: (_target, executablePath) => ({
80
+ command: executablePath,
81
+ settingsPath: null,
82
+ }),
83
+ });
84
+ }
@@ -0,0 +1,299 @@
1
+ "use strict";
2
+ /**
3
+ * Talking to one opencode server (Issue #1763).
4
+ *
5
+ * The server is not a separate process. #1758 §5.1.2 measured that the plain
6
+ * `opencode` TUI *is* an HTTP server when it is given `--port`: `/global/health`,
7
+ * `/event`, `GET /permission` and the reply endpoints all answered identically
8
+ * to `opencode serve`. So there is no daemon to supervise here — the server's
9
+ * lifetime is the pane's lifetime, and everything in this file is a request to
10
+ * a port that either answers or does not.
11
+ *
12
+ * Four measurements shape the choices below.
13
+ *
14
+ * - **The subscription is legacy `GET /event`.** `GET /api/event` (v2) goes
15
+ * silent after the first three frames of a turn, reproducibly, and
16
+ * `GET /api/session/:id/event?after=<seq>` returns zero bytes — so neither
17
+ * the newer envelope nor durable replay is usable on 1.18.3 (#1758 §5.2.2).
18
+ * - **The frames name their event in the JSON, not in the SSE `event:` field.**
19
+ * Every frame is a bare `data:` line, so a named `EventSource` listener picks
20
+ * up nothing. The parser below reads `data:` and nothing else.
21
+ * - **Replies go to `POST /permission/:requestID/reply`.** There are two
22
+ * endpoints and they differ (#1758 §5.5.2): the per-session one takes
23
+ * `{"response":…}` and cannot carry a reason, while this one takes
24
+ * `{"reply":…, "message"?:…}` and the message reaches the agent verbatim —
25
+ * it turned up in the tool part's `state.error`. One had to be picked and
26
+ * fixed; this is the superset, and a denial CommandMate cannot explain is a
27
+ * denial the agent cannot act on.
28
+ * - **Absence is free to detect.** A closed port fails in under a millisecond
29
+ * (§5.7.2), so health checks cost nothing and every call here is allowed to
30
+ * be attempted rather than guarded by cached state.
31
+ *
32
+ * Nothing in this module throws. A source that cannot reach its agent has to
33
+ * degrade to the screen scraper, and an exception on the way to that decision
34
+ * would take the caller down with it.
35
+ *
36
+ * @module lib/hooks/sources/opencode/client
37
+ */
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.OPENCODE_REQUEST_TIMEOUT_MS = exports.OPENCODE_SERVER_HOST = void 0;
40
+ exports.opencodeBaseUrl = opencodeBaseUrl;
41
+ exports.fetchOpencodeHealth = fetchOpencodeHealth;
42
+ exports.fetchOpencodePendingPermissions = fetchOpencodePendingPermissions;
43
+ exports.fetchOpencodePendingQuestions = fetchOpencodePendingQuestions;
44
+ exports.fetchOpencodeActivity = fetchOpencodeActivity;
45
+ exports.replyOpencodePermission = replyOpencodePermission;
46
+ exports.replyOpencodeQuestion = replyOpencodeQuestion;
47
+ exports.createSseParser = createSseParser;
48
+ exports.readOpencodeEventStream = readOpencodeEventStream;
49
+ const logger_1 = require("../../../../lib/logger");
50
+ const logger = (0, logger_1.createLogger)('lib/hooks/sources/opencode/client');
51
+ /**
52
+ * The only host an opencode server is ever addressed on.
53
+ *
54
+ * `--hostname` defaults to this and the spike confirmed the LAN address refuses
55
+ * connections (#1758 §5.8.3). The server is unauthenticated by default, so
56
+ * binding it anywhere else would publish an arbitrary-command execution API to
57
+ * the network; `--mdns`, which flips the default to `0.0.0.0`, is never passed.
58
+ */
59
+ exports.OPENCODE_SERVER_HOST = '127.0.0.1';
60
+ /** Timeout for the small request/response calls. Generous: they answer in ms. */
61
+ exports.OPENCODE_REQUEST_TIMEOUT_MS = 5_000;
62
+ /** `http://127.0.0.1:<port>`. */
63
+ function opencodeBaseUrl(port) {
64
+ return `http://${exports.OPENCODE_SERVER_HOST}:${port}`;
65
+ }
66
+ function isPlainObject(value) {
67
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
68
+ }
69
+ /**
70
+ * One JSON request, with a timeout, that answers null instead of throwing.
71
+ *
72
+ * @param url - Absolute URL on the loopback server
73
+ * @param init - Method / body; a timeout signal is added
74
+ * @returns The parsed body, or null on any failure at all
75
+ */
76
+ async function requestJson(url, init) {
77
+ try {
78
+ const response = await fetch(url, {
79
+ ...init,
80
+ signal: AbortSignal.timeout(exports.OPENCODE_REQUEST_TIMEOUT_MS),
81
+ });
82
+ if (!response.ok)
83
+ return null;
84
+ return (await response.json());
85
+ }
86
+ catch (error) {
87
+ // Includes the ordinary case: nothing is listening because the pane exited.
88
+ logger.debug('opencode-request-failed', {
89
+ url,
90
+ error: error instanceof Error ? error.message : String(error),
91
+ });
92
+ return null;
93
+ }
94
+ }
95
+ /**
96
+ * Ask whether an opencode server is listening on this port.
97
+ *
98
+ * @returns Its health and version, or null when nothing answered
99
+ */
100
+ async function fetchOpencodeHealth(port) {
101
+ const body = await requestJson(`${opencodeBaseUrl(port)}/global/health`);
102
+ if (!isPlainObject(body))
103
+ return null;
104
+ if (body.healthy !== true)
105
+ return null;
106
+ return { healthy: true, version: typeof body.version === 'string' ? body.version : null };
107
+ }
108
+ /** An array body, or an empty array — `GET /permission` answers a bare array. */
109
+ function asObjectArray(body) {
110
+ if (!Array.isArray(body))
111
+ return [];
112
+ return body.filter(isPlainObject);
113
+ }
114
+ /**
115
+ * The approvals currently waiting on a human (#1758 §5.4).
116
+ *
117
+ * This is what makes a missed `permission.asked` recoverable: the event is
118
+ * gone, but the pending state is still readable, which is the whole of the
119
+ * reconnect strategy since `?after=<seq>` returns nothing.
120
+ */
121
+ async function fetchOpencodePendingPermissions(port) {
122
+ return asObjectArray(await requestJson(`${opencodeBaseUrl(port)}/permission`));
123
+ }
124
+ /** The questions currently waiting on a human. */
125
+ async function fetchOpencodePendingQuestions(port) {
126
+ return asObjectArray(await requestJson(`${opencodeBaseUrl(port)}/question`));
127
+ }
128
+ /**
129
+ * Whether any session on this server is working (#1758 §5.7.4).
130
+ *
131
+ * `GET /session/status` answers `{"ses_…":{"type":"busy"|"idle"}}`. Note what
132
+ * this does *not* answer: a session blocked on an approval reads `busy`, so
133
+ * this says "the turn is not over", never "the agent is thinking".
134
+ *
135
+ * @returns `busy` when any session is busy, `idle` when none is, null when the
136
+ * server could not be asked
137
+ */
138
+ async function fetchOpencodeActivity(port) {
139
+ const body = await requestJson(`${opencodeBaseUrl(port)}/session/status`);
140
+ if (!isPlainObject(body))
141
+ return null;
142
+ for (const value of Object.values(body)) {
143
+ if (isPlainObject(value) && value.type === 'busy')
144
+ return 'busy';
145
+ }
146
+ return 'idle';
147
+ }
148
+ /**
149
+ * Answer one approval.
150
+ *
151
+ * @param port - The instance's server
152
+ * @param requestId - `per_…`, from `permission.asked` / `GET /permission`
153
+ * @param reply - `once` runs it and asks again next time; `always` saves the
154
+ * pattern; `reject` fails the tool call
155
+ * @param message - Shown to the agent verbatim on a rejection. Only this
156
+ * endpoint can carry it
157
+ * @returns Whether the server accepted it
158
+ */
159
+ async function replyOpencodePermission(port, requestId, reply, message) {
160
+ const body = { reply };
161
+ if (message)
162
+ body.message = message;
163
+ const result = await requestJson(`${opencodeBaseUrl(port)}/permission/${encodeURIComponent(requestId)}/reply`, {
164
+ method: 'POST',
165
+ headers: { 'Content-Type': 'application/json' },
166
+ body: JSON.stringify(body),
167
+ });
168
+ return result !== null;
169
+ }
170
+ /**
171
+ * Answer one question.
172
+ *
173
+ * @param answers - One array of selected labels per question, in the order the
174
+ * `question.asked` frame listed them
175
+ */
176
+ async function replyOpencodeQuestion(port, questionId, answers) {
177
+ const result = await requestJson(`${opencodeBaseUrl(port)}/question/${encodeURIComponent(questionId)}/reply`, {
178
+ method: 'POST',
179
+ headers: { 'Content-Type': 'application/json' },
180
+ body: JSON.stringify({ answers }),
181
+ });
182
+ return result !== null;
183
+ }
184
+ // =============================================================================
185
+ // SSE
186
+ // =============================================================================
187
+ /**
188
+ * Incremental parser for the one SSE shape opencode emits.
189
+ *
190
+ * `GET /event` sends frames with no `event:` line — a `data:` line, then a
191
+ * blank line. Multi-line `data:` is joined with `\n` per the SSE spec, though
192
+ * 1.18.3 has never been observed to send one; supporting it costs a line and
193
+ * removes a class of silent truncation.
194
+ *
195
+ * @returns A parser whose `push` returns whatever frames the chunk completed
196
+ */
197
+ function createSseParser() {
198
+ let buffer = '';
199
+ let dataLines = [];
200
+ const completed = [];
201
+ const finishEvent = () => {
202
+ if (dataLines.length === 0)
203
+ return;
204
+ completed.push(dataLines.join('\n'));
205
+ dataLines = [];
206
+ };
207
+ const consumeLine = (rawLine) => {
208
+ const line = rawLine.endsWith('\r') ? rawLine.slice(0, -1) : rawLine;
209
+ if (line === '') {
210
+ finishEvent();
211
+ return;
212
+ }
213
+ if (line.startsWith(':'))
214
+ return; // comment / keepalive
215
+ if (line.startsWith('data:')) {
216
+ dataLines.push(line.slice(5).replace(/^ /, ''));
217
+ }
218
+ // `id:` / `event:` / `retry:` are not used by this server; ignored.
219
+ };
220
+ return {
221
+ push(chunk) {
222
+ buffer += chunk;
223
+ let newlineIndex = buffer.indexOf('\n');
224
+ while (newlineIndex >= 0) {
225
+ consumeLine(buffer.slice(0, newlineIndex));
226
+ buffer = buffer.slice(newlineIndex + 1);
227
+ newlineIndex = buffer.indexOf('\n');
228
+ }
229
+ return completed.splice(0, completed.length);
230
+ },
231
+ flush() {
232
+ if (buffer !== '') {
233
+ consumeLine(buffer);
234
+ buffer = '';
235
+ }
236
+ finishEvent();
237
+ return completed.splice(0, completed.length);
238
+ },
239
+ };
240
+ }
241
+ /**
242
+ * Subscribe to one server's event stream.
243
+ *
244
+ * Yields parsed frames until the connection ends or `signal` aborts. A frame
245
+ * that is not JSON is skipped rather than ending the stream: a malformed line
246
+ * is a bug in one frame, not a reason to stop watching the session.
247
+ *
248
+ * Ending is normal and is the caller's cue to reconnect — the connection dies
249
+ * without a clean EOF when the server goes away (`transfer closed with
250
+ * outstanding read data remaining`, #1758 §5.7.2).
251
+ *
252
+ * @param port - The instance's server
253
+ * @param signal - Aborted by the subscription to close the stream
254
+ */
255
+ async function* readOpencodeEventStream(port, signal) {
256
+ const response = await fetch(`${opencodeBaseUrl(port)}/event`, {
257
+ signal,
258
+ headers: { Accept: 'text/event-stream' },
259
+ });
260
+ if (!response.ok || !response.body) {
261
+ throw new Error(`opencode /event responded ${response.status}`);
262
+ }
263
+ const reader = response.body.getReader();
264
+ const decoder = new TextDecoder();
265
+ const parser = createSseParser();
266
+ try {
267
+ for (;;) {
268
+ const { done, value } = await reader.read();
269
+ if (done)
270
+ break;
271
+ const chunk = decoder.decode(value, { stream: true });
272
+ for (const raw of parser.push(chunk)) {
273
+ const frame = safeParseFrame(raw);
274
+ if (frame)
275
+ yield frame;
276
+ }
277
+ }
278
+ for (const raw of parser.flush()) {
279
+ const frame = safeParseFrame(raw);
280
+ if (frame)
281
+ yield frame;
282
+ }
283
+ }
284
+ finally {
285
+ // `cancel` on an already-aborted stream rejects; the connection is going
286
+ // away either way, so the failure is not actionable.
287
+ await reader.cancel().catch(() => { });
288
+ }
289
+ }
290
+ /** JSON, or null when the frame was not an object. */
291
+ function safeParseFrame(raw) {
292
+ try {
293
+ const parsed = JSON.parse(raw);
294
+ return isPlainObject(parsed) ? parsed : null;
295
+ }
296
+ catch {
297
+ return null;
298
+ }
299
+ }