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,261 @@
1
+ "use strict";
2
+ /**
3
+ * What a normalised opencode event does to CommandMate's state (Issue #1763).
4
+ *
5
+ * The consuming half of the pipeline was already tool-agnostic before this
6
+ * Issue: `agent-event-state`, `permission-decision-service`,
7
+ * `current-output-builder`, `status-mapping` and `prompt-waiting-composition`
8
+ * all key off (worktree, tool, instance) and branch on nothing else. So this
9
+ * module is deliberately thin — it is the same sequence
10
+ * `POST /api/hooks/agent-event` and `POST /api/hooks/permission-request`
11
+ * perform, called in-process because there is no request to perform it on.
12
+ *
13
+ * The one place the two paths differ is *where the verdict goes*. A hook is
14
+ * answered in the body of the request it arrived on; an opencode approval is
15
+ * answered by a POST to the agent's own server, minutes later if need be. Both
16
+ * are spelled `answerPendingDecision(source, …)`, which is the seam #1759 built
17
+ * for exactly this.
18
+ *
19
+ * ## Why the database imports are dynamic
20
+ *
21
+ * `../registry` statically imports `./source`, so anything `./source`'s module
22
+ * graph reaches becomes part of every import of `@/lib/hooks/sources` —
23
+ * including `better-sqlite3` if this module were pulled in eagerly. The state
24
+ * effects are needed only when an event actually arrives, so they are imported
25
+ * then. (`./source` does not import this module at all; the runtime wires the
26
+ * two together.)
27
+ *
28
+ * Nothing here throws. An event is a fact about a session that is still
29
+ * running, and a failure to record it must cost the record, never the session.
30
+ *
31
+ * @module lib/hooks/sources/opencode/ingest
32
+ */
33
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
34
+ if (k2 === undefined) k2 = k;
35
+ var desc = Object.getOwnPropertyDescriptor(m, k);
36
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
37
+ desc = { enumerable: true, get: function() { return m[k]; } };
38
+ }
39
+ Object.defineProperty(o, k2, desc);
40
+ }) : (function(o, m, k, k2) {
41
+ if (k2 === undefined) k2 = k;
42
+ o[k2] = m[k];
43
+ }));
44
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
45
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
46
+ }) : function(o, v) {
47
+ o["default"] = v;
48
+ });
49
+ var __importStar = (this && this.__importStar) || (function () {
50
+ var ownKeys = function(o) {
51
+ ownKeys = Object.getOwnPropertyNames || function (o) {
52
+ var ar = [];
53
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
54
+ return ar;
55
+ };
56
+ return ownKeys(o);
57
+ };
58
+ return function (mod) {
59
+ if (mod && mod.__esModule) return mod;
60
+ var result = {};
61
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
62
+ __setModuleDefault(result, mod);
63
+ return result;
64
+ };
65
+ })();
66
+ Object.defineProperty(exports, "__esModule", { value: true });
67
+ exports.ingestOpencodeEvent = ingestOpencodeEvent;
68
+ const logger_1 = require("../../../../lib/logger");
69
+ const agent_event_types_1 = require("../../../../lib/hooks/agent-event-types");
70
+ const agent_event_state_1 = require("../../../../lib/session/agent-event-state");
71
+ const structured_prompt_1 = require("../../../../lib/session/structured-prompt");
72
+ const abstain_1 = require("../abstain");
73
+ const event_mapper_1 = require("../event-mapper");
74
+ const pending_decisions_1 = require("../pending-decisions");
75
+ const registry_1 = require("../registry");
76
+ const mappers_1 = require("./mappers");
77
+ const payloads_1 = require("./payloads");
78
+ const tool_id_1 = require("./tool-id");
79
+ const logger = (0, logger_1.createLogger)('lib/hooks/sources/opencode/ingest');
80
+ /** The one-line human-facing summary for a notification, or null. */
81
+ function describeNotification(event) {
82
+ const properties = (0, event_mapper_1.isPlainObject)(event.raw.properties) ? event.raw.properties : {};
83
+ if (event.detail === mappers_1.OPENCODE_PERMISSION_DETAIL) {
84
+ // `metadata.command` exists for `bash` approvals and is what the human is
85
+ // being asked about; the approval kind is the fallback for the rest.
86
+ return ((0, event_mapper_1.readNestedString)(properties, ['metadata', 'command']) ??
87
+ (0, event_mapper_1.readStringField)(properties, 'permission'));
88
+ }
89
+ if (event.detail === mappers_1.OPENCODE_QUESTION_DETAIL) {
90
+ const questions = properties.questions;
91
+ if (Array.isArray(questions) && (0, event_mapper_1.isPlainObject)(questions[0])) {
92
+ return (0, event_mapper_1.readStringField)(questions[0], 'question');
93
+ }
94
+ return null;
95
+ }
96
+ if (event.detail === mappers_1.OPENCODE_ERROR_DETAIL) {
97
+ return ((0, event_mapper_1.readNestedString)(properties, ['error', 'data', 'message']) ??
98
+ (0, event_mapper_1.readNestedString)(properties, ['error', 'name']));
99
+ }
100
+ return null;
101
+ }
102
+ /**
103
+ * Adjudicate one approval and answer it over REST (Auto-Yes v2).
104
+ *
105
+ * The adjudication itself is `resolvePermissionRequest`, unchanged and shared
106
+ * with every hook-based tool. What is opencode-specific is what silence means:
107
+ * on Claude an abstention costs a dialog, here it costs the session, because
108
+ * the agent waits with no timeout at all (#1758 §5.5.3). `describeAbstain` is
109
+ * how that gets said out loud — nothing else will say it, since a blocked
110
+ * opencode session looks exactly like one that is thinking.
111
+ */
112
+ async function adjudicatePermission(target, event, instanceId) {
113
+ const source = (0, registry_1.getAgentEventSource)(tool_id_1.OPENCODE_CLI_TOOL_ID);
114
+ const pending = (0, payloads_1.toOpencodePendingPermission)(event.raw, event.receivedAt);
115
+ if (!pending) {
116
+ logger.info('opencode-permission-unparsed', {
117
+ worktreeId: target.worktreeId,
118
+ instanceId,
119
+ });
120
+ return;
121
+ }
122
+ const { resolvePermissionRequest } = await Promise.resolve().then(() => __importStar(require('../../../../lib/hooks/permission-decision-service')));
123
+ const payload = source.parsePermissionRequest(event.raw);
124
+ const decision = resolvePermissionRequest({ worktreeId: target.worktreeId, cliToolId: tool_id_1.OPENCODE_CLI_TOOL_ID, instanceId }, payload);
125
+ const verdict = decision.behavior === 'allow' ? { kind: 'allowOnce' } : { kind: 'abstain' };
126
+ if (verdict.kind === 'abstain') {
127
+ const abstain = (0, abstain_1.describeAbstain)(source);
128
+ if (!abstain.safe) {
129
+ logger.warn('permission-request-abstain-blocks-agent', {
130
+ worktreeId: target.worktreeId,
131
+ cliToolId: tool_id_1.OPENCODE_CLI_TOOL_ID,
132
+ instanceId,
133
+ toolName: payload?.toolName ?? null,
134
+ decisionId: pending.id,
135
+ reason: decision.reason,
136
+ consequence: abstain.summary,
137
+ blocksForMs: abstain.blocksForMs,
138
+ });
139
+ }
140
+ }
141
+ // C2: for this source the verdict leaves over its own connection, and the
142
+ // `{}` that comes back is an acknowledgement rather than a reply body.
143
+ await (0, pending_decisions_1.answerPendingDecision)(source, { worktreeId: target.worktreeId, cliToolId: tool_id_1.OPENCODE_CLI_TOOL_ID, instanceId }, pending, verdict);
144
+ logger.info('opencode-permission-decided', {
145
+ worktreeId: target.worktreeId,
146
+ instanceId,
147
+ decisionId: pending.id,
148
+ toolName: payload?.toolName ?? null,
149
+ behavior: decision.behavior,
150
+ reason: decision.reason,
151
+ suppressedBy: decision.suppressedBy,
152
+ });
153
+ }
154
+ /**
155
+ * Record a question so `capture --prompts` and the picker can show its options.
156
+ *
157
+ * The structured content Claude never had: its `AskUserQuestion` picker has to
158
+ * be read off the screen (#1708), while opencode publishes the questions and
159
+ * their choices as data (#1758 §5.2.4).
160
+ *
161
+ * `reportPermissionRequestPending` is called alongside because that is the only
162
+ * exported way to tell the detection layer a human is blocked, and a question
163
+ * blocks exactly as an approval does — the session reads `busy` and no
164
+ * `session.idle` arrives until it is answered (§5.3.1). It is recorded as
165
+ * provisional, so it expires unless the scraper corroborates it, which is the
166
+ * same treatment Claude's pre-dialog prediction gets.
167
+ */
168
+ function recordQuestion(target, event, instanceId) {
169
+ const source = (0, registry_1.getAgentEventSource)(tool_id_1.OPENCODE_CLI_TOOL_ID);
170
+ const spec = source.parseQuestion(event.raw);
171
+ if (!spec)
172
+ return;
173
+ (0, agent_event_state_1.recordAskUserQuestion)(target.worktreeId, tool_id_1.OPENCODE_CLI_TOOL_ID, instanceId, spec, event.receivedAt);
174
+ (0, agent_event_state_1.reportPermissionRequestPending)(target.worktreeId, tool_id_1.OPENCODE_CLI_TOOL_ID, instanceId, 'question', event.receivedAt);
175
+ logger.info('opencode-question-recorded', {
176
+ worktreeId: target.worktreeId,
177
+ instanceId,
178
+ questionCount: spec.questions.length,
179
+ optionCounts: spec.questions.map((question) => question.choices.length),
180
+ });
181
+ }
182
+ /** Apply a completed turn to whatever the worktree is doing. */
183
+ async function applyStop(target, instanceId) {
184
+ const [{ getDbInstance }, { getWorktreeById }, { applyAgentStopEvent }] = await Promise.all([
185
+ Promise.resolve().then(() => __importStar(require('../../../../lib/db/db-instance'))),
186
+ Promise.resolve().then(() => __importStar(require('../../../../lib/db'))),
187
+ Promise.resolve().then(() => __importStar(require('../../../../lib/hooks/agent-event-service'))),
188
+ ]);
189
+ const db = getDbInstance();
190
+ const worktree = getWorktreeById(db, target.worktreeId) ?? null;
191
+ if (!worktree) {
192
+ // The worktree was removed while its pane was still running. Ordinary, not
193
+ // an error — the same outcome the hook receiver reports as 202-and-drop.
194
+ logger.info('opencode-stop-unresolved-target', { worktreeId: target.worktreeId });
195
+ return;
196
+ }
197
+ const outcome = await applyAgentStopEvent(db, worktree, tool_id_1.OPENCODE_CLI_TOOL_ID, instanceId);
198
+ logger.info('opencode-stop-applied', {
199
+ worktreeId: target.worktreeId,
200
+ instanceId,
201
+ taskId: outcome.taskId,
202
+ taskEventApplied: outcome.taskEventApplied,
203
+ verificationRunId: outcome.verificationRunId,
204
+ });
205
+ }
206
+ /**
207
+ * Apply one event from the stream.
208
+ *
209
+ * @param target - The instance the subscription belongs to
210
+ * @param event - Already normalised and already through the turn gate
211
+ */
212
+ async function ingestOpencodeEvent(target, event) {
213
+ const instanceId = target.instanceId ?? tool_id_1.OPENCODE_CLI_TOOL_ID;
214
+ try {
215
+ // The same guard the hook receiver applies. It cannot catch the abort
216
+ // double-idle on its own — see `./turn-gate`, which is what does — but it
217
+ // does cover a frame delivered twice by a re-sync racing the live stream.
218
+ if ((0, agent_event_state_1.isDuplicateAgentEvent)(target.worktreeId, tool_id_1.OPENCODE_CLI_TOOL_ID, instanceId, event.event, event.conversationId, event.receivedAt, event.detail)) {
219
+ logger.info('opencode-event-duplicate-dropped', {
220
+ worktreeId: target.worktreeId,
221
+ instanceId,
222
+ event: event.event,
223
+ detail: event.detail,
224
+ });
225
+ return;
226
+ }
227
+ (0, agent_event_state_1.recordAgentEvent)(target.worktreeId, tool_id_1.OPENCODE_CLI_TOOL_ID, instanceId, {
228
+ event: event.event,
229
+ at: event.receivedAt,
230
+ detail: event.detail?.slice(0, agent_event_types_1.MAX_EVENT_DETAIL_LENGTH) ?? null,
231
+ sessionId: event.conversationId,
232
+ message: describeNotification(event)?.slice(0, structured_prompt_1.MAX_STRUCTURED_PROMPT_MESSAGE_LENGTH) ?? null,
233
+ });
234
+ if (event.event === 'notification' && event.detail === mappers_1.OPENCODE_PERMISSION_DETAIL) {
235
+ await adjudicatePermission(target, event, instanceId);
236
+ return;
237
+ }
238
+ if (event.event === 'notification' && event.detail === mappers_1.OPENCODE_QUESTION_DETAIL) {
239
+ recordQuestion(target, event, instanceId);
240
+ return;
241
+ }
242
+ if (event.event === 'stop') {
243
+ await applyStop(target, instanceId);
244
+ return;
245
+ }
246
+ logger.info('opencode-event-received', {
247
+ worktreeId: target.worktreeId,
248
+ instanceId,
249
+ event: event.event,
250
+ detail: event.detail,
251
+ });
252
+ }
253
+ catch (error) {
254
+ logger.error('opencode-event-ingest-failed', {
255
+ worktreeId: target.worktreeId,
256
+ instanceId,
257
+ event: event.event,
258
+ error: error instanceof Error ? error.message : String(error),
259
+ });
260
+ }
261
+ }
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ /**
3
+ * opencode's SSE frames, mapped onto the seven words (Issue #1763, constraint
4
+ * C4).
5
+ *
6
+ * Every rule below is lifted from a frame that was actually captured from
7
+ * `opencode` 1.18.3 — the files in `tests/fixtures/hooks/opencode/` — and not
8
+ * from the server's OpenAPI document. The document is wrong in at least one
9
+ * place that matters (`server.heartbeat` is not in its `Event` union yet
10
+ * arrives every ten seconds, #1758 D5), so the fixtures are the specification
11
+ * and the tests read them directly.
12
+ *
13
+ * Three of the rules cannot be written as a name table, which is the whole
14
+ * reason {@link EventMapper} is a function (#1758 §5.2.3):
15
+ *
16
+ * - `message.part.updated` is `pre_tool_use` or `post_tool_use` depending on
17
+ * `part.state.status` — one event name, two words.
18
+ * - `user_prompt_submit` has no event of its own; it is `message.updated` with
19
+ * `info.role === "user"`.
20
+ * - `notification` is three unrelated events told apart only by `detail`.
21
+ *
22
+ * ## The envelope
23
+ *
24
+ * ```json
25
+ * { "id": "evt_…", "type": "session.idle", "properties": { "sessionID": "ses_…" } }
26
+ * ```
27
+ *
28
+ * The event's name is in `type` and everything else is nested under
29
+ * `properties`, so `conversationIdFields` — which reads flat keys — cannot
30
+ * reach `sessionID`. {@link withConversationId} fills it in from the nested
31
+ * path instead, which is the C5 escape hatch the interface documents.
32
+ *
33
+ * @module lib/hooks/sources/opencode/mappers
34
+ */
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.OPENCODE_MAPPERS = exports.OPENCODE_ERROR_DETAIL = exports.OPENCODE_QUESTION_DETAIL = exports.OPENCODE_PERMISSION_DETAIL = void 0;
37
+ exports.frameProperties = frameProperties;
38
+ exports.frameSessionId = frameSessionId;
39
+ exports.partToolName = partToolName;
40
+ exports.partCallId = partCallId;
41
+ exports.withConversationId = withConversationId;
42
+ const event_mapper_1 = require("../event-mapper");
43
+ /**
44
+ * Detail for `permission.asked`.
45
+ *
46
+ * Deliberately Claude's spelling. `wait --on-prompt` has to mean the same thing
47
+ * on both tools, and `agent-event-state` opens its prompt-waiting record on
48
+ * exactly this string — renaming it for opencode would leave the state machine
49
+ * silently unable to see an opencode approval dialog (#1758 §9.3).
50
+ */
51
+ exports.OPENCODE_PERMISSION_DETAIL = 'permission_prompt';
52
+ /**
53
+ * Detail for `question.asked`.
54
+ *
55
+ * A new value rather than a reuse: opencode's `question` tool is answered with
56
+ * structured choices over its own endpoint, and nothing above this layer should
57
+ * be able to confuse it with an approval it could allow. There is no
58
+ * `idle_prompt` equivalent on opencode at all — no event reports "the agent is
59
+ * sitting at the composer" — so that spelling never appears here.
60
+ */
61
+ exports.OPENCODE_QUESTION_DETAIL = 'question_prompt';
62
+ /** Detail for `session.error`. */
63
+ exports.OPENCODE_ERROR_DETAIL = 'error';
64
+ /** The `properties` object of a frame, or an empty object. */
65
+ function frameProperties(payload) {
66
+ return (0, event_mapper_1.isPlainObject)(payload.properties) ? payload.properties : {};
67
+ }
68
+ /** `properties.sessionID`, the id every frame that belongs to a turn carries. */
69
+ function frameSessionId(payload) {
70
+ return (0, event_mapper_1.readNestedString)(frameProperties(payload), ['sessionID']);
71
+ }
72
+ /** `properties.part.state.status` — `pending` / `running` / `completed` / `error`. */
73
+ function partStatus(payload) {
74
+ return (0, event_mapper_1.readNestedString)(frameProperties(payload), ['part', 'state', 'status']);
75
+ }
76
+ /** Whether this `message.part.updated` describes a tool call rather than text. */
77
+ function partIsToolCall(payload) {
78
+ return (0, event_mapper_1.readNestedString)(frameProperties(payload), ['part', 'type']) === 'tool';
79
+ }
80
+ /** `properties.part.tool` — `bash`, `read`, … (lower case, unlike Claude's). */
81
+ function partToolName(payload) {
82
+ return (0, event_mapper_1.readNestedString)(frameProperties(payload), ['part', 'tool']);
83
+ }
84
+ /** `properties.part.callID` — the correlation key for one tool call. */
85
+ function partCallId(payload) {
86
+ return (0, event_mapper_1.readNestedString)(frameProperties(payload), ['part', 'callID']);
87
+ }
88
+ /** Statuses that mean the tool call is over, either way (#1758 §5.2.3). */
89
+ const FINISHED_PART_STATUSES = ['completed', 'error'];
90
+ /**
91
+ * The ordered rules, first match wins.
92
+ *
93
+ * `session.status`, `server.connected`, `server.heartbeat`, `permission.replied`
94
+ * and `question.replied` are deliberately absent. They are real frames that
95
+ * arrive on every healthy connection and they map to none of the seven words,
96
+ * so they fall through, return null and are counted (C8) — which is what the
97
+ * interface asks for and what stops a ten-second keepalive from throwing.
98
+ *
99
+ * `session.status(idle)` in particular must NOT be mapped: it is emitted in the
100
+ * same millisecond as `session.idle` and mapping both would report every turn's
101
+ * completion twice (#1758 §5.3.2 rule 4).
102
+ */
103
+ const OPENCODE_BASE_MAPPERS = [
104
+ // 1:1. `session.deleted` only fires for an explicit `DELETE /session/:id` —
105
+ // the TUI's `/exit` emits nothing at all — so it is expressible but is not
106
+ // the signal that the agent is gone. That stays tmux's job (#1758 §5.6.4).
107
+ (0, event_mapper_1.whenNamed)('session.idle', 'stop'),
108
+ (0, event_mapper_1.whenNamed)('session.created', 'session_start'),
109
+ (0, event_mapper_1.whenNamed)('session.deleted', 'session_end'),
110
+ // Composite: no dedicated event, so the role decides.
111
+ (type, payload) => type === 'message.updated' &&
112
+ (0, event_mapper_1.readNestedString)(frameProperties(payload), ['info', 'role']) === 'user'
113
+ ? { event: 'user_prompt_submit' }
114
+ : null,
115
+ // Partial match: one event name, two words, chosen by a nested status.
116
+ // `pending` — the frame just before `running` — maps to nothing on purpose;
117
+ // mapping it as well would report every tool call twice.
118
+ (type, payload) => type === 'message.part.updated' && partIsToolCall(payload) && partStatus(payload) === 'running'
119
+ ? {
120
+ event: 'pre_tool_use',
121
+ detail: (0, event_mapper_1.boundDetail)(partToolName(payload)),
122
+ toolCallId: partCallId(payload),
123
+ }
124
+ : null,
125
+ (type, payload) => type === 'message.part.updated' &&
126
+ partIsToolCall(payload) &&
127
+ FINISHED_PART_STATUSES.includes(partStatus(payload) ?? '')
128
+ ? {
129
+ event: 'post_tool_use',
130
+ detail: (0, event_mapper_1.boundDetail)(partToolName(payload)),
131
+ toolCallId: partCallId(payload),
132
+ }
133
+ : null,
134
+ // Bundle: three unrelated events collapse into `notification`.
135
+ (0, event_mapper_1.whenNamed)('permission.asked', 'notification', exports.OPENCODE_PERMISSION_DETAIL),
136
+ (0, event_mapper_1.whenNamed)('question.asked', 'notification', exports.OPENCODE_QUESTION_DETAIL),
137
+ (0, event_mapper_1.whenNamed)('session.error', 'notification', exports.OPENCODE_ERROR_DETAIL),
138
+ ];
139
+ /**
140
+ * Fill `conversationId` from the nested envelope.
141
+ *
142
+ * @param mapper - A rule that may or may not have set the field itself
143
+ * @returns The same rule, with `properties.sessionID` as the fallback
144
+ */
145
+ function withConversationId(mapper) {
146
+ return (type, payload) => {
147
+ const mapped = mapper(type, payload);
148
+ if (!mapped)
149
+ return null;
150
+ return { ...mapped, conversationId: mapped.conversationId ?? frameSessionId(payload) };
151
+ };
152
+ }
153
+ /** The rules an opencode source carries. */
154
+ exports.OPENCODE_MAPPERS = OPENCODE_BASE_MAPPERS.map(withConversationId);
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ /**
3
+ * Reading opencode's approval and question payloads (Issue #1763, seam S7).
4
+ *
5
+ * Both shapes are taken from captured frames — `permission-asked.json` and
6
+ * `question-asked.json` in `tests/fixtures/hooks/opencode/` — and both are
7
+ * parsed into the vocabulary the tool-independent adjudicator already speaks,
8
+ * so `permission-decision-service` and `agent-event-state` need no opencode
9
+ * branch.
10
+ *
11
+ * ## The tool name is not in the approval payload
12
+ *
13
+ * `permission.asked` carries `permission` (the *kind* of approval:
14
+ * `external_directory`, …), `patterns`, `metadata` and `tool.callID` — but no
15
+ * tool name (#1758 §5.4). Auto-Yes matches deny patterns against what is being
16
+ * asked for, so the name has to come from somewhere: the `message.part.updated`
17
+ * frame for the same `callID` carries `part.tool` (`bash`), and it arrives
18
+ * first, so the subscription records the correlation as it goes and this module
19
+ * looks it up. When the correlation is missing the approval kind is used
20
+ * instead — an unknown tool name makes `collectToolInputMatchTexts` fall back
21
+ * to the serialised input, which contains the command, so the matching surface
22
+ * never silently empties.
23
+ *
24
+ * ## What the deny patterns see
25
+ *
26
+ * `metadata` verbatim (it holds `command` for `bash` approvals), plus the
27
+ * approval kind and its patterns. Nothing from the pane and nothing from an
28
+ * earlier request can reach it — the property #1699 was opened about.
29
+ *
30
+ * @module lib/hooks/sources/opencode/payloads
31
+ */
32
+ Object.defineProperty(exports, "__esModule", { value: true });
33
+ exports.MAX_TRACKED_TOOL_CALLS = void 0;
34
+ exports.rememberOpencodeToolCall = rememberOpencodeToolCall;
35
+ exports.lookupOpencodeToolName = lookupOpencodeToolName;
36
+ exports.resetOpencodeToolCalls = resetOpencodeToolCalls;
37
+ exports.parseOpencodePermissionRequest = parseOpencodePermissionRequest;
38
+ exports.parseOpencodeQuestion = parseOpencodeQuestion;
39
+ exports.toOpencodePendingPermission = toOpencodePendingPermission;
40
+ exports.toOpencodePendingQuestion = toOpencodePendingQuestion;
41
+ const ask_user_question_payload_1 = require("../../../../lib/hooks/ask-user-question-payload");
42
+ const event_mapper_1 = require("../event-mapper");
43
+ /**
44
+ * Cap on remembered `callID -> tool name` pairs.
45
+ *
46
+ * One per tool call, and a long session makes thousands, so the map is bounded
47
+ * and the oldest is dropped. Forgetting costs a less specific tool name on an
48
+ * approval, never a wrong one.
49
+ */
50
+ exports.MAX_TRACKED_TOOL_CALLS = 256;
51
+ const toolCallNames = (globalThis.__opencodeToolCallNames ??= new Map());
52
+ /** Record that a tool call has a name, seen on a `message.part.updated` frame. */
53
+ function rememberOpencodeToolCall(callId, toolName) {
54
+ toolCallNames.delete(callId);
55
+ toolCallNames.set(callId, toolName);
56
+ while (toolCallNames.size > exports.MAX_TRACKED_TOOL_CALLS) {
57
+ const oldest = toolCallNames.keys().next();
58
+ if (oldest.done)
59
+ break;
60
+ toolCallNames.delete(oldest.value);
61
+ }
62
+ }
63
+ /** The tool behind a `callID`, or null when it has not been seen. */
64
+ function lookupOpencodeToolName(callId) {
65
+ if (!callId)
66
+ return null;
67
+ return toolCallNames.get(callId) ?? null;
68
+ }
69
+ /** Forget every correlation. Test seam. */
70
+ function resetOpencodeToolCalls() {
71
+ toolCallNames.clear();
72
+ }
73
+ /**
74
+ * The object an approval or question lives in.
75
+ *
76
+ * Two callers hand this module two different shapes and both are legitimate:
77
+ * the SSE frame `{ id, type, properties }`, and the bare object
78
+ * `GET /permission` returns when a missed event is being recovered. Unwrapping
79
+ * here is what lets the reconnect path reuse the live path's parsing.
80
+ */
81
+ function unwrap(payload) {
82
+ if (typeof payload.type === 'string' && (0, event_mapper_1.isPlainObject)(payload.properties)) {
83
+ return payload.properties;
84
+ }
85
+ return payload;
86
+ }
87
+ /** `tool.callID`, present on both approvals and questions. */
88
+ function toolCallId(properties) {
89
+ return (0, event_mapper_1.readNestedString)(properties, ['tool', 'callID']);
90
+ }
91
+ /**
92
+ * Read a `permission.asked` frame, or a pending entry from `GET /permission`.
93
+ *
94
+ * @param payload - The frame or the bare permission object
95
+ * @returns The payload the adjudicator judges, or null when this is not an
96
+ * approval this server can read — which every caller must treat as "no
97
+ * decision", i.e. leave it for the human
98
+ */
99
+ function parseOpencodePermissionRequest(payload) {
100
+ const properties = unwrap(payload);
101
+ const permissionId = (0, event_mapper_1.readStringField)(properties, 'id');
102
+ const sessionId = (0, event_mapper_1.readStringField)(properties, 'sessionID');
103
+ // Both are required: the id is what a verdict is addressed to, and without a
104
+ // session there is nothing to attribute the request to.
105
+ if (!permissionId || !sessionId)
106
+ return null;
107
+ // `question.asked` shares the envelope; it is answered with choices, never
108
+ // adjudicated as an approval.
109
+ if (Array.isArray(properties.questions))
110
+ return null;
111
+ const kind = (0, event_mapper_1.readStringField)(properties, 'permission');
112
+ const metadata = (0, event_mapper_1.isPlainObject)(properties.metadata) ? properties.metadata : {};
113
+ return {
114
+ toolName: lookupOpencodeToolName(toolCallId(properties)) ?? kind ?? 'permission',
115
+ toolInput: {
116
+ permission: kind,
117
+ patterns: Array.isArray(properties.patterns) ? properties.patterns : [],
118
+ ...metadata,
119
+ },
120
+ // `per_…` is what the reply URL takes, and it is stable for the life of the
121
+ // request — the correlation key Claude spells `prompt_id`.
122
+ promptId: permissionId,
123
+ sessionId,
124
+ // opencode has no equivalent of Claude's permission mode: the dialog is
125
+ // drawn unconditionally (§5.5.3), so there is no "do not ask me" state that
126
+ // would make a no-decision non-blocking.
127
+ permissionMode: null,
128
+ // `always` is the rule that would be saved by answering `always`. Recorded
129
+ // for the audit trail, never a decision input — it is opencode's suggestion,
130
+ // which is the thing being judged.
131
+ permissionSuggestions: Array.isArray(properties.always) ? properties.always : null,
132
+ };
133
+ }
134
+ /**
135
+ * Read a `question.asked` frame (#1758 §5.2.4).
136
+ *
137
+ * The one place opencode is *better* structured than Claude: the choices arrive
138
+ * as data, where Claude's `AskUserQuestion` picker had to be read off the
139
+ * screen. The inner shape — `{ question, header, options: [{ label,
140
+ * description }] }` — is identical to Claude's `tool_input.questions`, so the
141
+ * existing strict parser is reused rather than re-derived.
142
+ *
143
+ * @returns The spec, or null when this is not a readable question
144
+ */
145
+ function parseOpencodeQuestion(payload) {
146
+ const properties = unwrap(payload);
147
+ const questionId = (0, event_mapper_1.readStringField)(properties, 'id');
148
+ if (!questionId)
149
+ return null;
150
+ const questions = (0, ask_user_question_payload_1.parseAskUserQuestionToolInput)({ questions: properties.questions });
151
+ if (questions === null)
152
+ return null;
153
+ return { questions, promptId: questionId };
154
+ }
155
+ /**
156
+ * Turn an approval into the transport-independent {@link PendingDecision}.
157
+ *
158
+ * @param payload - A `permission.asked` frame or a `GET /permission` entry
159
+ * @param askedAt - Epoch ms
160
+ */
161
+ function toOpencodePendingPermission(payload, askedAt) {
162
+ const parsed = parseOpencodePermissionRequest(payload);
163
+ if (!parsed || !parsed.promptId)
164
+ return null;
165
+ return {
166
+ kind: 'permission',
167
+ id: parsed.promptId,
168
+ conversationId: parsed.sessionId,
169
+ subject: { kind: 'permission', toolName: parsed.toolName, toolInput: parsed.toolInput },
170
+ raw: payload,
171
+ askedAt,
172
+ };
173
+ }
174
+ /** Turn a question into a {@link PendingDecision}. */
175
+ function toOpencodePendingQuestion(payload, askedAt) {
176
+ const properties = unwrap(payload);
177
+ const questionId = (0, event_mapper_1.readStringField)(properties, 'id');
178
+ const spec = parseOpencodeQuestion(payload);
179
+ if (!questionId || !spec)
180
+ return null;
181
+ return {
182
+ kind: 'question',
183
+ id: questionId,
184
+ conversationId: (0, event_mapper_1.readStringField)(properties, 'sessionID'),
185
+ subject: { kind: 'question', spec },
186
+ raw: payload,
187
+ askedAt,
188
+ };
189
+ }