commandmate 0.42.1 → 0.43.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 (435) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +144 -144
  3. package/.next/app-path-routes-manifest.json +23 -23
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +9 -9
  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/agents/update/route_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  12. package/.next/server/app/api/app/update-check/route.js +1 -1
  13. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  14. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  15. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/capabilities/route.js +1 -1
  18. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  19. package/.next/server/app/api/daily-summary/route.js +1 -1
  20. package/.next/server/app/api/daily-summary/route.js.nft.json +1 -1
  21. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  22. package/.next/server/app/api/daily-summary/status/route.js +1 -1
  23. package/.next/server/app/api/daily-summary/status/route.js.nft.json +1 -1
  24. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  27. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  28. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  29. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  30. package/.next/server/app/api/hooks/agent-event/route.js +103 -1
  31. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  32. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/hooks/claude-done/route.js +2 -2
  34. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  35. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  37. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  38. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  41. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
  45. package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
  46. package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
  47. package/.next/server/app/api/relays/route.js +1 -1
  48. package/.next/server/app/api/relays/route.js.nft.json +1 -1
  49. package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  51. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  52. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  53. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  54. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  55. package/.next/server/app/api/repositories/clone/route.js +1 -1
  56. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  57. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  58. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/repositories/restore/route.js +1 -1
  60. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  61. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/repositories/route.js +1 -1
  63. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  64. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  65. package/.next/server/app/api/repositories/scan/route.js +1 -1
  66. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  67. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  68. package/.next/server/app/api/repositories/sync/route.js +1 -1
  69. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  70. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  71. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  72. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  73. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  74. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  75. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  76. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/skills/[id]/route.js +1 -1
  78. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  82. package/.next/server/app/api/skills/route.js +1 -1
  83. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/slash-commands/route.js +1 -1
  85. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  88. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  89. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  93. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  94. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  95. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  96. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  97. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  99. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  100. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +3 -1
  104. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js.nft.json +1 -1
  105. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  107. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  108. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/direct-input/route.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
  111. package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +3 -1
  116. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js.nft.json +1 -1
  117. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  119. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  145. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  148. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  151. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js.nft.json +1 -1
  161. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js.nft.json +1 -1
  164. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  167. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  171. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/route.js +1 -103
  173. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  174. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +3 -1
  176. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +1 -1
  177. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +3 -1
  179. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +1 -1
  180. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/schedules/route.js +3 -1
  182. package/.next/server/app/api/worktrees/[id]/schedules/route.js.nft.json +1 -1
  183. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -103
  186. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  187. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +104 -2
  189. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  190. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  191. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  196. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js.nft.json +1 -1
  200. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  203. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/tasks/route.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
  207. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  208. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  212. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  215. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  217. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  218. package/.next/server/app/api/worktrees/[id]/verify/config/route.js +1 -1
  219. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  220. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
  221. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  222. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
  223. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  224. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  225. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  226. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  227. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/api/worktrees/route.js +1 -1
  229. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  230. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  231. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  232. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  233. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  234. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  235. package/.next/server/app/page_client-reference-manifest.js +1 -1
  236. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  237. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  238. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  239. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  240. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  241. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  242. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  243. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  244. package/.next/server/app/worktrees/[id]/page.js +9 -9
  245. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  246. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  247. package/.next/server/app-paths-manifest.json +23 -23
  248. package/.next/server/chunks/1068.js +1 -1
  249. package/.next/server/chunks/1210.js +1 -1
  250. package/.next/server/chunks/1501.js +4 -4
  251. package/.next/server/chunks/1990.js +1 -1
  252. package/.next/server/chunks/2119.js +1 -1
  253. package/.next/server/chunks/22.js +1 -1
  254. package/.next/server/chunks/2328.js +1 -1
  255. package/.next/server/chunks/2404.js +4 -3
  256. package/.next/server/chunks/2445.js +1 -1
  257. package/.next/server/chunks/252.js +1 -1
  258. package/.next/server/chunks/2816.js +1 -1
  259. package/.next/server/chunks/3543.js +1 -1
  260. package/.next/server/chunks/3730.js +1 -1
  261. package/.next/server/chunks/3945.js +1 -1
  262. package/.next/server/chunks/4207.js +3 -3
  263. package/.next/server/chunks/434.js +1 -1
  264. package/.next/server/chunks/5064.js +1 -1
  265. package/.next/server/chunks/5571.js +1 -1
  266. package/.next/server/chunks/5742.js +1 -1
  267. package/.next/server/chunks/5775.js +1 -1
  268. package/.next/server/chunks/611.js +1 -1
  269. package/.next/server/chunks/6130.js +1 -1
  270. package/.next/server/chunks/6285.js +1 -1
  271. package/.next/server/chunks/6491.js +103 -0
  272. package/.next/server/chunks/6661.js +1 -1
  273. package/.next/server/chunks/6781.js +1 -1
  274. package/.next/server/chunks/6793.js +1 -1
  275. package/.next/server/chunks/7491.js +3 -0
  276. package/.next/server/chunks/7685.js +1 -1
  277. package/.next/server/chunks/7905.js +1 -1
  278. package/.next/server/chunks/8581.js +2 -2
  279. package/.next/server/chunks/8583.js +1 -1
  280. package/.next/server/chunks/8673.js +6 -6
  281. package/.next/server/chunks/8728.js +2 -2
  282. package/.next/server/chunks/8791.js +1 -1
  283. package/.next/server/chunks/8800.js +4 -3
  284. package/.next/server/chunks/8918.js +5 -5
  285. package/.next/server/chunks/9130.js +3 -3
  286. package/.next/server/chunks/{8052.js → 9353.js} +4 -2
  287. package/.next/server/chunks/9390.js +3 -0
  288. package/.next/server/chunks/9627.js +4 -4
  289. package/.next/server/chunks/964.js +1 -1
  290. package/.next/server/chunks/967.js +1 -0
  291. package/.next/server/chunks/9731.js +3 -3
  292. package/.next/server/chunks/9882.js +3 -3
  293. package/.next/server/middleware-manifest.json +5 -5
  294. package/.next/server/pages/500.html +1 -1
  295. package/.next/server/server-reference-manifest.json +1 -1
  296. package/.next/static/chunks/{1642-fb2e176aaadbd137.js → 1642-767aed8e7c61ef7f.js} +1 -1
  297. package/.next/static/chunks/{2407-21fbf12d753b8d4d.js → 2407-940df9b11fadafc6.js} +1 -1
  298. package/.next/static/chunks/{2619-04bc32f026a0d946.js → 2619-a305ad4810f1393a.js} +1 -1
  299. package/.next/static/chunks/5449-6cb80bab2bd06b79.js +1 -0
  300. package/.next/static/chunks/7705-1f58d4c03d991fcf.js +1 -0
  301. package/.next/static/chunks/8165-3525fb42f1b4976e.js +1 -0
  302. package/.next/static/chunks/app/{layout-8ff4c7c08ef1f621.js → layout-057c850cd0df978e.js} +1 -1
  303. package/.next/static/chunks/app/review/page-ff9efae3f86eb840.js +1 -0
  304. package/.next/static/chunks/app/skills/[skillId]/page-74aac15286504ef4.js +1 -0
  305. package/.next/static/chunks/app/skills/page-182e16168b2fc098.js +1 -0
  306. package/.next/static/chunks/app/worktrees/[id]/page-eab0bf7564d3f9e2.js +1 -0
  307. package/.next/static/chunks/app/worktrees/[id]/terminal/{page-373ea37b16d930c7.js → page-c601f3b3ece6557e.js} +1 -1
  308. package/.next/trace +13 -13
  309. package/README.md +3 -3
  310. package/dist/cli/commands/ask.d.ts.map +1 -1
  311. package/dist/cli/commands/ask.js +23 -149
  312. package/dist/cli/commands/reply.d.ts +40 -0
  313. package/dist/cli/commands/reply.d.ts.map +1 -0
  314. package/dist/cli/commands/reply.js +133 -0
  315. package/dist/cli/commands/verify.d.ts.map +1 -1
  316. package/dist/cli/commands/verify.js +9 -0
  317. package/dist/cli/commands/wait.d.ts +5 -0
  318. package/dist/cli/commands/wait.d.ts.map +1 -1
  319. package/dist/cli/commands/wait.js +10 -1
  320. package/dist/cli/docs/agent-operations.d.ts +2 -2
  321. package/dist/cli/docs/agent-operations.d.ts.map +1 -1
  322. package/dist/cli/docs/agent-operations.js +13 -0
  323. package/dist/cli/program.d.ts.map +1 -1
  324. package/dist/cli/program.js +4 -0
  325. package/dist/cli/types/index.d.ts +2 -0
  326. package/dist/cli/types/index.d.ts.map +1 -1
  327. package/dist/cli/utils/reply-ledger.d.ts +95 -0
  328. package/dist/cli/utils/reply-ledger.d.ts.map +1 -0
  329. package/dist/cli/utils/reply-ledger.js +187 -0
  330. package/dist/lib/cli-tools/copilot-executable.d.ts +9 -0
  331. package/dist/lib/cli-tools/copilot-executable.d.ts.map +1 -1
  332. package/dist/lib/cli-tools/copilot-executable.js +21 -5
  333. package/dist/lib/cli-tools/opencode-executable.d.ts +103 -0
  334. package/dist/lib/cli-tools/opencode-executable.d.ts.map +1 -0
  335. package/dist/lib/cli-tools/opencode-executable.js +179 -0
  336. package/dist/lib/cli-tools/types.d.ts +1 -1
  337. package/dist/lib/cli-tools/types.d.ts.map +1 -1
  338. package/dist/lib/cli-tools/types.js +5 -1
  339. package/dist/lib/detection/tools/verified-against.d.ts +15 -0
  340. package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
  341. package/dist/lib/detection/tools/verified-against.js +17 -1
  342. package/dist/lib/detection/version-probes.d.ts.map +1 -1
  343. package/dist/lib/detection/version-probes.js +14 -1
  344. package/dist/lib/session/tmux-session-surface.d.ts.map +1 -1
  345. package/dist/lib/session/tmux-session-surface.js +1 -1
  346. package/dist/server/locales/en/worktree.json +44 -14
  347. package/dist/server/locales/ja/worktree.json +44 -14
  348. package/dist/server/server.js +23 -0
  349. package/dist/server/src/config/cli-tool-timing-config.js +19 -1
  350. package/dist/server/src/config/detection-evidence-config.js +3 -0
  351. package/dist/server/src/config/schedule-config.js +55 -1
  352. package/dist/server/src/lib/auto-yes-poller.js +47 -4
  353. package/dist/server/src/lib/cli-tools/agent-mode-spec.js +54 -2
  354. package/dist/server/src/lib/cli-tools/base.js +6 -2
  355. package/dist/server/src/lib/cli-tools/command-code.js +55 -1
  356. package/dist/server/src/lib/cli-tools/composer-spec.js +10 -0
  357. package/dist/server/src/lib/cli-tools/copilot-executable.js +21 -5
  358. package/dist/server/src/lib/cli-tools/graceful-exit.js +15 -1
  359. package/dist/server/src/lib/cli-tools/index.js +3 -1
  360. package/dist/server/src/lib/cli-tools/install-hints.js +9 -3
  361. package/dist/server/src/lib/cli-tools/liveness-spec.js +19 -0
  362. package/dist/server/src/lib/cli-tools/manager.js +2 -0
  363. package/dist/server/src/lib/cli-tools/opencode-executable.js +179 -0
  364. package/dist/server/src/lib/cli-tools/opencode-v2.js +369 -0
  365. package/dist/server/src/lib/cli-tools/opencode.js +29 -5
  366. package/dist/server/src/lib/cli-tools/types.js +5 -1
  367. package/dist/server/src/lib/cmate-cli-tool-parser.js +65 -7
  368. package/dist/server/src/lib/cmate-parser.js +12 -0
  369. package/dist/server/src/lib/cmate-validator.js +13 -1
  370. package/dist/server/src/lib/db/worktree-db.js +1 -1
  371. package/dist/server/src/lib/detection/cli-patterns.js +78 -2
  372. package/dist/server/src/lib/detection/model-info-extractor.js +79 -7
  373. package/dist/server/src/lib/detection/status-detector.js +10 -1
  374. package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +2 -1
  375. package/dist/server/src/lib/detection/tools/opencode-v2/detect.js +253 -0
  376. package/dist/server/src/lib/detection/tools/opencode-v2/dialog-title.js +48 -0
  377. package/dist/server/src/lib/detection/tools/registry.js +2 -0
  378. package/dist/server/src/lib/detection/tools/run-detection.js +9 -0
  379. package/dist/server/src/lib/detection/tools/verified-against.js +17 -1
  380. package/dist/server/src/lib/detection/upstream-faults.js +8 -0
  381. package/dist/server/src/lib/detection/version-probes.js +14 -1
  382. package/dist/server/src/lib/hooks/agent-session-telemetry.js +36 -1
  383. package/dist/server/src/lib/hooks/sources/opencode/log-diagnosis.js +105 -0
  384. package/dist/server/src/lib/hooks/sources/opencode/source.js +7 -1
  385. package/dist/server/src/lib/hooks/sources/opencode-v2/client.js +422 -0
  386. package/dist/server/src/lib/hooks/sources/opencode-v2/decision-labels.js +24 -0
  387. package/dist/server/src/lib/hooks/sources/opencode-v2/history.js +421 -0
  388. package/dist/server/src/lib/hooks/sources/opencode-v2/ingest.js +271 -0
  389. package/dist/server/src/lib/hooks/sources/opencode-v2/mappers.js +165 -0
  390. package/dist/server/src/lib/hooks/sources/opencode-v2/payloads.js +351 -0
  391. package/dist/server/src/lib/hooks/sources/opencode-v2/ports.js +230 -0
  392. package/dist/server/src/lib/hooks/sources/opencode-v2/reattach.js +149 -0
  393. package/dist/server/src/lib/hooks/sources/opencode-v2/runtime.js +180 -0
  394. package/dist/server/src/lib/hooks/sources/opencode-v2/secrets.js +182 -0
  395. package/dist/server/src/lib/hooks/sources/opencode-v2/source.js +295 -0
  396. package/dist/server/src/lib/hooks/sources/opencode-v2/subscription.js +455 -0
  397. package/dist/server/src/lib/hooks/sources/opencode-v2/tool-id.js +18 -0
  398. package/dist/server/src/lib/hooks/sources/opencode-v2/usage.js +214 -0
  399. package/dist/server/src/lib/hooks/sources/registry.js +2 -0
  400. package/dist/server/src/lib/hooks/structured-decision-response.js +14 -5
  401. package/dist/server/src/lib/job-executor.js +2 -1
  402. package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +15 -1
  403. package/dist/server/src/lib/polling/structured-history-gate.js +19 -5
  404. package/dist/server/src/lib/relay/relay-delivery.js +4 -1
  405. package/dist/server/src/lib/session/agent-event-state.js +24 -0
  406. package/dist/server/src/lib/session/claude-executor.js +184 -10
  407. package/dist/server/src/lib/session/current-output-builder.js +27 -3
  408. package/dist/server/src/lib/session/send-user-message.js +4 -0
  409. package/dist/server/src/lib/session/structured-prompt.js +54 -0
  410. package/dist/server/src/lib/session/tmux-session-surface.js +1 -1
  411. package/dist/server/src/lib/skills/compatibility-matrix.js +65 -0
  412. package/dist/server/src/lib/tmux/tmux.js +48 -2
  413. package/dist/server/src/lib/verification/env-clean-gate.js +228 -9
  414. package/dist/server/src/lib/verification/env-snapshot.js +65 -1
  415. package/dist/server/src/types/cli-tool-contracts.js +10 -2
  416. package/dist/types/cli-tool-contracts.d.ts +16 -5
  417. package/dist/types/cli-tool-contracts.d.ts.map +1 -1
  418. package/dist/types/cli-tool-contracts.js +10 -2
  419. package/package.json +2 -1
  420. package/release-notes/0.42.2.json +20 -0
  421. package/release-notes/0.43.0.json +130 -0
  422. package/scripts/hooks/cmate-agent-event.sh +14 -0
  423. package/scripts/opencode-v2/launch.sh +226 -0
  424. package/.next/server/chunks/4443.js +0 -3
  425. package/.next/server/chunks/5164.js +0 -1
  426. package/.next/server/chunks/650.js +0 -1
  427. package/.next/static/chunks/5449-550bd273dccc3ae4.js +0 -1
  428. package/.next/static/chunks/7705-2a2936551b0cf9a3.js +0 -1
  429. package/.next/static/chunks/8165-934ee7ff3b4ddfd4.js +0 -1
  430. package/.next/static/chunks/app/review/page-30616daa1dc595c2.js +0 -1
  431. package/.next/static/chunks/app/skills/[skillId]/page-ab7e432b69fccb3b.js +0 -1
  432. package/.next/static/chunks/app/skills/page-56b4fa11223e0cbd.js +0 -1
  433. package/.next/static/chunks/app/worktrees/[id]/page-3c946bd2875391fd.js +0 -1
  434. /package/.next/static/{3M_S0B7dhEDdVE2XSJz1Y → BVkBYdceLRvMROqQIqeBx}/_buildManifest.js +0 -0
  435. /package/.next/static/{3M_S0B7dhEDdVE2XSJz1Y → BVkBYdceLRvMROqQIqeBx}/_ssgManifest.js +0 -0
@@ -24,6 +24,7 @@
24
24
  * | gemini | 0.58.0 | `app.cycleApprovalMode` (docs) | **NOT MEASURED** — see below |
25
25
  * | opencode | 1.18.30 | agent switch, not a mode | — (already shipped as #2046's quick keys) |
26
26
  * | vibe-local | — | nothing (5 presses, no change) | — (`-y` AUTO-APPROVE is fixed) |
27
+ * | opencode-v2 | 2.0.18 | agent switch (Build ⇄ Plan) | build ⇄ plan (declared since #3038) |
27
28
  *
28
29
  * ## The three tools this table deliberately leaves out
29
30
  *
@@ -32,6 +33,9 @@
32
33
  * mode spec would put a second button on the same key with a different
33
34
  * promise. The separation is a DECLARATION (no entry here), not a tool-id
34
35
  * check in the UI.
36
+ * (OpenCode V2 is NOT left out any more — see {@link OPENCODE_V2_MODE_SPEC}.
37
+ * #2966 left it out for v1's reason; #3038 moved its `shift+tab` from the
38
+ * quick keys to the mode button, so there is still one button per key.)
35
39
  * - **vibe-local.** Five presses produced a byte-identical frame. There is no
36
40
  * mode to cycle; the wrapper fixes `-y`.
37
41
  * - **gemini.** Its bundled `docs/reference/keyboard-shortcuts.md` does bind
@@ -44,12 +48,13 @@
44
48
  *
45
49
  * ## Why the indicators are patterns on a windowed tail and not positions
46
50
  *
47
- * The five declaring tools put the mode in five structurally different places —
51
+ * The declaring tools put the mode in structurally different places —
48
52
  * a dedicated footer row (claude), an independent row above the shortcut hint
49
53
  * (Command Code 1.53.1) or *replacing* it (1.49.0), the right end of a status
50
54
  * bar (codex), a word spliced into a hint bar whose element count changes with
51
55
  * the mode (copilot), and a right-aligned footer segment plus a banner inside
52
- * the composer box (agy). No column index, no row offset and no "nth segment"
56
+ * the composer box (agy), and the agent row under the composer (OpenCode V2).
57
+ * No column index, no row offset and no "nth segment"
53
58
  * rule survives that set, so each tool declares what its row LOOKS like and the
54
59
  * reader scans a small window of non-blank tail rows for it.
55
60
  *
@@ -290,6 +295,52 @@ const ANTIGRAVITY_MODE_SPEC = {
290
295
  tailRows: 2,
291
296
  noteId: null,
292
297
  };
298
+ /**
299
+ * OpenCode V2's agent row, directly under the composer (Issue #3038).
300
+ *
301
+ * `shift+tab` on 2.0.18 toggles the AGENT, not a permission mode — `Build`
302
+ * (edits allowed) ⇄ `Plan` (read only) — on the home screen and inside a session
303
+ * alike, and the composer's last row names it. Measured 2026-09-30 through
304
+ * `scripts/opencode-v2/launch.sh` on a private tmux socket, 80x200
305
+ * (`tests/fixtures/opencode-v2-agent-mode-3038/`):
306
+ *
307
+ * ` ┃ Build · LongCat 2.5 Preview Free OpenCode Zen` (home, 4th row up)
308
+ * ` ┃ Plan · LongCat 2.5 Preview Free OpenCode Zen` (session, 3rd row up)
309
+ *
310
+ * Two rows the patterns must NOT read, both on the same screen:
311
+ *
312
+ * - the completion row a finished turn leaves in the transcript,
313
+ * ` Build · LongCat 2.5 Preview Free · 4.9s · 8.1 tok/s`. On 2.0.18 it
314
+ * has no gutter at all (v1 drew `▣` there); the required `┃` excludes it;
315
+ * - the user's own message, drawn in the same `┃ <text>` gutter. It is above
316
+ * the composer, so the tail window below cannot reach it on a frame where
317
+ * the composer is drawn.
318
+ *
319
+ * Both agents are drawn, so unlike codex / copilot / agy there is no silent
320
+ * base mode here: a frame without the row (a permission or question dialog
321
+ * replaces the composer) reads `unknown`.
322
+ *
323
+ * `build` is its own id rather than `default` — the chip says what the pane
324
+ * says (#2592) — and the `opencodeAgentSwitch` note tells the user this button
325
+ * switches the agent, which its "permission mode" aria label does not.
326
+ *
327
+ * The same key was `OpencodeQuickKeys`' v2 `agentNext` until #3038. It was
328
+ * taken off the strip in the same change, so the key has one button.
329
+ */
330
+ const OPENCODE_V2_MODE_SPEC = {
331
+ key: 'BTab',
332
+ cycle: ['build', 'plan'],
333
+ indicators: [
334
+ { mode: 'build', pattern: /^[^\S\n]*┃[^\S\n]+Build[^\S\n]·[^\S\n]/ },
335
+ { mode: 'plan', pattern: /^[^\S\n]*┃[^\S\n]+Plan[^\S\n]·[^\S\n]/ },
336
+ ],
337
+ // The home screen draws `2.0.18` under the footer, which puts the agent row
338
+ // 4th from the bottom; in a session it is 3rd (footer, `╹▀▀▀`, agent row).
339
+ // Four and no more: the fifth row up is the composer's own gutter, and above
340
+ // that is the transcript, where the user's `┃ …` message lives.
341
+ tailRows: 4,
342
+ noteId: 'opencodeAgentSwitch',
343
+ };
293
344
  /**
294
345
  * The declarations, keyed by tool.
295
346
  *
@@ -304,6 +355,7 @@ const AGENT_MODE_SPECS = {
304
355
  codex: CODEX_MODE_SPEC,
305
356
  copilot: COPILOT_MODE_SPEC,
306
357
  antigravity: ANTIGRAVITY_MODE_SPEC,
358
+ 'opencode-v2': OPENCODE_V2_MODE_SPEC,
307
359
  };
308
360
  /**
309
361
  * How one CLI cycles its permission mode, or `null` when it does not have one.
@@ -595,8 +595,10 @@ class BaseCLITool {
595
595
  * against `NAVIGATION_KEY_VALUES` anyway, because a future edit could still
596
596
  * add an override to one of them.
597
597
  *
598
- * THREE tools override it now:
598
+ * FOUR tools override it now:
599
599
  * - opencode, with its `ctrl+x` leader and chord letters (#2046);
600
+ * - OpenCode V2, with the same leader and a narrower set measured on 2.0.18
601
+ * (`OPENCODE_V2_NAVIGATION_KEY_VALUES`, #2966);
600
602
  * - claude and Command Code, with `CLAUDE_NAVIGATION_KEY_VALUES` — the base
601
603
  * pad plus `s`, the key claude's `/model` footer offers for "use this
602
604
  * session only" while `Enter` on the same overlay rewrites the user's
@@ -611,8 +613,10 @@ class BaseCLITool {
611
613
  * Declare how this tool cycles its permission mode (Issue #2592).
612
614
  *
613
615
  * The default is `null` — "this tool has no mode on `shift+tab`" — and that is
614
- * the answer for three of the eight: opencode (whose `BTab` switches AGENTS,
616
+ * the answer for four of the nine: opencode (whose `BTab` switches AGENTS,
615
617
  * and already has `OpencodeQuickKeys`' `agentPrev` button from #2046),
618
+ * OpenCode V2 (the same: `BTab` toggles Build ⇄ Plan on 2.0.18 and is its
619
+ * quick keys' `agentNext`, #2966),
616
620
  * vibe-local (measured: five presses, byte-identical frame) and gemini (its
617
621
  * own docs bind `app.cycleApprovalMode`, but sign-in refused the CLI and the
618
622
  * footer spelling was never measured — a button is a promise about what
@@ -36,7 +36,7 @@
36
36
  * only the correlation.
37
37
  */
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.CommandCodeTool = exports.COMMAND_CODE_EXIT_COMMAND = exports.COMMAND_CODE_LAUNCH_FLAGS = exports.COMMAND_CODE_COMMAND = void 0;
39
+ exports.CommandCodeTool = exports.COMMAND_CODE_STARTING_WINDOW_MS = exports.COMMAND_CODE_EXIT_COMMAND = exports.COMMAND_CODE_LAUNCH_FLAGS = exports.COMMAND_CODE_COMMAND = void 0;
40
40
  exports.buildCommandCodeLaunchCommand = buildCommandCodeLaunchCommand;
41
41
  exports.isCommandCodeReady = isCommandCodeReady;
42
42
  const base_1 = require("./base");
@@ -51,6 +51,7 @@ const tool_id_1 = require("../../lib/hooks/sources/command-code/tool-id");
51
51
  const agent_session_lifecycle_1 = require("../../lib/session/agent-session-lifecycle");
52
52
  const cli_tool_timing_config_1 = require("../../config/cli-tool-timing-config");
53
53
  const install_hints_1 = require("./install-hints");
54
+ const session_start_error_1 = require("../../lib/session/session-start-error");
54
55
  const logger = (0, logger_1.createLogger)('cli-tools/command-code');
55
56
  /** The executable CommandMate launches. See the module docblock for why not `cmd`. */
56
57
  exports.COMMAND_CODE_COMMAND = 'commandcode';
@@ -106,6 +107,16 @@ const COMMAND_CODE_POLL_INTERVAL_MS = 1000;
106
107
  const COMMAND_CODE_INIT_MAX_ATTEMPTS = 30;
107
108
  /** Timeout for waiting for the composer before sending a message. */
108
109
  const COMMAND_CODE_PROMPT_WAIT_TIMEOUT_MS = 15000;
110
+ /**
111
+ * How long after a launch a composer that has never been seen still counts as
112
+ * "starting" (Issue #3006).
113
+ *
114
+ * Past this, a pane that has shown no composer since it was launched is not
115
+ * slow, it is stuck on something (an unmeasured dialog, a crash screen), and
116
+ * `prompt not ready` — which #3007 answers by reading the screen — is the
117
+ * truer report than "retry in a few seconds".
118
+ */
119
+ exports.COMMAND_CODE_STARTING_WINDOW_MS = 120_000;
109
120
  /** Rows of pane tail the readiness probe reads. */
110
121
  const COMMAND_CODE_READINESS_CAPTURE_LINES = 50;
111
122
  /**
@@ -141,6 +152,20 @@ class CommandCodeTool extends base_1.BaseCLITool {
141
152
  id = 'command-code';
142
153
  name = 'Command Code CLI';
143
154
  command = exports.COMMAND_CODE_COMMAND;
155
+ /**
156
+ * Sessions this instance launched whose composer has not been seen since,
157
+ * keyed by tmux session name, valued by launch time (Issue #3006).
158
+ *
159
+ * This is what tells a slow cold start apart from a live session that is
160
+ * showing something other than the composer. Only the launch path adds an
161
+ * entry, and any readiness probe that sees the composer removes it, so a
162
+ * session that has ever reached its composer keeps the old
163
+ * `prompt not ready` refusal. Held per instance rather than per module
164
+ * because `CLIToolManager` holds one instance for the process, and a restart
165
+ * forgets it — which errs towards `prompt not ready`, the answer this
166
+ * repository gave before.
167
+ */
168
+ composerPendingSince = new Map();
144
169
  /**
145
170
  * Declare the claude-family pad (Issue #2297).
146
171
  *
@@ -209,6 +234,9 @@ class CommandCodeTool extends base_1.BaseCLITool {
209
234
  // launch below then fails: falling back to the screen scraper is always safe
210
235
  // and trusting a dead session's events is not.
211
236
  (0, agent_session_lifecycle_1.beginAgentSession)({ worktreeId, cliToolId: tool_id_1.COMMAND_CODE_CLI_TOOL_ID, instanceId });
237
+ // Issue #3006: from here until a readiness probe sees the composer, a send
238
+ // that cannot find it is reporting a slow start, not a wedged session.
239
+ this.composerPendingSince.set(sessionName, Date.now());
212
240
  try {
213
241
  if (!exists) {
214
242
  // Inline-rendered, so the pane keeps scrollback; depth comes from the
@@ -229,6 +257,7 @@ class CommandCodeTool extends base_1.BaseCLITool {
229
257
  logger.info('started-command-code-session');
230
258
  }
231
259
  catch (error) {
260
+ this.composerPendingSince.delete(sessionName);
232
261
  throw new Error(`Failed to start Command Code session: ${(0, errors_1.getErrorMessage)(error)}`);
233
262
  }
234
263
  }
@@ -246,6 +275,7 @@ class CommandCodeTool extends base_1.BaseCLITool {
246
275
  try {
247
276
  const rawOutput = await (0, tmux_1.capturePane)(sessionName, COMMAND_CODE_READINESS_CAPTURE_LINES);
248
277
  if (isCommandCodeReady(rawOutput)) {
278
+ this.composerPendingSince.delete(sessionName);
249
279
  logger.info('command-code-prompt-detected');
250
280
  return;
251
281
  }
@@ -262,6 +292,15 @@ class CommandCodeTool extends base_1.BaseCLITool {
262
292
  * Mirrors CodexTool.waitForPrompt: throws on timeout so a failed readiness
263
293
  * check STOPS the send rather than typing into a non-ready TUI.
264
294
  *
295
+ * Issue #3006: when the session was launched by this server and its composer
296
+ * has not been seen once since — the cold start of a dispatch — the timeout
297
+ * is a {@link SessionStartTimeoutError} (`SESSION_STARTING`, 503 at the send
298
+ * route), the same answer claude gives for a start that is merely slow. A
299
+ * session that HAS shown its composer keeps the plain `prompt not ready`
300
+ * error: it is up, and something on screen is in the way.
301
+ *
302
+ * @throws SessionStartTimeoutError when a just-launched session's composer
303
+ * has still not appeared
265
304
  * @throws Error when the composer is not detected within the timeout
266
305
  */
267
306
  async waitForPrompt(sessionName) {
@@ -271,6 +310,7 @@ class CommandCodeTool extends base_1.BaseCLITool {
271
310
  try {
272
311
  const rawOutput = await (0, tmux_1.capturePane)(sessionName, COMMAND_CODE_READINESS_CAPTURE_LINES);
273
312
  if (isCommandCodeReady(rawOutput)) {
313
+ this.composerPendingSince.delete(sessionName);
274
314
  return;
275
315
  }
276
316
  }
@@ -279,6 +319,16 @@ class CommandCodeTool extends base_1.BaseCLITool {
279
319
  }
280
320
  await new Promise((resolve) => setTimeout(resolve, pollInterval));
281
321
  }
322
+ const launchedAt = this.composerPendingSince.get(sessionName);
323
+ if (launchedAt !== undefined) {
324
+ const sinceLaunchMs = Date.now() - launchedAt;
325
+ if (sinceLaunchMs <= exports.COMMAND_CODE_STARTING_WINDOW_MS) {
326
+ logger.info('command-code-session-still-starting', { sessionName, sinceLaunchMs });
327
+ throw new session_start_error_1.SessionStartTimeoutError(this.name, sessionName, sinceLaunchMs);
328
+ }
329
+ // Too long since the launch to call it slow; report it as not ready.
330
+ this.composerPendingSince.delete(sessionName);
331
+ }
282
332
  logger.info('command-code-prompt-not-ready');
283
333
  throw new Error('Command Code prompt not ready: timed out waiting for the composer before sending');
284
334
  }
@@ -312,6 +362,9 @@ class CommandCodeTool extends base_1.BaseCLITool {
312
362
  logger.info('sent-message-to-command-code-session');
313
363
  }
314
364
  catch (error) {
365
+ // Issue #3006: passed through unwrapped so its `code` reaches the route.
366
+ if ((0, session_start_error_1.isSessionStartTimeoutError)(error))
367
+ throw error;
315
368
  throw new Error(`Failed to send message to Command Code: ${(0, errors_1.getErrorMessage)(error)}`);
316
369
  }
317
370
  }
@@ -338,6 +391,7 @@ class CommandCodeTool extends base_1.BaseCLITool {
338
391
  await new Promise((resolve) => setTimeout(resolve, cli_tool_timing_config_1.TUI_EXIT_WAIT_MS));
339
392
  }
340
393
  const killed = await (0, tmux_1.killSession)(sessionName);
394
+ this.composerPendingSince.delete(sessionName);
341
395
  // So a later session reusing the name starts clean.
342
396
  (0, tmux_capture_cache_1.invalidateCache)(sessionName);
343
397
  if (killed) {
@@ -87,6 +87,16 @@ const COMPOSER_SPECS = {
87
87
  clearBeforeSend: false,
88
88
  submitEnterCount: 1,
89
89
  },
90
+ // Issue #2934: OpenCode V2 draws the same gutter-and-no-marker input box as
91
+ // v1 (`┃ Ask anything… "…"` on 2.0.18, 80x200), so the box reader is the
92
+ // right one — the marker reader would find nothing and classify every send
93
+ // `submitted` without evidence. Same pane height as v1's.
94
+ 'opencode-v2': {
95
+ reader: 'opencode-box',
96
+ verifyCaptureLines: tmux_pane_config_1.OPENCODE_PANE_HEIGHT,
97
+ clearBeforeSend: false,
98
+ submitEnterCount: 1,
99
+ },
90
100
  };
91
101
  /**
92
102
  * The composer description for a CLI tool.
@@ -39,6 +39,7 @@
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.COPILOT_VERSION_PROBE_TIMEOUT_MS = void 0;
41
41
  exports.findExecutableOnPath = findExecutableOnPath;
42
+ exports.findExecutablesOnPath = findExecutablesOnPath;
42
43
  exports.resolveCopilotExecutable = resolveCopilotExecutable;
43
44
  const child_process_1 = require("child_process");
44
45
  const fs_1 = require("fs");
@@ -83,17 +84,32 @@ function isExecutableFile(candidate) {
83
84
  * is; what is copilot-specific is the caller below.
84
85
  */
85
86
  function findExecutableOnPath(name) {
87
+ return findExecutablesOnPath(name, 1)[0] ?? null;
88
+ }
89
+ /**
90
+ * Every executable named `name` on `PATH`, in `PATH` order, up to `limit`.
91
+ *
92
+ * Issue #2939: `opencode` can name two different programs on one machine
93
+ * (OpenCode 1.x's installer and `@opencode/cli`, which registers `opencode`
94
+ * next to `opencode2`), so "the first one" is not always the one a tool wants.
95
+ * The same walk as {@link findExecutableOnPath}, not a second copy of it.
96
+ */
97
+ function findExecutablesOnPath(name, limit = Infinity) {
86
98
  const rawPath = process.env.PATH;
87
- if (!rawPath)
88
- return null;
99
+ if (!rawPath || limit <= 0)
100
+ return [];
101
+ const found = [];
89
102
  for (const directory of rawPath.split(path_1.delimiter)) {
90
103
  if (!directory)
91
104
  continue;
92
105
  const candidate = (0, path_1.join)(directory, name);
93
- if (isExecutableFile(candidate))
94
- return candidate;
106
+ if (found.includes(candidate) || !isExecutableFile(candidate))
107
+ continue;
108
+ found.push(candidate);
109
+ if (found.length >= limit)
110
+ break;
95
111
  }
96
- return null;
112
+ return found;
97
113
  }
98
114
  /**
99
115
  * Where `gh copilot` puts the copy it downloads.
@@ -42,7 +42,7 @@
42
42
  * @module lib/cli-tools/graceful-exit
43
43
  */
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
- exports.DEFAULT_GRACEFUL_EXIT_SPEC = exports.GEMINI_EXIT_COMMAND_TEXT = exports.COMMAND_CODE_EXIT_COMMAND_TEXT = exports.OPENCODE_EXIT_COMMAND_TEXT = exports.COPILOT_EXIT_COMMAND_TEXT = void 0;
45
+ exports.DEFAULT_GRACEFUL_EXIT_SPEC = exports.GEMINI_EXIT_COMMAND_TEXT = exports.COMMAND_CODE_EXIT_COMMAND_TEXT = exports.OPENCODE_V2_EXIT_COMMAND_TEXT = exports.OPENCODE_EXIT_COMMAND_TEXT = exports.COPILOT_EXIT_COMMAND_TEXT = void 0;
46
46
  exports.resolveGracefulExitSpec = resolveGracefulExitSpec;
47
47
  exports.verifyGracefulExit = verifyGracefulExit;
48
48
  const copilot_constants_1 = require("../../config/copilot-constants");
@@ -52,6 +52,8 @@ const cli_tool_contracts_1 = require("../../types/cli-tool-contracts");
52
52
  exports.COPILOT_EXIT_COMMAND_TEXT = '/exit';
53
53
  /** The graceful exit command opencode's TUI accepts. */
54
54
  exports.OPENCODE_EXIT_COMMAND_TEXT = '/exit';
55
+ /** OpenCode V2's quit command (Issue #2934) — the TUI's own `/exit`. */
56
+ exports.OPENCODE_V2_EXIT_COMMAND_TEXT = '/exit';
55
57
  /** Command Code's own quit command (Issue #2250). */
56
58
  exports.COMMAND_CODE_EXIT_COMMAND_TEXT = '/exit';
57
59
  /** The graceful exit command gemini's TUI accepts. */
@@ -141,6 +143,18 @@ const GRACEFUL_EXIT_SPECS = {
141
143
  exitWaitMs: cli_tool_timing_config_1.OPENCODE_EXIT_WAIT_MS,
142
144
  ownsLoopbackServer: true,
143
145
  },
146
+ // Issue #2934: `/exit` and a separate Enter, as for v1. The server is not the
147
+ // TUI here but `opencode2 serve` in the same pane, stopped by
148
+ // `scripts/opencode-v2/launch.sh`'s trap when the TUI goes — so the pane still
149
+ // owns a loopback port, and the postcondition checks it stopped answering.
150
+ 'opencode-v2': {
151
+ keys: [
152
+ (0, cli_tool_contracts_1.literalStep)(exports.OPENCODE_V2_EXIT_COMMAND_TEXT, cli_tool_timing_config_1.TUI_TEXT_INPUT_WAIT_MS),
153
+ (0, cli_tool_contracts_1.keyStep)('Enter'),
154
+ ],
155
+ exitWaitMs: cli_tool_timing_config_1.OPENCODE_V2_EXIT_WAIT_MS,
156
+ ownsLoopbackServer: true,
157
+ },
144
158
  };
145
159
  /**
146
160
  * The graceful-exit description for a CLI tool.
@@ -6,7 +6,7 @@
6
6
  * @module cli-tools
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.CLIToolManager = exports.buildCommandCodeLaunchCommand = exports.CommandCodeTool = exports.AntigravityTool = exports.GeminiTool = exports.CodexTool = exports.ClaudeTool = exports.BaseCLITool = exports.DEFAULT_GRACEFUL_EXIT_SPEC = exports.verifyGracefulExit = exports.resolveGracefulExitSpec = exports.GEMINI_PANE_HEIGHT = exports.resolveCaptureSpec = exports.DEFAULT_COMPOSER_SPEC = exports.resolveComposerSpec = exports.isImageCapableCLITool = void 0;
9
+ exports.CLIToolManager = exports.OpenCodeV2Tool = exports.buildCommandCodeLaunchCommand = exports.CommandCodeTool = exports.AntigravityTool = exports.GeminiTool = exports.CodexTool = exports.ClaudeTool = exports.BaseCLITool = exports.DEFAULT_GRACEFUL_EXIT_SPEC = exports.verifyGracefulExit = exports.resolveGracefulExitSpec = exports.GEMINI_PANE_HEIGHT = exports.resolveCaptureSpec = exports.DEFAULT_COMPOSER_SPEC = exports.resolveComposerSpec = exports.isImageCapableCLITool = void 0;
10
10
  var types_1 = require("./types");
11
11
  Object.defineProperty(exports, "isImageCapableCLITool", { enumerable: true, get: function () { return types_1.isImageCapableCLITool; } });
12
12
  var composer_spec_1 = require("./composer-spec");
@@ -34,6 +34,8 @@ Object.defineProperty(exports, "AntigravityTool", { enumerable: true, get: funct
34
34
  var command_code_1 = require("./command-code");
35
35
  Object.defineProperty(exports, "CommandCodeTool", { enumerable: true, get: function () { return command_code_1.CommandCodeTool; } });
36
36
  Object.defineProperty(exports, "buildCommandCodeLaunchCommand", { enumerable: true, get: function () { return command_code_1.buildCommandCodeLaunchCommand; } });
37
+ var opencode_v2_1 = require("./opencode-v2");
38
+ Object.defineProperty(exports, "OpenCodeV2Tool", { enumerable: true, get: function () { return opencode_v2_1.OpenCodeV2Tool; } });
37
39
  // Export CLI tool manager
38
40
  var manager_1 = require("./manager");
39
41
  Object.defineProperty(exports, "CLIToolManager", { enumerable: true, get: function () { return manager_1.CLIToolManager; } });
@@ -83,6 +83,8 @@ exports.CLI_TOOL_INSTALL_HINTS = {
83
83
  opencode: 'Install with: npm install -g opencode-ai',
84
84
  copilot: copilot_constants_1.COPILOT_INSTALL_HINT,
85
85
  'command-code': 'Install with: npm install -g command-code',
86
+ // Issue #2934: the package installs the `opencode2` executable.
87
+ 'opencode-v2': 'Install with: npm install -g @opencode/cli',
86
88
  // No package to name: `agy` ships with Antigravity and updates itself. The
87
89
  // URL is lifted from the binary on PATH rather than from a search result.
88
90
  antigravity: 'Install the Antigravity CLI: https://antigravity.google/docs/cli/reference',
@@ -114,18 +116,22 @@ function getCliToolInstallHint(id) {
114
116
  * and #2009's contract is that the phrase survives.
115
117
  *
116
118
  * @param tool - The tool that could not be started
119
+ * @param detail - Why, when there is more to say than "not on PATH" — e.g.
120
+ * `opencode` is there but is OpenCode V2 (Issue #2939)
117
121
  * @returns A sentence safe to hand back to an HTTP caller
118
122
  */
119
- function buildMissingToolMessage(tool) {
123
+ function buildMissingToolMessage(tool, detail) {
120
124
  return (`${tool.name} (${tool.command}) is not installed or not in PATH. ` +
125
+ (detail ? `${detail} ` : '') +
121
126
  `${getCliToolInstallHint(tool.id)}`);
122
127
  }
123
128
  /**
124
129
  * The typed refusal, carrying {@link buildMissingToolMessage}.
125
130
  *
126
131
  * @param tool - The tool that could not be started
132
+ * @param detail - See {@link buildMissingToolMessage}
127
133
  * @returns The error every launch path throws for a missing binary
128
134
  */
129
- function missingToolError(tool) {
130
- return new session_start_error_1.SessionStartUnavailableError(tool.name, buildMissingToolMessage(tool));
135
+ function missingToolError(tool, detail) {
136
+ return new session_start_error_1.SessionStartUnavailableError(tool.name, buildMissingToolMessage(tool, detail));
131
137
  }
@@ -211,6 +211,25 @@ const LIVENESS_SPECS = {
211
211
  cli_patterns_1.COMMAND_CODE_THINKING_PATTERN,
212
212
  ],
213
213
  },
214
+ /**
215
+ * OpenCode V2 2.0.18 — measured at 80x200 (Issue #2934).
216
+ *
217
+ * The footer (`… ctrl+p commands`) is drawn on every frame the TUI paints,
218
+ * before and after a turn and while one runs, so it alone carries liveness;
219
+ * the placeholder and the running hint are listed as well so a frame with
220
+ * either is not taken for a shell. None of the three can be matched by a
221
+ * shell prompt. After the TUI exits the alternate screen is gone and only the
222
+ * shell's rows remain, which is what makes the verdict flip.
223
+ */
224
+ 'opencode-v2': {
225
+ ...SHARED,
226
+ ...ADDED_TOOL_DEFAULTS,
227
+ alivePatterns: [
228
+ cli_patterns_1.OPENCODE_V2_IDLE_COMPOSER_PATTERN,
229
+ cli_patterns_1.OPENCODE_V2_FOOTER_PATTERN,
230
+ cli_patterns_1.OPENCODE_V2_THINKING_PATTERN,
231
+ ],
232
+ },
214
233
  /** vibe-local — patterns from `cli-patterns`; no live frames (needs Ollama). */
215
234
  'vibe-local': {
216
235
  ...SHARED,
@@ -46,6 +46,7 @@ const opencode_1 = require("./opencode");
46
46
  const copilot_1 = require("./copilot");
47
47
  const antigravity_1 = require("./antigravity");
48
48
  const command_code_1 = require("./command-code");
49
+ const opencode_v2_1 = require("./opencode-v2");
49
50
  /**
50
51
  * CLI Tool Manager (Singleton)
51
52
  * Provides centralized access to all CLI tools (Issue #368: includes Vibe Local, Issue #379: includes OpenCode)
@@ -67,6 +68,7 @@ class CLIToolManager {
67
68
  this.tools.set('copilot', new copilot_1.CopilotTool());
68
69
  this.tools.set('antigravity', new antigravity_1.AntigravityTool());
69
70
  this.tools.set('command-code', new command_code_1.CommandCodeTool());
71
+ this.tools.set('opencode-v2', new opencode_v2_1.OpenCodeV2Tool());
70
72
  }
71
73
  /**
72
74
  * Get singleton instance
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ /**
3
+ * Which `opencode` is OpenCode 1.x and which is OpenCode V2 (Issue #2939).
4
+ *
5
+ * ## Why the name is not enough
6
+ *
7
+ * OpenCode V2's npm package `@opencode/cli` (2.0.18) registers **both**
8
+ * `opencode` and `opencode2` in its `bin`. So on a machine that has it,
9
+ * `opencode` may be OpenCode 1.x (its own installer, `~/.opencode/bin`) or
10
+ * OpenCode V2 (`/opt/homebrew/bin/opencode`), decided by nothing but the order
11
+ * of `PATH`. Asking `which opencode` then answers "OpenCode is installed" for a
12
+ * V2 binary, and the v1 launch line (`opencode --port N --hostname …`) reaches
13
+ * a program that has neither flag.
14
+ *
15
+ * The answer here is the version each candidate prints about itself:
16
+ *
17
+ * - OpenCode 1.x prints a bare `1.18.33`;
18
+ * - OpenCode V2 prints `opencode v2.0.18`.
19
+ *
20
+ * Every `opencode` / `opencode2` on `PATH` is a candidate, not just the first,
21
+ * so a V2 `opencode` earlier on `PATH` no longer hides a 1.x one behind it.
22
+ *
23
+ * ## Probe and launch are one measurement
24
+ *
25
+ * The path that answered is the path the launch line runs — the rule
26
+ * `./copilot-executable` set for copilot (#1907). The server resolves names on
27
+ * its own `PATH`, the pane on its login shell's; typing a bare `opencode` would
28
+ * let the two disagree.
29
+ *
30
+ * ## Cost
31
+ *
32
+ * `opencode --version` takes ~0.4 s and both tools probe `opencode`, so one
33
+ * probe per path is shared for {@link OPENCODE_EXECUTABLE_CACHE_TTL_MS}, and a
34
+ * concurrent caller gets the probe already in flight.
35
+ *
36
+ * @module lib/cli-tools/opencode-executable
37
+ */
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.OPENCODE_EXECUTABLE_CACHE_TTL_MS = exports.OPENCODE_VERSION_PROBE_TIMEOUT_MS = exports.OPENCODE_V2_BINARY_NAME = exports.OPENCODE_V1_BINARY_NAME = void 0;
40
+ exports.parseOpencodeVersionOutput = parseOpencodeVersionOutput;
41
+ exports.clearOpencodeExecutableCache = clearOpencodeExecutableCache;
42
+ exports.probeOpencodeExecutable = probeOpencodeExecutable;
43
+ exports.resolveOpencodeV1Executable = resolveOpencodeV1Executable;
44
+ exports.resolveOpencodeV2Executable = resolveOpencodeV2Executable;
45
+ exports.describeOpencodeV1Unavailable = describeOpencodeV1Unavailable;
46
+ const child_process_1 = require("child_process");
47
+ const copilot_executable_1 = require("./copilot-executable");
48
+ const env_sanitizer_1 = require("../security/env-sanitizer");
49
+ /** OpenCode 1.x's executable name (tool id `opencode`). */
50
+ exports.OPENCODE_V1_BINARY_NAME = 'opencode';
51
+ /** OpenCode V2's own executable name (tool id `opencode-v2`). */
52
+ exports.OPENCODE_V2_BINARY_NAME = 'opencode2';
53
+ /** Budget for one `--version`. */
54
+ exports.OPENCODE_VERSION_PROBE_TIMEOUT_MS = 5000;
55
+ /** `--version` prints one short line; anything bigger is not an answer. */
56
+ const OPENCODE_VERSION_PROBE_MAX_BUFFER = 64 * 1024;
57
+ /** How long one probe result is reused (same TTL as the installed-agents cache). */
58
+ exports.OPENCODE_EXECUTABLE_CACHE_TTL_MS = 30_000;
59
+ /** Candidates probed per name. A PATH with more copies than this is not a setup to guess about. */
60
+ const MAX_CANDIDATES_PER_NAME = 4;
61
+ /** `opencode v2.0.18` — OpenCode V2's form. */
62
+ const PREFIXED_VERSION_LINE = /^opencode v(\d+)\.(\d+)\.(\d+)((?:[-+][0-9A-Za-z.-]+)?)$/;
63
+ /** `1.18.33` — OpenCode 1.x's form: the version and nothing else. */
64
+ const BARE_VERSION_LINE = /^v?(\d+)\.(\d+)\.(\d+)((?:[-+][0-9A-Za-z.-]+)?)$/;
65
+ /**
66
+ * Classify `opencode --version` / `opencode2 --version` output.
67
+ *
68
+ * A line has to be a version in one of the two forms and nothing else, so a
69
+ * different program that happens to print a number is not taken for either.
70
+ * The major version decides: 1 is OpenCode 1.x, 2 or later is OpenCode V2.
71
+ * `0.x` (the pre-1.0 `opencode`) and anything unreadable are null.
72
+ *
73
+ * @returns The generation and version, or null when the output is not OpenCode's
74
+ */
75
+ function parseOpencodeVersionOutput(output) {
76
+ for (const rawLine of output.split(/\r?\n/)) {
77
+ const line = rawLine.trim();
78
+ if (!line)
79
+ continue;
80
+ const match = PREFIXED_VERSION_LINE.exec(line) ?? BARE_VERSION_LINE.exec(line);
81
+ if (!match)
82
+ continue;
83
+ const major = Number(match[1]);
84
+ const version = `${match[1]}.${match[2]}.${match[3]}${match[4] ?? ''}`;
85
+ if (major === 1)
86
+ return { generation: 'v1', version };
87
+ if (major >= 2)
88
+ return { generation: 'v2', version };
89
+ return null;
90
+ }
91
+ return null;
92
+ }
93
+ const probeCache = new Map();
94
+ /** Forget every cached probe (tests, and a caller that knows the install changed). */
95
+ function clearOpencodeExecutableCache() {
96
+ probeCache.clear();
97
+ }
98
+ function runVersionProbe(executable) {
99
+ return new Promise((resolve) => {
100
+ try {
101
+ (0, child_process_1.execFile)(executable, ['--version'], {
102
+ timeout: exports.OPENCODE_VERSION_PROBE_TIMEOUT_MS,
103
+ maxBuffer: OPENCODE_VERSION_PROBE_MAX_BUFFER,
104
+ env: (0, env_sanitizer_1.sanitizeEnvForChildProcess)(),
105
+ }, (error, stdout, stderr) => {
106
+ if (error) {
107
+ resolve(null);
108
+ return;
109
+ }
110
+ resolve(parseOpencodeVersionOutput(`${stdout ?? ''}\n${stderr ?? ''}`));
111
+ });
112
+ }
113
+ catch {
114
+ resolve(null);
115
+ }
116
+ });
117
+ }
118
+ /** `<path> --version`, classified; cached per path. Never rejects. */
119
+ function probeOpencodeExecutable(path) {
120
+ const now = Date.now();
121
+ const cached = probeCache.get(path);
122
+ if (cached && cached.expiresAt > now)
123
+ return cached.info;
124
+ const info = runVersionProbe(path);
125
+ probeCache.set(path, { expiresAt: now + exports.OPENCODE_EXECUTABLE_CACHE_TTL_MS, info });
126
+ return info;
127
+ }
128
+ /** Probe `names` in order and return the first candidate of `generation`. */
129
+ async function resolveGeneration(names, generation) {
130
+ const probed = [];
131
+ for (const name of names) {
132
+ for (const path of (0, copilot_executable_1.findExecutablesOnPath)(name, MAX_CANDIDATES_PER_NAME)) {
133
+ if (probed.some((p) => p.path === path))
134
+ continue;
135
+ const info = await probeOpencodeExecutable(path);
136
+ probed.push({ path, info });
137
+ if (info?.generation === generation) {
138
+ return { executable: { path, version: info.version, generation }, probed };
139
+ }
140
+ }
141
+ }
142
+ return { executable: null, probed };
143
+ }
144
+ /**
145
+ * OpenCode 1.x: the first `opencode` on `PATH` that prints a 1.x version.
146
+ * An `opencode` that answers `opencode v2.x` is skipped, never launched.
147
+ */
148
+ function resolveOpencodeV1Executable() {
149
+ return resolveGeneration([exports.OPENCODE_V1_BINARY_NAME], 'v1');
150
+ }
151
+ /**
152
+ * OpenCode V2: `opencode2` first, then an `opencode` that prints
153
+ * `opencode v2.x` — for an operator who has V2 only under the `opencode` name.
154
+ */
155
+ function resolveOpencodeV2Executable() {
156
+ return resolveGeneration([exports.OPENCODE_V2_BINARY_NAME, exports.OPENCODE_V1_BINARY_NAME], 'v2');
157
+ }
158
+ /**
159
+ * Why OpenCode 1.x counts as not installed, when there is more to say than
160
+ * "no `opencode` on PATH".
161
+ *
162
+ * @returns A sentence naming the `opencode` that is there and what it is, or
163
+ * null when nothing called `opencode` was found at all
164
+ */
165
+ function describeOpencodeV1Unavailable(resolution) {
166
+ if (resolution.executable)
167
+ return null;
168
+ const v2 = resolution.probed.find((p) => p.info?.generation === 'v2');
169
+ if (v2?.info) {
170
+ return (`\`opencode\` at ${v2.path} is OpenCode V2 ${v2.info.version}, not OpenCode 1.x ` +
171
+ '(npm `@opencode/cli` registers both `opencode` and `opencode2`). ' +
172
+ 'Use the OpenCode V2 agent, or put an OpenCode 1.x `opencode` on PATH.');
173
+ }
174
+ const other = resolution.probed[0];
175
+ if (other) {
176
+ return `\`opencode\` at ${other.path} did not report an OpenCode 1.x version (\`opencode --version\`).`;
177
+ }
178
+ return null;
179
+ }