commandmate 0.31.1 → 0.31.3

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 (299) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +170 -170
  3. package/.next/app-path-routes-manifest.json +29 -29
  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/update/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/app/update-check/route.js +1 -1
  12. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  13. package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
  14. package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.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 +2 -2
  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 +2 -2
  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.nft.json +1 -1
  30. package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
  31. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  32. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/capabilities/route.js +1 -1
  35. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  38. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  41. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/hooks/agent-event/route.js +1 -1
  44. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  45. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  46. package/.next/server/app/api/hooks/claude-done/route.js +2 -2
  47. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  48. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  49. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  50. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  51. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  52. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  53. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  54. package/.next/server/app/api/push/escalation/route.js +2 -2
  55. package/.next/server/app/api/push/escalation/route.js.nft.json +1 -1
  56. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/push/subscriptions/route.js +1 -1
  58. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/push/vapid/route.js +2 -2
  60. package/.next/server/app/api/push/vapid/route.js.nft.json +1 -1
  61. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  63. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  64. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  65. package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
  66. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  67. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  68. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/repositories/clone/route.js +1 -1
  70. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  71. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  72. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  73. package/.next/server/app/api/repositories/restore/route.js +1 -1
  74. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  75. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  76. package/.next/server/app/api/repositories/route.js +1 -1
  77. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  78. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/repositories/scan/route.js +1 -1
  80. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  81. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  82. package/.next/server/app/api/repositories/sync/route.js +1 -1
  83. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  84. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  85. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  87. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  88. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  89. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  94. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  95. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  97. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  100. package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  104. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  105. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  107. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  110. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  116. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  119. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  146. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.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_client-reference-manifest.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  163. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  164. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  167. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  170. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  176. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  177. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  179. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  180. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  186. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  190. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  191. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  194. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  196. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  198. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  203. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  207. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  211. package/.next/server/app/api/worktrees/route.js +1 -1
  212. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  213. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  214. package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  215. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  216. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  217. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  218. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  219. package/.next/server/app/page_client-reference-manifest.js +1 -1
  220. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  221. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  222. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  223. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  224. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  225. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  226. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  227. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  228. package/.next/server/app/worktrees/[id]/page.js +10 -10
  229. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  230. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  231. package/.next/server/app-paths-manifest.json +29 -29
  232. package/.next/server/chunks/1058.js +1 -1
  233. package/.next/server/chunks/1068.js +1 -1
  234. package/.next/server/chunks/1191.js +2 -2
  235. package/.next/server/chunks/1886.js +1 -1
  236. package/.next/server/chunks/2119.js +1 -1
  237. package/.next/server/chunks/2404.js +1 -1
  238. package/.next/server/chunks/2445.js +1 -1
  239. package/.next/server/chunks/261.js +1 -1
  240. package/.next/server/chunks/2739.js +1 -1
  241. package/.next/server/chunks/3241.js +1 -1
  242. package/.next/server/chunks/3484.js +1 -0
  243. package/.next/server/chunks/358.js +1 -0
  244. package/.next/server/chunks/4325.js +1 -1
  245. package/.next/server/chunks/4393.js +1 -1
  246. package/.next/server/chunks/4443.js +1 -1
  247. package/.next/server/chunks/5017.js +1 -1
  248. package/.next/server/chunks/5120.js +1 -1
  249. package/.next/server/chunks/5164.js +1 -1
  250. package/.next/server/chunks/552.js +3 -3
  251. package/.next/server/chunks/595.js +8 -0
  252. package/.next/server/chunks/6130.js +1 -1
  253. package/.next/server/chunks/8800.js +1 -1
  254. package/.next/server/chunks/8918.js +3 -3
  255. package/.next/server/chunks/9123.js +1 -1
  256. package/.next/server/chunks/9130.js +2 -2
  257. package/.next/server/chunks/9627.js +3 -3
  258. package/.next/server/chunks/9696.js +2 -2
  259. package/.next/server/chunks/9798.js +2 -2
  260. package/.next/server/middleware-manifest.json +5 -5
  261. package/.next/server/pages/500.html +1 -1
  262. package/.next/server/server-reference-manifest.json +1 -1
  263. package/.next/static/chunks/{1783-11c9b4d8a52ebd91.js → 2813-de885de8a4b11910.js} +1 -1
  264. package/.next/static/chunks/4718-07ec4e10186928db.js +1 -0
  265. package/.next/static/chunks/app/worktrees/[id]/page-91b639c90795baa9.js +1 -0
  266. package/.next/static/css/acc4b9c3feb04287.css +1 -0
  267. package/.next/trace +13 -13
  268. package/dist/lib/detection/tools/verified-against.d.ts +24 -24
  269. package/dist/lib/detection/tools/verified-against.js +24 -24
  270. package/dist/server/locales/en/worktree.json +1402 -0
  271. package/dist/server/locales/ja/worktree.json +1402 -0
  272. package/dist/server/src/lib/db/chat-db.js +44 -1
  273. package/dist/server/src/lib/detection/cli-patterns.js +157 -23
  274. package/dist/server/src/lib/detection/model-info-extractor.js +185 -4
  275. package/dist/server/src/lib/detection/tools/antigravity/detect.js +105 -25
  276. package/dist/server/src/lib/detection/tools/antigravity/dialog.js +233 -0
  277. package/dist/server/src/lib/detection/tools/verified-against.js +24 -24
  278. package/dist/server/src/lib/hooks/hook-settings-generator.js +16 -0
  279. package/dist/server/src/lib/hooks/sources/claude/model-switch.js +169 -0
  280. package/dist/server/src/lib/hooks/sources/claude/source.js +14 -1
  281. package/dist/server/src/lib/polling/response-checker.js +17 -1
  282. package/dist/server/src/lib/polling/response-poller-core.js +143 -9
  283. package/dist/server/src/lib/push/index.js +13 -1
  284. package/dist/server/src/lib/push/model-change-push-notifier.js +174 -0
  285. package/dist/server/src/lib/push/notification-dedup.js +2 -1
  286. package/dist/server/src/lib/push/push-sender.js +48 -20
  287. package/dist/server/src/lib/realtime/model-change-broadcast.js +171 -0
  288. package/dist/server/src/lib/realtime/types.js +19 -1
  289. package/dist/server/src/lib/realtime/waiting-broadcast.js +13 -0
  290. package/dist/server/src/lib/session/agent-event-state.js +344 -12
  291. package/package.json +1 -1
  292. package/.next/server/chunks/6894.js +0 -8
  293. package/.next/server/chunks/7187.js +0 -1
  294. package/.next/server/chunks/7472.js +0 -1
  295. package/.next/static/chunks/4718-46e1d2f07c8423ba.js +0 -1
  296. package/.next/static/chunks/app/worktrees/[id]/page-64d4ec3051971760.js +0 -1
  297. package/.next/static/css/5c13ea243dfdcb66.css +0 -1
  298. /package/.next/static/{60mm4_QBuFtFTfo5UMyKU → 0hTIackGXw6v7diXJS6yN}/_buildManifest.js +0 -0
  299. /package/.next/static/{60mm4_QBuFtFTfo5UMyKU → 0hTIackGXw6v7diXJS6yN}/_ssgManifest.js +0 -0
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ /**
3
+ * Claude Code's `PostModelSwitch` hook, as CommandMate reads it (Issue #2363).
4
+ *
5
+ * #2361 detected a `/model` switch off the pane, because the seven events
6
+ * CommandMate registered never mentioned it: Claude names its model on
7
+ * `SessionStart` and on nothing else. The same probe found the build emitting
8
+ * a pair of dedicated hooks, and this module is the structured half of the
9
+ * answer — the frame reader stays as the fallback (see
10
+ * `lib/session/agent-event-state`'s `FRAME_OVERTAKES_HOOK_MODEL_TOOLS`).
11
+ *
12
+ * ## Measured on claude 2.1.263 (2026-09-06, isolated `CLAUDE_CONFIG_DIR`)
13
+ *
14
+ * Re-taken for this Issue rather than inherited from #2361, whose numbers were
15
+ * a by-product. Payload, delivered verbatim by a `type: "http"` hook injected
16
+ * through `--settings` — the same channel every other event here uses:
17
+ *
18
+ * ```json
19
+ * {
20
+ * "session_id": "…", "transcript_path": "…", "cwd": "…", "prompt_id": "…",
21
+ * "hook_event_name": "PostModelSwitch",
22
+ * "from_model": "claude-haiku-4-5-20251001",
23
+ * "to_model": "claude-sonnet-5",
24
+ * "requested_model": "sonnet",
25
+ * "source": "command",
26
+ * "context_tokens": 0, "prompt_cache_warm": false, "cache_ttl": "5m",
27
+ * "estimated_cache_write_usd": 0, "pricing": "catalog"
28
+ * }
29
+ * ```
30
+ *
31
+ * - **`to_model` is the model id in the `SessionStart` spelling** —
32
+ * `claude-sonnet-5`, `claude-haiku-4-5-20251001`, `claude-opus-5`,
33
+ * `claude-opus-5[1m]` — so the latch in `agent-event-state` compares like
34
+ * with like, and the `[1m]` suffix travels with it.
35
+ * - **`/fast` is a switch**: ON from Haiku reported `to_model:
36
+ * "claude-opus-5[1m]"`, `requested_model: null`, `source: "command"`. That
37
+ * is the fix for the spelling drift #2361 refused to read (the confirmation
38
+ * line says `Opus 5`, the banner `Opus 5 (1M context)`): the hook spells it
39
+ * the one way. `/fast` OFF fires nothing and the model stays on Opus.
40
+ * - **`requested_model` is null** for `/model default` (→ `claude-opus-5[1m]`)
41
+ * and for `/fast`, and is the user's alias (`sonnet`) otherwise. Never read.
42
+ * - **`source`** is `command` for `/model <arg>` and `/fast`, `picker` for the
43
+ * interactive list (measured with `s`). The schema also names `sdk`, `auto`
44
+ * and `resume`; none were reproducible. Not read.
45
+ * - **Nothing fires when the model does not change**: `/model haiku` while on
46
+ * Haiku, `/fast` while already on Opus 1M, the picker's `Esc` (`Kept model
47
+ * as`), and `/effort` all stay silent. `/clear` emits its usual
48
+ * `SessionEnd` + `SessionStart` (no `model` key) and no switch.
49
+ * - **There is no `model` key on this event.** The generic `modelFields:
50
+ * ['model']` lookup answers null for it, which is why the extraction below
51
+ * exists rather than a second entry in that list.
52
+ *
53
+ * ## Why `from_model` is never read
54
+ *
55
+ * It is the model the session was on BEFORE the switch. Reading it as "the
56
+ * model" would move the latch backwards on the very event that reports a
57
+ * forward move. It is also the field the paired `PreModelSwitch` got wrong:
58
+ * in the probe's second session that hook fired **twice per switch**, and on
59
+ * `/fast` the second of the two named `from_model: "claude-sonnet-5"` for a
60
+ * session that was on Haiku (`PostModelSwitch` fired once, and agreed with
61
+ * the screen, every time).
62
+ *
63
+ * ## Why `PreModelSwitch` is not registered
64
+ *
65
+ * Three measured reasons. It is a decision hook — its response body can block
66
+ * or redirect the switch — and the event receiver answers a fixed 202 that
67
+ * decides nothing, so registering it would put a blocking round-trip (5 s at
68
+ * worst, on a wedged server) in front of every `/model` for no information.
69
+ * It fired twice per switch with inconsistent values (above). And its
70
+ * `to_model` is the request, not the outcome — the second of that pair on
71
+ * `/model haiku` said `to_model: "claude-sonnet-5"`; `PostModelSwitch` alone
72
+ * is the event that says what happened. The Issue leaves this to
73
+ * implementation judgement, and this is it.
74
+ *
75
+ * ## Which of the seven words
76
+ *
77
+ * `notification`, with a subtype of its own ({@link modelSwitchDetail}). A
78
+ * model switch is the agent telling the human something and is neither a turn
79
+ * boundary nor a tool call; `agent-event-state` treats a `notification` whose
80
+ * subtype it does not recognise as evidence of nothing (no status, no dialog,
81
+ * no turn), and `status-mapping` answers null for it — measured behaviour, not
82
+ * a hope. The one thing every event does is run the model latch, and that is
83
+ * the whole point of delivering this one.
84
+ *
85
+ * @module lib/hooks/sources/claude/model-switch
86
+ */
87
+ Object.defineProperty(exports, "__esModule", { value: true });
88
+ exports.claudeModelSwitchMapper = exports.MODEL_SWITCH_DETAIL = exports.CLAUDE_PRE_MODEL_SWITCH_EVENT_NAME = exports.CLAUDE_POST_MODEL_SWITCH_EVENT_NAME = void 0;
89
+ exports.modelSwitchDetail = modelSwitchDetail;
90
+ exports.isModelSwitchDetail = isModelSwitchDetail;
91
+ exports.isClaudeModelSwitchPayload = isClaudeModelSwitchPayload;
92
+ exports.extractClaudeSwitchedModel = extractClaudeSwitchedModel;
93
+ const event_mapper_1 = require("../event-mapper");
94
+ /** Claude's own name for the event; the key written into `--settings`. */
95
+ exports.CLAUDE_POST_MODEL_SWITCH_EVENT_NAME = 'PostModelSwitch';
96
+ /**
97
+ * The paired decision hook, which is deliberately NOT registered — see the
98
+ * module comment. Named here so the test that pins its absence from the
99
+ * injected settings spells it the way this module does.
100
+ */
101
+ exports.CLAUDE_PRE_MODEL_SWITCH_EVENT_NAME = 'PreModelSwitch';
102
+ /**
103
+ * The subtype a switch is filed under (Issue #2363).
104
+ *
105
+ * A word of CommandMate's own, beside Claude's `permission_prompt` /
106
+ * `idle_prompt` on the same event. Nothing branches on it — the model rides on
107
+ * the normalised event's `model`, not on the subtype — but two things read it:
108
+ * `structuredEvents.lastEventDetail` shows it, and the receiver's
109
+ * de-duplication key carries it. See {@link modelSwitchDetail} for why the
110
+ * target model is appended.
111
+ */
112
+ exports.MODEL_SWITCH_DETAIL = 'model_switch';
113
+ /** The payload key that names the model the session is now on. */
114
+ const TO_MODEL_FIELD = 'to_model';
115
+ /**
116
+ * `model_switch:<to_model>`, or the bare word when the switch names no target.
117
+ *
118
+ * The target is part of the subtype because the subtype is part of the
119
+ * receiver's de-duplication key: `(instance, event, detail, session_id)` within
120
+ * a 3 s window (`isDuplicateAgentEvent`). With a fixed word, two switches to
121
+ * DIFFERENT models inside that window — the picker's `s` followed by `/fast`,
122
+ * a `/model` typed twice to correct itself — would collapse into one and the
123
+ * second target would be lost until the frame caught up. With the target in
124
+ * the key, only a second delivery of the SAME switch collapses, which is the
125
+ * case the window exists for (a user's own `PostModelSwitch` hook is
126
+ * concatenated with the injected one, and both name the same `to_model`).
127
+ */
128
+ function modelSwitchDetail(toModel) {
129
+ return toModel === null ? exports.MODEL_SWITCH_DETAIL : `${exports.MODEL_SWITCH_DETAIL}:${toModel}`;
130
+ }
131
+ /** Whether a recorded `detail` is one this module wrote, target or no target. */
132
+ function isModelSwitchDetail(detail) {
133
+ return detail === exports.MODEL_SWITCH_DETAIL || (detail?.startsWith(`${exports.MODEL_SWITCH_DETAIL}:`) ?? false);
134
+ }
135
+ /** True for the one native event this module speaks for. */
136
+ function isClaudeModelSwitchPayload(payload) {
137
+ return (0, event_mapper_1.readStringField)(payload, 'hook_event_name') === exports.CLAUDE_POST_MODEL_SWITCH_EVENT_NAME;
138
+ }
139
+ /**
140
+ * The rule that maps `PostModelSwitch` onto `notification(model_switch:<to_model>)`.
141
+ *
142
+ * Appended after the shared CamelCase table in `./source`, so every spelling
143
+ * that table already claims keeps its word.
144
+ */
145
+ const claudeModelSwitchMapper = (nativeEventName, payload) => nativeEventName === exports.CLAUDE_POST_MODEL_SWITCH_EVENT_NAME
146
+ ? {
147
+ event: 'notification',
148
+ detail: modelSwitchDetail((0, event_mapper_1.readStringField)(payload, TO_MODEL_FIELD)),
149
+ }
150
+ : null;
151
+ exports.claudeModelSwitchMapper = claudeModelSwitchMapper;
152
+ /**
153
+ * The model a `PostModelSwitch` reports, or null for any other payload.
154
+ *
155
+ * `to_model` and only `to_model`: `from_model` is the value being left behind
156
+ * and `requested_model` is an alias that is null for `/model default` and
157
+ * `/fast`. Answers null for a switch that somehow carries no `to_model`, which
158
+ * the caller (`buildNormalizedEvent`) turns into "this event names no model"
159
+ * — the latch is left where it was rather than blanked or reversed.
160
+ *
161
+ * Declared as the source's `extractModel`, which runs before the flat
162
+ * `modelFields` lookup; for every other event it answers null and the lookup
163
+ * proceeds exactly as it did before this Issue.
164
+ */
165
+ function extractClaudeSwitchedModel(payload) {
166
+ if (!isClaudeModelSwitchPayload(payload))
167
+ return null;
168
+ return (0, event_mapper_1.readStringField)(payload, TO_MODEL_FIELD);
169
+ }
@@ -41,6 +41,7 @@ const permission_request_payload_1 = require("../../../../lib/hooks/permission-r
41
41
  const define_source_1 = require("../define-source");
42
42
  const event_mapper_1 = require("../event-mapper");
43
43
  const hook_event_vocabulary_1 = require("../hook-event-vocabulary");
44
+ const model_switch_1 = require("./model-switch");
44
45
  const tool_id_1 = require("./tool-id");
45
46
  /**
46
47
  * The no-decision body, byte for byte what the #1721 spike returned for D5.
@@ -129,7 +130,12 @@ exports.claudeAgentEventSource = (0, define_source_1.definePushHookSource)({
129
130
  // word, no predicates — so it is expressed as rules built from the table
130
131
  // rather than as a table, and a source that needs conditions (opencode) adds
131
132
  // them to the same list.
132
- mappers: (0, event_mapper_1.fromNameTable)(hook_event_vocabulary_1.CAMEL_CASE_HOOK_EVENT_NAMES),
133
+ //
134
+ // Issue #2363: plus the one spelling that is Claude's alone. `PostModelSwitch`
135
+ // is filed as `notification(model_switch:<to_model>)` — see `./model-switch`
136
+ // for the measurement and for why its `Pre` twin is not here. Appended after
137
+ // the shared table so nothing that table claims changes its word.
138
+ mappers: [...(0, event_mapper_1.fromNameTable)(hook_event_vocabulary_1.CAMEL_CASE_HOOK_EVENT_NAMES), model_switch_1.claudeModelSwitchMapper],
133
139
  nativeEventNameFields: ['hook_event_name'],
134
140
  conversationIdFields: hook_event_vocabulary_1.SESSION_ID_FIELDS,
135
141
  toolCallIdFields: hook_event_vocabulary_1.TOOL_CALL_ID_FIELDS,
@@ -140,6 +146,13 @@ exports.claudeAgentEventSource = (0, define_source_1.definePushHookSource)({
140
146
  // does that. The value arrives with its own suffix (`claude-opus-5[1m]`) and
141
147
  // is not parsed here: a display string the tool chose is the tool's to spell.
142
148
  modelFields: ['model'],
149
+ // Issue #2363. The second and only other event that names a model, and it
150
+ // names it under a different key: `PostModelSwitch` carries `to_model` (the
151
+ // model the session is now on) and no `model` at all. Read there, and only
152
+ // there — `from_model` is the value being left behind and must never reach
153
+ // the latch. `extractModel` runs before `modelFields`, and answers null for
154
+ // every other event so the flat lookup above is unchanged for them.
155
+ extractModel: model_switch_1.extractClaudeSwitchedModel,
143
156
  // S2.
144
157
  extractDetail: hook_event_vocabulary_1.extractSnakeCaseEventDetail,
145
158
  // S7. Both parsers are strict and answer null for anything they cannot vouch
@@ -11,6 +11,7 @@ const db_instance_1 = require("../../lib/db/db-instance");
11
11
  const db_1 = require("../../lib/db");
12
12
  const ws_server_1 = require("../../lib/ws-server");
13
13
  const prompt_detector_1 = require("../../lib/detection/prompt-detector");
14
+ const dialog_1 = require("../../lib/detection/tools/antigravity/dialog");
14
15
  const conversation_logger_1 = require("../../lib/conversation-logger");
15
16
  const types_1 = require("../../lib/cli-tools/types");
16
17
  const claude_output_1 = require("../../lib/claude-output");
@@ -190,8 +191,23 @@ function buildPromptExtractionResult(lines, lastCapturedLine, totalLines, buffer
190
191
  * @returns PromptDetectionResult with isPrompt, promptData, and cleanContent
191
192
  */
192
193
  function detectPromptWithOptions(output, cliToolId) {
194
+ const clean = (0, cli_patterns_1.stripBoxDrawing)((0, cli_patterns_1.stripAnsi)(output));
195
+ // Issue #2364: agy's `↑/↓ Navigate` dialogs are read by agy's own reader
196
+ // before the generic pass, on the same spelling `tools/antigravity/detect.ts`
197
+ // reads them on. The generic multiple-choice parser takes one row per option
198
+ // and agy wraps a long command across several rows of one label, so without
199
+ // this the poller stored nothing for the frame the status API published as a
200
+ // prompt — and, on the file-creation menu, stored a question with the diff
201
+ // preview joined into it. One reader for both producers is what makes the
202
+ // stored `prompt` row, the push notification's excerpt and `/current-output`
203
+ // agree about one screen.
204
+ if (cliToolId === 'antigravity') {
205
+ const dialog = (0, dialog_1.detectAntigravityNumberedDialogPrompt)(clean);
206
+ if (dialog !== null)
207
+ return dialog;
208
+ }
193
209
  const promptOptions = (0, cli_patterns_1.buildDetectPromptOptions)(cliToolId);
194
- return (0, prompt_detector_1.detectPrompt)((0, cli_patterns_1.stripBoxDrawing)((0, cli_patterns_1.stripAnsi)(output)), promptOptions);
210
+ return (0, prompt_detector_1.detectPrompt)(clean, promptOptions);
195
211
  }
196
212
  // ============================================================================
197
213
  // extractResponse (internal)
@@ -61,7 +61,14 @@ const coordinator = globalThis.__responsePollerCoordinator ??
61
61
  pendingRestart: new Map(),
62
62
  ownerStorage: new async_hooks_1.AsyncLocalStorage(),
63
63
  generationCounter: 0,
64
+ pausedOnPrompt: new Set(),
64
65
  });
66
+ // The coordinator object outlives a module reload (that is the point of putting
67
+ // it on `globalThis`), so a field added after the object was first built has to
68
+ // be filled in on an object an older evaluation created — `next dev` keeps
69
+ // `globalThis` across HMR, and a poller started before the reload would
70
+ // otherwise crash the first tick after it.
71
+ coordinator.pausedOnPrompt ??= new Set();
65
72
  /**
66
73
  * Active pollers map: "worktreeId:instanceId" -> NodeJS.Timeout
67
74
  *
@@ -107,10 +114,23 @@ function takeOwnership(pollerKey) {
107
114
  generation: ++coordinator.generationCounter,
108
115
  superseded: false,
109
116
  stopped: false,
117
+ selfStopped: false,
110
118
  };
111
119
  coordinator.owners.set(pollerKey, owner);
112
120
  return owner;
113
121
  }
122
+ /**
123
+ * The tools whose chain ends the moment a reply is saved (opencode, copilot).
124
+ *
125
+ * `checkForResponse()` stops the poller on exactly two "something was recorded"
126
+ * paths, and they are split by this predicate: a full-screen TUI's chain stops
127
+ * AFTER ITS REPLY, every other tool's chain stops ON A PROMPT and expects
128
+ * `/respond` to start it again. The same two tools are the ones that need the
129
+ * Layer-2 accumulator, so this is the single place the pair is spelled out.
130
+ */
131
+ function isFullScreenTui(cliToolId) {
132
+ return cliToolId === 'opencode' || cliToolId === 'copilot';
133
+ }
114
134
  // ============================================================================
115
135
  // Polling lifecycle (public API)
116
136
  // ============================================================================
@@ -122,6 +142,17 @@ function takeOwnership(pollerKey) {
122
142
  * `checkForResponse()` does **not** run the two side by side — the restart is
123
143
  * handed to that tick's epilogue and applied when it settles.
124
144
  *
145
+ * Issue #2230: two different callers reach this function, and they mean two
146
+ * different things. `sendUserMessage` starts a NEW TURN — the previous chain is
147
+ * still ticking over the finished screen, and the restart drops its response
148
+ * hash so an identical reply in the new turn is still recorded (#1268).
149
+ * `/respond`, `/prompt-response` and the Auto-Yes poller RESUME the turn the
150
+ * chain paused on when it recorded a prompt — the chain has already stopped
151
+ * itself, the screen may be exactly the finished turn the prompt was drawn
152
+ * over, and the hash is kept so that screen is not saved a second time. The
153
+ * two are told apart by the state the previous chain left behind
154
+ * ({@link PollerCoordinator.pausedOnPrompt}), not by who is calling.
155
+ *
125
156
  * @param worktreeId - Worktree ID
126
157
  * @param cliToolId - CLI tool ID (claude, codex, gemini)
127
158
  * @param instanceId - Optional agent instance ID (defaults to primary)
@@ -151,8 +182,22 @@ function startPolling(worktreeId, cliToolId, instanceId) {
151
182
  });
152
183
  coordinator.running.delete(pollerKey);
153
184
  }
154
- // Stop existing poller if any
155
- stopPolling(worktreeId, cliToolId, instanceId);
185
+ restartChain(pollerKey, target);
186
+ }
187
+ /**
188
+ * Retire whatever chain holds `pollerKey` and start a fresh one for `target`.
189
+ *
190
+ * Shared by the direct path of {@link startPolling} and the queued restart a
191
+ * tick applies in its epilogue, so both make the same decision about the
192
+ * response hash (Issue #2230): kept when the previous chain paused itself on a
193
+ * prompt and this is the resume, dropped otherwise.
194
+ */
195
+ function restartChain(pollerKey, target) {
196
+ const resume = coordinator.pausedOnPrompt.has(pollerKey);
197
+ stopPollingByKey(pollerKey, { resume });
198
+ if (resume) {
199
+ logger.info('poller:resumed-after-prompt', { pollerKey });
200
+ }
156
201
  beginPolling(target);
157
202
  }
158
203
  /** Seed a fresh polling cycle (start time, TUI accumulator) and schedule its first tick. */
@@ -161,7 +206,7 @@ function beginPolling(target) {
161
206
  // Record start time
162
207
  coordinator.pollingStartTimes.set(pollerKey, Date.now());
163
208
  // Initialize TUI accumulator for full-screen TUI tools (Layer 2 safety net)
164
- if (target.cliToolId === 'opencode' || target.cliToolId === 'copilot') {
209
+ if (isFullScreenTui(target.cliToolId)) {
165
210
  (0, tui_accumulator_1.initTuiAccumulator)(pollerKey);
166
211
  }
167
212
  // Start polling with setTimeout chain to prevent race conditions
@@ -212,12 +257,18 @@ async function runPollTick(target, owner) {
212
257
  return;
213
258
  }
214
259
  // Check for response
260
+ let recorded = false;
215
261
  try {
216
- await coordinator.ownerStorage.run(owner, () => (0, response_checker_1.checkForResponse)(target.worktreeId, target.cliToolId, target.instanceId));
262
+ recorded = await coordinator.ownerStorage.run(owner, () => (0, response_checker_1.checkForResponse)(target.worktreeId, target.cliToolId, target.instanceId));
217
263
  }
218
264
  catch (error) {
219
265
  logger.error('error:', { error: error instanceof Error ? error.message : String(error) });
220
266
  }
267
+ // Issue #2230: the chain stopped itself inside that call. Now that its
268
+ // verdict is known, decide whether the stop ended the turn or paused it.
269
+ if (owner.selfStopped) {
270
+ settleSelfStop(owner, target, recorded);
271
+ }
221
272
  // Issue #1120: push the current terminal snapshot to WS subscribers so the
222
273
  // output streams during generation. No-op (and no tmux capture) when nobody
223
274
  // is subscribed to the worktree room. Best-effort; polling is the fallback.
@@ -244,16 +295,63 @@ async function runPollTick(target, owner) {
244
295
  const pending = coordinator.pendingRestart.get(pollerKey);
245
296
  if (pending) {
246
297
  coordinator.pendingRestart.delete(pollerKey);
247
- stopPollingByKey(pollerKey);
248
- beginPolling(pending);
298
+ restartChain(pollerKey, pending);
249
299
  }
250
300
  }
251
301
  }
302
+ /**
303
+ * Finish a stop that `checkForResponse()` raised from inside its own tick
304
+ * (Issue #2230).
305
+ *
306
+ * `checkForResponse()` ends its chain on four paths, and `stopPollingByKey()`
307
+ * cannot tell them apart while the call is still on the stack — so it leaves
308
+ * the response hash alone and this runs once the verdict is in:
309
+ *
310
+ * - **recorded, not a full-screen TUI** — the prompt path. The turn is NOT
311
+ * over: the agent is waiting for an answer, and the screen under the dialog
312
+ * is very often the previous reply, already saved. The hash stays and the
313
+ * key is marked paused, so the `/respond` (or Auto-Yes) restart that follows
314
+ * resumes the cycle instead of opening one over the same screen. Measured
315
+ * live on 2026-09-01: claude drew `Teach auto mode about your environment?`
316
+ * AFTER a finished turn, and answering it re-saved the reply.
317
+ * - **recorded, full-screen TUI** — the reply itself was just saved and the
318
+ * chain is done. The cycle ends here exactly as before.
319
+ * - **nothing recorded** — worktree gone or session not running. There is no
320
+ * turn left to protect, and a hash kept here would suppress the first reply
321
+ * of the session that replaces it.
322
+ *
323
+ * The prompt hash is NOT kept in any of these. If the answer did not take and
324
+ * the same dialog is still up on the first resumed tick, the operator has to
325
+ * get a new card rather than silence.
326
+ */
327
+ function settleSelfStop(owner, target, recorded) {
328
+ if (recorded && !isFullScreenTui(target.cliToolId)) {
329
+ coordinator.pausedOnPrompt.add(owner.pollerKey);
330
+ logger.info('poller:paused-on-prompt', {
331
+ pollerKey: owner.pollerKey,
332
+ generation: owner.generation,
333
+ });
334
+ return;
335
+ }
336
+ (0, response_dedup_1.clearResponseHashCache)(owner.pollerKey);
337
+ }
252
338
  /**
253
339
  * Stop the poller identified by an already-computed poller key.
254
340
  * Shared by stopPolling() and stopAllPolling() so cleanup logic stays in one place.
341
+ *
342
+ * Issue #2230: this is where the per-turn dedup caches end, and the response
343
+ * hash is the one whose ending has to be timed. It is dropped here for an
344
+ * explicit stop (a route, `session-cleanup`, `kill-session`, the 30-minute
345
+ * budget) and for the restart that opens a new turn. It is **kept** in two
346
+ * cases: `resume` — the restart is picking up a chain that paused itself on a
347
+ * prompt — and a stop raised by the chain's own tick, whose meaning is settled
348
+ * by {@link settleSelfStop} once `checkForResponse()` has returned. The prompt
349
+ * hash and the TUI accumulator are dropped unconditionally, as before.
350
+ *
351
+ * @param pollerKey - Poller key ("worktreeId:instanceId")
352
+ * @param options.resume - This stop precedes a restart of a paused chain.
255
353
  */
256
- function stopPollingByKey(pollerKey) {
354
+ function stopPollingByKey(pollerKey, options = {}) {
257
355
  // Issue #2223: a tick that has been superseded still runs to completion, and
258
356
  // `checkForResponse()` ends the turn with `stopPolling()` on four paths
259
357
  // (worktree gone, session not running, prompt detected, TUI reply saved).
@@ -268,13 +366,20 @@ function stopPollingByKey(pollerKey) {
268
366
  return;
269
367
  }
270
368
  const owner = coordinator.owners.get(pollerKey);
369
+ // The live owner stopping itself from inside its own tick. Identity, not key
370
+ // equality: a stale generation with the same key was turned away above.
371
+ const selfStop = owner !== undefined && caller === owner;
271
372
  if (owner) {
272
373
  owner.stopped = true;
374
+ owner.selfStopped = selfStop;
273
375
  coordinator.owners.delete(pollerKey);
274
376
  }
275
377
  // A restart queued behind an in-flight tick is cancelled by an explicit stop:
276
378
  // "start then stop" must leave the session stopped.
277
379
  coordinator.pendingRestart.delete(pollerKey);
380
+ // Whatever this stop is, the pause it may be ending is over: a resume consumes
381
+ // it, an explicit stop cancels it.
382
+ coordinator.pausedOnPrompt.delete(pollerKey);
278
383
  const timerId = coordinator.activePollers.get(pollerKey);
279
384
  if (timerId) {
280
385
  clearTimeout(timerId);
@@ -287,7 +392,12 @@ function stopPollingByKey(pollerKey) {
287
392
  (0, prompt_dedup_1.clearPromptHashCache)(pollerKey);
288
393
  // Issue #1268: Clear response hash cache too, so the next turn can save a
289
394
  // response even when its content is identical to the previous turn's.
290
- (0, response_dedup_1.clearResponseHashCache)(pollerKey);
395
+ //
396
+ // Issue #2230: unless this turn is not actually over. A self-stop is settled
397
+ // by the tick once its verdict is known; a resume is continuing a paused turn.
398
+ if (!selfStop && !options.resume) {
399
+ (0, response_dedup_1.clearResponseHashCache)(pollerKey);
400
+ }
291
401
  }
292
402
  /**
293
403
  * Stop polling for a worktree and CLI tool / instance combination
@@ -312,11 +422,15 @@ function stopAllPolling() {
312
422
  const keys = new Set([
313
423
  ...Array.from(coordinator.activePollers.keys()),
314
424
  ...Array.from(coordinator.owners.keys()),
425
+ // Issue #2230: a paused chain has no timer and no owner, but it is still
426
+ // holding a response hash for the turn it paused on.
427
+ ...Array.from(coordinator.pausedOnPrompt),
315
428
  ]);
316
429
  for (const pollerKey of keys) {
317
430
  stopPollingByKey(pollerKey);
318
431
  }
319
432
  coordinator.pendingRestart.clear();
433
+ coordinator.pausedOnPrompt.clear();
320
434
  }
321
435
  /**
322
436
  * Get list of active pollers
@@ -448,10 +562,30 @@ function migrateResponsePollerWorktreeIds(renames, resolveCliToolId) {
448
562
  for (const move of moves) {
449
563
  const startedAt = carried.get(move.newKey)?.startedAt;
450
564
  exports.pollingStartTimes.set(move.newKey, startedAt ?? Date.now());
451
- if (move.cliToolId === 'opencode' || move.cliToolId === 'copilot') {
565
+ if (isFullScreenTui(move.cliToolId)) {
452
566
  (0, tui_accumulator_1.initTuiAccumulator)(move.newKey);
453
567
  }
454
568
  scheduleNextResponsePoll(move.newWorktreeId, move.cliToolId, move.instanceId);
455
569
  }
570
+ // Issue #2230: a chain paused on a prompt has no timer, so the loop above
571
+ // never sees it — but it is holding the response hash for the turn it paused
572
+ // on, and `/respond` will resume it under the NEW ID. Move the hash and the
573
+ // pause mark with it; the chain itself stays paused until that resume.
574
+ const pausedMoves = [];
575
+ for (const pollerKey of Array.from(coordinator.pausedOnPrompt)) {
576
+ const parts = splitPollerKey(pollerKey);
577
+ if (!parts)
578
+ continue;
579
+ const newWorktreeId = targets.get(parts.worktreeId);
580
+ if (!newWorktreeId)
581
+ continue;
582
+ pausedMoves.push({ oldKey: pollerKey, newKey: `${newWorktreeId}:${parts.instanceId}` });
583
+ }
584
+ for (const move of pausedMoves)
585
+ coordinator.pausedOnPrompt.delete(move.oldKey);
586
+ for (const move of pausedMoves) {
587
+ (0, response_dedup_1.renameResponseHashCacheKey)(move.oldKey, move.newKey);
588
+ coordinator.pausedOnPrompt.add(move.newKey);
589
+ }
456
590
  return moves;
457
591
  }
@@ -2,7 +2,7 @@
2
2
  /** Web Push module barrel (Issue #1125). */
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.notifyPromptResolved = exports.decidePromptResolution = exports.MAX_ESCALATION_THRESHOLD_MINUTES = exports.MIN_ESCALATION_THRESHOLD_MINUTES = exports.ESCALATION_SETTINGS_KEY = exports.ESCALATION_THRESHOLD_CHOICES = exports.DEFAULT_ESCALATION_SETTINGS = exports.normalizeEscalationSettings = exports.setPushEscalationSettings = exports.getPushEscalationSettings = exports.ESCALATION_TICK_MS = exports.pendingEscalationCount = exports.runEscalationTick = exports.handleWaitingTransition = exports.isWaitingPushNotifierActive = exports.stopWaitingPushNotifier = exports.startWaitingPushNotifier = exports.UPSTREAM_FAULT_COOLDOWN_MS = exports.clearUpstreamFaultEpisodes = exports.observeUpstreamFaultEdge = exports.notifySessionStartFailurePush = exports.notifyUpstreamFaultPush = exports.notifyVerificationFailurePush = exports.isPromptPushSuppressed = exports.decidePromptPush = exports.resetWaitingPushDedup = exports.shouldSendWaitingPush = exports.DEFAULT_DEDUP_WINDOW_MS = exports.resetNotificationDedup = exports.shouldSendNotification = exports.resolvePushLocale = exports.buildExcerpt = exports.buildPushPayload = exports.notifyPushSubscribers = exports.PUSH_DELIVERY_HEALTH_MAX_AGE_MS = exports.PUSH_DELIVERY_HEALTH_KEY_PREFIX = exports.clearAllPushDeliveryHealth = exports.clearPushDeliveryHealth = exports.recordPushDeliveryFailure = exports.getPushDeliveryHealth = exports.VAPID_ENV_KEYS = exports.VAPID_DEFAULT_SUBJECT = exports.extractVapidSubjectHost = exports.classifyVapidSubject = exports.runVapidSelfCheck = exports.formatVapidReportLines = exports.inspectVapidConfig = exports.getVapidPublicKey = exports.isPushConfigured = exports.getVapidConfig = void 0;
5
- exports.PROMPT_CARD_MAX_AGE_MS = exports.PROMPT_CARD_KEY_PREFIX = exports.promptCardCount = exports.forgetPromptCardMemory = exports.clearAllPromptCards = exports.clearPromptCard = exports.hasPromptCard = exports.markPromptCardShown = exports.MIN_DEVICES_FOR_CROSS_DEVICE_CLEAR = void 0;
5
+ exports.MODEL_CHANGE_TAG_SUFFIX = exports.resolveReadersLocale = exports.buildModelChangedBodies = exports.buildModelChangedSentence = exports.notifyModelChangePush = exports.PROMPT_CARD_MAX_AGE_MS = exports.PROMPT_CARD_KEY_PREFIX = exports.promptCardCount = exports.forgetPromptCardMemory = exports.clearAllPromptCards = exports.clearPromptCard = exports.hasPromptCard = exports.markPromptCardShown = exports.MIN_DEVICES_FOR_CROSS_DEVICE_CLEAR = void 0;
6
6
  var vapid_1 = require("./vapid");
7
7
  Object.defineProperty(exports, "getVapidConfig", { enumerable: true, get: function () { return vapid_1.getVapidConfig; } });
8
8
  Object.defineProperty(exports, "isPushConfigured", { enumerable: true, get: function () { return vapid_1.isPushConfigured; } });
@@ -93,3 +93,15 @@ Object.defineProperty(exports, "forgetPromptCardMemory", { enumerable: true, get
93
93
  Object.defineProperty(exports, "promptCardCount", { enumerable: true, get: function () { return prompt_card_state_1.promptCardCount; } });
94
94
  Object.defineProperty(exports, "PROMPT_CARD_KEY_PREFIX", { enumerable: true, get: function () { return prompt_card_state_1.PROMPT_CARD_KEY_PREFIX; } });
95
95
  Object.defineProperty(exports, "PROMPT_CARD_MAX_AGE_MS", { enumerable: true, get: function () { return prompt_card_state_1.PROMPT_CARD_MAX_AGE_MS; } });
96
+ // The model edge's push (Issue #2357).
97
+ // NOTE: `realtime/model-change-broadcast` imports these from
98
+ // './model-change-push-notifier' directly, for the reason every block above
99
+ // gives — a suite that stubs the whole '@/lib/push' barrel would otherwise
100
+ // leave the notifier undefined on the path it guards.
101
+ var model_change_push_notifier_1 = require("./model-change-push-notifier");
102
+ Object.defineProperty(exports, "notifyModelChangePush", { enumerable: true, get: function () { return model_change_push_notifier_1.notifyModelChangePush; } });
103
+ Object.defineProperty(exports, "buildModelChangedSentence", { enumerable: true, get: function () { return model_change_push_notifier_1.buildModelChangedSentence; } });
104
+ Object.defineProperty(exports, "buildModelChangedBodies", { enumerable: true, get: function () { return model_change_push_notifier_1.buildModelChangedBodies; } });
105
+ Object.defineProperty(exports, "resolveReadersLocale", { enumerable: true, get: function () { return model_change_push_notifier_1.resolveReadersLocale; } });
106
+ var push_sender_2 = require("./push-sender");
107
+ Object.defineProperty(exports, "MODEL_CHANGE_TAG_SUFFIX", { enumerable: true, get: function () { return push_sender_2.MODEL_CHANGE_TAG_SUFFIX; } });