commandmate 0.47.2 → 0.49.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 (434) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +180 -180
  3. package/.next/app-path-routes-manifest.json +30 -30
  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.js +3 -3
  12. package/.next/server/app/api/app/update/route_client-reference-manifest.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_client-reference-manifest.js +1 -1
  20. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  22. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  24. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/hooks/agent-event/route.js +2 -2
  27. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  28. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  29. package/.next/server/app/api/hooks/claude-done/route.js +2 -2
  30. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  31. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  32. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  33. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  34. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/push/escalation/route.js +1 -1
  38. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/push/vapid/route.js +1 -1
  41. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
  43. package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
  44. package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/relays/route.js +1 -1
  46. package/.next/server/app/api/relays/route.js.nft.json +1 -1
  47. package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
  48. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  49. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  51. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  52. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  53. package/.next/server/app/api/repositories/clone/route.js +1 -1
  54. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  55. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/repositories/restore/route.js +1 -1
  58. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  59. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  60. package/.next/server/app/api/repositories/route.js +1 -1
  61. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  62. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  63. package/.next/server/app/api/repositories/scan/route.js +1 -1
  64. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  65. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  66. package/.next/server/app/api/repositories/sync/route.js +1 -1
  67. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  68. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  70. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  71. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  72. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  73. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  74. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  75. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  76. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  78. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  82. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  83. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  85. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  88. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  89. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  91. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  92. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  94. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  95. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  97. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  100. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  101. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/worktrees/[id]/direct-input/route.js +1 -1
  103. package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
  104. package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  107. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  119. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  135. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  138. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  141. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/opencode/session/route.js.nft.json +1 -1
  151. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/opencode/share/route.js.nft.json +1 -1
  154. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  157. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route.js.nft.json +1 -1
  160. package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route_client-reference-manifest.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  164. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  167. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  168. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  174. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +3 -3
  176. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  177. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  179. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  180. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  186. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  188. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -103
  191. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  192. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  196. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  199. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  203. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.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/login/page_client-reference-manifest.js +1 -1
  215. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  217. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  218. package/.next/server/app/page_client-reference-manifest.js +1 -1
  219. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  220. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  221. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  222. package/.next/server/app/sessions/page.js +1 -1
  223. package/.next/server/app/sessions/page.js.nft.json +1 -1
  224. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  225. package/.next/server/app/skills/[skillId]/page.js +1 -1
  226. package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
  227. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  228. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  229. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  230. package/.next/server/app/worktrees/[id]/files/[...path]/page.js +2 -2
  231. package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +1 -1
  232. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  233. package/.next/server/app/worktrees/[id]/page.js +12 -12
  234. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  235. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  236. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  237. package/.next/server/app-paths-manifest.json +30 -30
  238. package/.next/server/chunks/1191.js +11 -4
  239. package/.next/server/chunks/1501.js +1 -1
  240. package/.next/server/chunks/1601.js +2 -2
  241. package/.next/server/chunks/1656.js +2 -2
  242. package/.next/server/chunks/1945.js +3 -3
  243. package/.next/server/chunks/1990.js +103 -0
  244. package/.next/server/chunks/2069.js +1 -0
  245. package/.next/server/chunks/2119.js +1 -1
  246. package/.next/server/chunks/2404.js +1 -1
  247. package/.next/server/chunks/2422.js +1 -1
  248. package/.next/server/chunks/2445.js +1 -1
  249. package/.next/server/chunks/2534.js +1 -1
  250. package/.next/server/chunks/255.js +1 -1
  251. package/.next/server/chunks/3241.js +1 -1
  252. package/.next/server/chunks/3505.js +2 -2
  253. package/.next/server/chunks/4243.js +1 -1
  254. package/.next/server/chunks/4248.js +1 -1
  255. package/.next/server/chunks/4280.js +1 -0
  256. package/.next/server/chunks/5209.js +1 -1
  257. package/.next/server/chunks/6119.js +1 -1
  258. package/.next/server/chunks/6130.js +1 -1
  259. package/.next/server/chunks/6401.js +1 -1
  260. package/.next/server/chunks/6486.js +9 -8
  261. package/.next/server/chunks/6781.js +1 -1
  262. package/.next/server/chunks/720.js +103 -0
  263. package/.next/server/chunks/7604.js +2 -0
  264. package/.next/server/chunks/7905.js +1 -1
  265. package/.next/server/chunks/8581.js +8 -8
  266. package/.next/server/chunks/8728.js +3 -3
  267. package/.next/server/chunks/8791.js +1 -1
  268. package/.next/server/chunks/8807.js +19 -18
  269. package/.next/server/chunks/8918.js +2 -104
  270. package/.next/server/chunks/936.js +1 -1
  271. package/.next/server/chunks/9390.js +1 -1
  272. package/.next/server/chunks/9540.js +1 -1
  273. package/.next/server/chunks/9627.js +5 -5
  274. package/.next/server/chunks/9731.js +2 -2
  275. package/.next/server/middleware-manifest.json +5 -5
  276. package/.next/server/pages/500.html +1 -1
  277. package/.next/server/server-reference-manifest.json +1 -1
  278. package/.next/static/chunks/1128-914c559913546bbc.js +1 -0
  279. package/.next/static/chunks/{2407-a6533805a86d05bd.js → 2407-ab92ae9837c39dce.js} +1 -1
  280. package/.next/static/chunks/{2863-6a07ec82fb52f4dd.js → 2863-7173dc305dffc4f6.js} +1 -1
  281. package/.next/static/chunks/6288-6fadbba6e84393b2.js +1 -0
  282. package/.next/static/chunks/7665-e9ef6e0a85b9fa49.js +1 -0
  283. package/.next/static/chunks/8407-35bbfc84793d7004.js +1 -0
  284. package/.next/static/chunks/9079-987939d231704218.js +1 -0
  285. package/.next/static/chunks/app/{layout-538d8d2746ad1588.js → layout-aa8e66164a4367af.js} +1 -1
  286. package/.next/static/chunks/app/sessions/page-cfd645305e25fd33.js +1 -0
  287. package/.next/static/chunks/app/skills/[skillId]/{page-52ba58712faf3378.js → page-cb6e74fd9a6a571d.js} +1 -1
  288. package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-704086656fb45699.js +1 -0
  289. package/.next/static/chunks/app/worktrees/[id]/page-a8d7886703ffc7b4.js +1 -0
  290. package/.next/static/css/{743f79ff19ab91e9.css → db8959555c3d9c96.css} +1 -1
  291. package/.next/trace +13 -13
  292. package/dist/cli/commands/auto-yes.d.ts +24 -0
  293. package/dist/cli/commands/auto-yes.d.ts.map +1 -1
  294. package/dist/cli/commands/auto-yes.js +76 -8
  295. package/dist/cli/commands/capture.d.ts.map +1 -1
  296. package/dist/cli/commands/capture.js +5 -0
  297. package/dist/cli/commands/instances.d.ts.map +1 -1
  298. package/dist/cli/commands/instances.js +10 -1
  299. package/dist/cli/commands/prompt.d.ts.map +1 -1
  300. package/dist/cli/commands/prompt.js +5 -3
  301. package/dist/cli/commands/send.d.ts.map +1 -1
  302. package/dist/cli/commands/send.js +19 -6
  303. package/dist/cli/commands/verify.d.ts.map +1 -1
  304. package/dist/cli/commands/verify.js +8 -1
  305. package/dist/cli/commands/wait.d.ts.map +1 -1
  306. package/dist/cli/commands/wait.js +101 -13
  307. package/dist/cli/config/duration-constants.d.ts +16 -13
  308. package/dist/cli/config/duration-constants.d.ts.map +1 -1
  309. package/dist/cli/config/duration-constants.js +21 -21
  310. package/dist/cli/docs/agent-operations.d.ts +2 -2
  311. package/dist/cli/docs/agent-operations.d.ts.map +1 -1
  312. package/dist/cli/docs/agent-operations.js +29 -1
  313. package/dist/cli/types/api-responses.d.ts +145 -3
  314. package/dist/cli/types/api-responses.d.ts.map +1 -1
  315. package/dist/cli/types/index.d.ts +4 -0
  316. package/dist/cli/types/index.d.ts.map +1 -1
  317. package/dist/cli/utils/resource-resolvers.d.ts +0 -18
  318. package/dist/cli/utils/resource-resolvers.d.ts.map +1 -1
  319. package/dist/cli/utils/resource-resolvers.js +1 -51
  320. package/dist/cli/utils/verify-runner.d.ts +24 -1
  321. package/dist/cli/utils/verify-runner.d.ts.map +1 -1
  322. package/dist/cli/utils/verify-runner.js +54 -1
  323. package/dist/config/auto-yes-duration.d.ts +56 -0
  324. package/dist/config/auto-yes-duration.d.ts.map +1 -0
  325. package/dist/config/auto-yes-duration.js +76 -0
  326. package/dist/lib/polling/auto-yes-suppression-reason.d.ts +54 -2
  327. package/dist/lib/polling/auto-yes-suppression-reason.d.ts.map +1 -1
  328. package/dist/lib/polling/auto-yes-suppression-reason.js +33 -2
  329. package/dist/lib/prompt-observation/types.d.ts +13 -0
  330. package/dist/lib/prompt-observation/types.d.ts.map +1 -1
  331. package/dist/server/locales/en/worktree.json +2 -1
  332. package/dist/server/locales/ja/worktree.json +2 -1
  333. package/dist/server/src/config/auto-yes-config.js +14 -19
  334. package/dist/server/src/config/auto-yes-duration.js +76 -0
  335. package/dist/server/src/lib/auto-yes-poller-answer-target.js +38 -0
  336. package/dist/server/src/lib/auto-yes-poller-keys.js +35 -0
  337. package/dist/server/src/lib/auto-yes-poller-session-presence.js +26 -0
  338. package/dist/server/src/lib/auto-yes-poller-tick.js +233 -0
  339. package/dist/server/src/lib/auto-yes-poller.js +337 -376
  340. package/dist/server/src/lib/auto-yes-state.js +59 -4
  341. package/dist/server/src/lib/cli-tools/submit-verified-sender.js +235 -19
  342. package/dist/server/src/lib/db/chat-db.js +5 -1
  343. package/dist/server/src/lib/db/verification-db.js +23 -2
  344. package/dist/server/src/lib/detection/composer-text.js +215 -11
  345. package/dist/server/src/lib/detection/option-recommendation.js +120 -0
  346. package/dist/server/src/lib/detection/prompt-detect-multiple-choice-approval-context.js +290 -0
  347. package/dist/server/src/lib/detection/prompt-detect-multiple-choice-chrome.js +193 -0
  348. package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +402 -539
  349. package/dist/server/src/lib/detection/prompt-detector.js +92 -21
  350. package/dist/server/src/lib/detection/prompt-screen-key.js +60 -0
  351. package/dist/server/src/lib/detection/tools/antigravity/dialog.js +158 -35
  352. package/dist/server/src/lib/detection/tools/claude/detect.js +111 -10
  353. package/dist/server/src/lib/detection/tools/command-code/dialog.js +67 -0
  354. package/dist/server/src/lib/detection/tools/dialog-block.js +16 -0
  355. package/dist/server/src/lib/detection/upstream-faults.js +19 -2
  356. package/dist/server/src/lib/detection/waiting-screen-reading.js +98 -0
  357. package/dist/server/src/lib/hooks/permission-decision-service.js +7 -0
  358. package/dist/server/src/lib/hooks/structured-decision-response.js +1 -1
  359. package/dist/server/src/lib/polling/auto-yes-confirm-page.js +2 -2
  360. package/dist/server/src/lib/polling/auto-yes-confirmation-ledger-types.js +3 -0
  361. package/dist/server/src/lib/polling/auto-yes-confirmation-ledger.js +34 -3
  362. package/dist/server/src/lib/polling/auto-yes-decision-state.js +195 -0
  363. package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +139 -10
  364. package/dist/server/src/lib/polling/auto-yes-enter-fallback.js +14 -0
  365. package/dist/server/src/lib/polling/auto-yes-manual-answer.js +124 -0
  366. package/dist/server/src/lib/polling/auto-yes-option-effect.js +157 -0
  367. package/dist/server/src/lib/polling/auto-yes-policy.js +11 -5
  368. package/dist/server/src/lib/polling/auto-yes-poller-capture.js +15 -2
  369. package/dist/server/src/lib/polling/auto-yes-poller-generation.js +42 -1
  370. package/dist/server/src/lib/polling/auto-yes-poller-receipt-log.js +42 -5
  371. package/dist/server/src/lib/polling/auto-yes-poller-state.js +147 -49
  372. package/dist/server/src/lib/polling/auto-yes-poller-steps.js +172 -2
  373. package/dist/server/src/lib/polling/auto-yes-prompt-suppression.js +2 -2
  374. package/dist/server/src/lib/polling/auto-yes-question-choice.js +57 -0
  375. package/dist/server/src/lib/polling/auto-yes-resolver.js +96 -21
  376. package/dist/server/src/lib/polling/auto-yes-suppression-reason.js +33 -2
  377. package/dist/server/src/lib/polling/auto-yes-suppression-state.js +25 -1
  378. package/dist/server/src/lib/polling/prompt-screen-reading.js +232 -0
  379. package/dist/server/src/lib/polling/response-checker-dialog-gate.js +39 -0
  380. package/dist/server/src/lib/polling/response-checker.js +145 -58
  381. package/dist/server/src/lib/prompt-answer-sender.js +104 -10
  382. package/dist/server/src/lib/push/notification-dedup.js +15 -2
  383. package/dist/server/src/lib/push/prompt-card-state.js +140 -19
  384. package/dist/server/src/lib/push/prompt-push-gate.js +158 -12
  385. package/dist/server/src/lib/push/push-sender.js +23 -3
  386. package/dist/server/src/lib/push/resolution-push-notifier.js +14 -0
  387. package/dist/server/src/lib/push/waiting-push-notifier.js +139 -17
  388. package/dist/server/src/lib/realtime/terminal-broadcast.js +16 -0
  389. package/dist/server/src/lib/session/agent-event-state.js +25 -5
  390. package/dist/server/src/lib/session/agent-event-turn.js +140 -46
  391. package/dist/server/src/lib/session/cli-session.js +21 -2
  392. package/dist/server/src/lib/session/composer-clear.js +56 -4
  393. package/dist/server/src/lib/session/current-output-builder.js +66 -12
  394. package/dist/server/src/lib/session/send-attempt-state.js +24 -7
  395. package/dist/server/src/lib/session/waiting-episode-binding-observation.js +289 -0
  396. package/dist/server/src/lib/session/waiting-episode-binding-resolve.js +38 -0
  397. package/dist/server/src/lib/session/waiting-episode-binding.js +276 -0
  398. package/dist/server/src/lib/session/waiting-episode-state-ops.js +152 -0
  399. package/dist/server/src/lib/session/waiting-episode-state-store.js +202 -0
  400. package/dist/server/src/lib/session/waiting-episode-state-types.js +6 -0
  401. package/dist/server/src/lib/session/waiting-episode-state.js +68 -91
  402. package/dist/server/src/lib/session/waiting-episode-verdict.js +174 -0
  403. package/dist/server/src/lib/tmux/tmux-capture-cache.js +76 -11
  404. package/dist/server/src/lib/tmux/tmux.js +79 -9
  405. package/dist/server/src/lib/verification/gate-runner.js +172 -16
  406. package/dist/server/src/lib/verification/machine-lock.js +5 -0
  407. package/dist/server/src/lib/ws-server.js +18 -3
  408. package/dist/server/src/types/auto-yes-answer-mode.js +38 -0
  409. package/dist/server/src/types/auto-yes-decision.js +61 -0
  410. package/dist/server/src/types/auto-yes.js +6 -0
  411. package/dist/server/src/types/prompt-reading.js +32 -0
  412. package/dist/types/auto-yes-answer-mode.d.ts +35 -0
  413. package/dist/types/auto-yes-answer-mode.d.ts.map +1 -0
  414. package/dist/types/auto-yes-answer-mode.js +38 -0
  415. package/docs/en/user-guide/webapp-guide.md +47 -13
  416. package/package.json +1 -1
  417. package/public/sw.js +76 -4
  418. package/release-notes/0.48.0.json +57 -0
  419. package/release-notes/0.49.0.json +45 -0
  420. package/.next/server/chunks/1559.js +0 -2
  421. package/.next/server/chunks/2460.js +0 -1
  422. package/.next/server/chunks/5595.js +0 -1
  423. package/.next/server/chunks/610.js +0 -1
  424. package/.next/server/chunks/6722.js +0 -1
  425. package/.next/static/chunks/5371-a549a0d2c2044d41.js +0 -1
  426. package/.next/static/chunks/602-1c1488959215e140.js +0 -1
  427. package/.next/static/chunks/6288-09feba367cc2c65e.js +0 -1
  428. package/.next/static/chunks/8407-155f84e5ba05f1d5.js +0 -1
  429. package/.next/static/chunks/9079-24f9fa549ed298f1.js +0 -1
  430. package/.next/static/chunks/app/sessions/page-e02f1adb1d1c1ccc.js +0 -1
  431. package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-9cf1ecc59e36a004.js +0 -1
  432. package/.next/static/chunks/app/worktrees/[id]/page-46aced20b2b1c010.js +0 -1
  433. /package/.next/static/{etorRtpxbQqqOzdUeXdw2 → 3_JtAZaKMJEDFIIfkHv4n}/_buildManifest.js +0 -0
  434. /package/.next/static/{etorRtpxbQqqOzdUeXdw2 → 3_JtAZaKMJEDFIIfkHv4n}/_ssgManifest.js +0 -0
@@ -10,6 +10,9 @@
10
10
  */
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.reopenedTurns = exports.agentTurns = exports.generationStartedAt = void 0;
13
+ exports.registerTurnOutcomeSink = registerTurnOutcomeSink;
14
+ exports.toGenerationRef = toGenerationRef;
15
+ exports.liveDecisionCount = liveDecisionCount;
13
16
  exports.currentGeneration = currentGeneration;
14
17
  exports.effectiveTurn = effectiveTurn;
15
18
  exports.livePendingDecisions = livePendingDecisions;
@@ -71,6 +74,38 @@ exports.reopenedTurns = (0, global_state_1.getOrInitGlobal)('__agentEventReopene
71
74
  * boundary rather than a cosmetic clash.
72
75
  */
73
76
  const turnSequence = (0, global_state_1.getOrInitGlobal)('__agentEventTurnSeq', () => ({ value: 0 }));
77
+ /**
78
+ * Install the sink for outcomes this module produces outside a
79
+ * `recordAgentEvent` call. Registered by `waiting-episode-binding`, through
80
+ * `globalThis`, so this module imports nothing that imports it back.
81
+ */
82
+ function registerTurnOutcomeSink(sink) {
83
+ globalThis.__agentEventTurnOutcomeSink = sink;
84
+ }
85
+ /** A generation as the waiting episode names it. */
86
+ function toGenerationRef(generation) {
87
+ return generation === null ? { kind: 'none' } : { kind: 'opened', at: generation };
88
+ }
89
+ /** Live decisions held by a record, counted without retiring the expired ones. */
90
+ function liveDecisionCount(turn, now) {
91
+ return turn.pendingDecisions.filter((decision) => (0, provisional_turn_1.isDecisionLive)(decision, now)).length;
92
+ }
93
+ /** Describe the instance's record before a transition rewrites it. */
94
+ function describePrevious(turn, eventSessionId, at) {
95
+ if (turn === null)
96
+ return { kind: 'none' };
97
+ if (turn.closedAt !== null)
98
+ return { kind: 'closed', turnId: turn.turnId, closedBy: turn.closedBy ?? 'stop' };
99
+ if (turn.openedAt === null) {
100
+ const decisions = liveDecisionCount(turn, at);
101
+ return decisions > 0
102
+ ? { kind: 'dialog-only', turnId: turn.turnId, decisions, sessionId: turn.sessionId }
103
+ : { kind: 'display-only', turnId: turn.turnId };
104
+ }
105
+ return (0, provisional_turn_1.closesTurn)(turn, eventSessionId)
106
+ ? { kind: 'open-same-session', turnId: turn.turnId }
107
+ : { kind: 'open-other-session', turnId: turn.turnId };
108
+ }
74
109
  // =============================================================================
75
110
  // Turn model (Issue #1930)
76
111
  // =============================================================================
@@ -283,10 +318,18 @@ function observeScraperCompletionEvidence(worktreeId, cliToolId, instanceId, com
283
318
  * were raised by a process that no longer exists, and answering one would
284
319
  * deliver a verdict into a slot nobody is holding.
285
320
  */
286
- function fenceTurnForNewGeneration(key, at) {
321
+ function fenceTurnForNewGeneration(key, at, source = 'session-start') {
287
322
  const turn = exports.agentTurns.get(key);
323
+ // Issue #3798: reported whether or not a turn existed — the waiting episode
324
+ // is fenced by its own generation, not by the turn's.
325
+ const outcome = {
326
+ kind: 'generation-fenced',
327
+ source,
328
+ generation: toGenerationRef(currentGeneration(key)),
329
+ fencedTurnId: turn?.turnId ?? null,
330
+ };
288
331
  if (!turn)
289
- return;
332
+ return outcome;
290
333
  evictDecisions(key, turn);
291
334
  // A turn that had ALREADY ended is left where it is, which means the fence in
292
335
  // `fencedTurn` hides it from here on. That asymmetry is deliberate: the
@@ -295,7 +338,7 @@ function fenceTurnForNewGeneration(key, at) {
295
338
  // nobody has typed into yet. Before #1930 the same protection came from
296
339
  // comparing the event's timestamp against the generation.
297
340
  if (turn.closedAt !== null)
298
- return;
341
+ return outcome;
299
342
  // An OPEN turn is closed and carried across, so `capture --json` can say
300
343
  // `closedBy: 'generation'` rather than going quiet. `getStructuredSessionState`
301
344
  // reads that reason as "nothing is known", so it publishes no verdict either
@@ -304,6 +347,7 @@ function fenceTurnForNewGeneration(key, at) {
304
347
  turn.closedAt = at;
305
348
  turn.closedBy = 'generation';
306
349
  turn.generationAt = at;
350
+ return outcome;
307
351
  }
308
352
  /**
309
353
  * The turn transition: what one delivery does to {@link TurnRecord}
@@ -406,23 +450,32 @@ function applyTurnTransition(key, record) {
406
450
  // An event stamped before the current generation was produced by a process
407
451
  // that has been replaced. Refusing it here is what makes re-recording a stale
408
452
  // `user_prompt_submit` at its original timestamp a no-op.
409
- if (generation !== null && record.at < generation)
410
- return;
453
+ if (generation !== null && record.at < generation) {
454
+ if (record.event === 'stop')
455
+ return { kind: 'stop-rejected', reason: 'before-generation' };
456
+ if (record.event === 'session_end')
457
+ return { kind: 'session-end-rejected', reason: 'before-generation' };
458
+ return { kind: 'none' };
459
+ }
411
460
  switch (record.event) {
412
- case 'user_prompt_submit':
461
+ case 'user_prompt_submit': {
413
462
  // Issue #3330: a queued notice the agent attached to its running turn
414
463
  // continues that turn; any other prompt is a new one.
415
- openTurn(key, record, generation, { continueOpen: record.joinsOpenTurn === true });
464
+ const outcome = openTurn(key, record, 'user_prompt_submit', generation, {
465
+ continueOpen: record.joinsOpenTurn === true,
466
+ });
416
467
  releaseAllDecisions(key);
417
- return;
418
- case 'post_tool_use':
419
- openTurn(key, record, generation, { continueOpen: true });
468
+ return outcome;
469
+ }
470
+ case 'post_tool_use': {
471
+ const outcome = openTurn(key, record, 'post_tool_use', generation, { continueOpen: true });
420
472
  // The tool call the dialog was gating has finished, so somebody answered
421
473
  // it (Issue #1726). This is the release #1725 could not have: it had no
422
474
  // event meaning "the human answered", only `Stop` meaning "the turn
423
475
  // ended", which can be minutes later.
424
476
  releaseAllDecisions(key);
425
- return;
477
+ return outcome;
478
+ }
426
479
  case 'pre_tool_use':
427
480
  // Deliberately leaves the dialog alone (Issue #1726). It is the
428
481
  // `AskUserQuestion` invocation, and a picker being *about to be drawn* is
@@ -432,28 +485,26 @@ function applyTurnTransition(key, record) {
432
485
  // start of a turn when the agent's own `Stop` is the last thing that
433
486
  // ended one. See the `after its stop` row above.
434
487
  if (record.promptOpensTurns === true && endedByOwnStop(key))
435
- return;
436
- openTurn(key, record, generation, { continueOpen: true });
437
- return;
488
+ return { kind: 'none' };
489
+ return openTurn(key, record, 'pre_tool_use', generation, { continueOpen: true });
438
490
  case 'stop':
439
- applyStopToTurn(key, record, generation);
440
- return;
441
- case 'session_end':
442
- applySessionEndToTurn(key, record);
491
+ return applyStopToTurn(key, record, generation);
492
+ case 'session_end': {
493
+ const outcome = applySessionEndToTurn(key, record);
443
494
  releaseAllDecisions(key);
444
- return;
495
+ return outcome;
496
+ }
445
497
  case 'session_start':
446
498
  // The generation was opened by `recordAgentEvent` before this ran, and
447
499
  // `fenceTurnForNewGeneration` closed the turn with it. Nothing further:
448
500
  // the frame carries no verdict, so it is not the displayed event either.
449
- return;
501
+ return { kind: 'none' };
450
502
  case 'notification':
451
- applyNotificationToTurn(key, record, generation);
452
- return;
503
+ return applyNotificationToTurn(key, record, generation);
453
504
  default:
454
505
  // exhaustive check: a new AgentEventType must decide its transition here
455
506
  record.event;
456
- return;
507
+ return { kind: 'none' };
457
508
  }
458
509
  }
459
510
  /**
@@ -494,8 +545,10 @@ function displayOf(record) {
494
545
  * this event's turn. False for `user_prompt_submit`, which IS a new turn —
495
546
  * unless the source marked it as joining the running one (Issue #3330).
496
547
  */
497
- function openTurn(key, record, generation, { continueOpen }) {
548
+ function openTurn(key, record, event, generation, { continueOpen }) {
498
549
  const turn = fencedTurn(key);
550
+ // Issue #3798: read before anything below rewrites the record.
551
+ const previous = describePrevious(turn, record.sessionId, record.at);
499
552
  const openHere = turn !== null &&
500
553
  turn.closedAt === null &&
501
554
  turn.openedAt !== null &&
@@ -506,7 +559,7 @@ function openTurn(key, record, generation, { continueOpen }) {
506
559
  // partway through. Learning it is what lets a later `stop` be matched.
507
560
  turn.sessionId ??= record.sessionId;
508
561
  turn.scraperCompletionPolls = 0;
509
- return;
562
+ return { kind: 'continued', turnId: turn.turnId };
510
563
  }
511
564
  // A dialog-only record (openedAt null) is not a turn; its decisions belong to
512
565
  // the turn that is opening now, because that is when they were raised.
@@ -532,6 +585,7 @@ function openTurn(key, record, generation, { continueOpen }) {
532
585
  exports.reopenedTurns.set(key, { turnId: opened.turnId, replaced: turn });
533
586
  (0, agent_event_dedup_1.trimOldestEntries)(exports.reopenedTurns, agent_event_dedup_1.MAX_RECENT_EVENT_KEYS);
534
587
  }
588
+ return { kind: 'opened', turnId: opened.turnId, event, generation: toGenerationRef(generation), previous };
535
589
  }
536
590
  /**
537
591
  * Give a dropped copy's queued-notice mark its effect (Issue #3330).
@@ -590,6 +644,11 @@ function joinOpenTurnFromDuplicate(worktreeId, cliToolId, instanceId, record) {
590
644
  scraperCompletionPolls: 0,
591
645
  });
592
646
  exports.reopenedTurns.delete(key);
647
+ // Issue #3798: a wait that opened under the discarded turn belongs to the
648
+ // turn put back. Told through the sink — this runs outside `recordAgentEvent`.
649
+ globalThis.__agentEventTurnOutcomeSink?.({ worktreeId, cliToolId, instanceId }, [
650
+ { kind: 'restored', restoredTurnId: replaced.turnId, discardedTurnId: current.turnId },
651
+ ]);
593
652
  return true;
594
653
  }
595
654
  /**
@@ -604,15 +663,27 @@ function applyStopToTurn(key, record, generation) {
604
663
  const turn = fencedTurn(key);
605
664
  if (turn !== null && turn.closedAt === null && turn.openedAt !== null) {
606
665
  if (!(0, provisional_turn_1.closesTurn)(turn, record.sessionId))
607
- return;
666
+ return { kind: 'stop-rejected', reason: 'other-session' };
608
667
  turn.closedAt = record.at;
609
668
  turn.closedBy = 'stop';
610
669
  turn.displayEvent = displayOf(record);
611
670
  releaseAllDecisions(key);
612
- return;
671
+ return { kind: 'stopped', turnId: turn.turnId, generation: toGenerationRef(generation) };
672
+ }
673
+ const previous = describePrevious(turn, record.sessionId, record.at);
674
+ // Issue #3798: a dialog raised by one agent session is not ended by another
675
+ // session's stop. Both ids are needed to tell — a record or a stop with no id
676
+ // is read as the same session, as `closesTurn` reads it. opencode publishes
677
+ // `session.idle` for every session its server holds (#1758 §5.6).
678
+ if (previous.kind === 'dialog-only' &&
679
+ previous.sessionId !== null &&
680
+ record.sessionId !== null &&
681
+ previous.sessionId !== record.sessionId) {
682
+ return { kind: 'stop-rejected', reason: 'other-session' };
613
683
  }
684
+ const recordTurnId = nextTurnId(record.at);
614
685
  exports.agentTurns.set(key, {
615
- turnId: nextTurnId(record.at),
686
+ turnId: recordTurnId,
616
687
  sessionId: record.sessionId,
617
688
  openedAt: null,
618
689
  closedAt: record.at,
@@ -623,6 +694,7 @@ function applyStopToTurn(key, record, generation) {
623
694
  scraperCompletionPolls: 0,
624
695
  });
625
696
  boundTurnMap();
697
+ return { kind: 'stop-without-turn', recordTurnId, generation: toGenerationRef(generation), previous };
626
698
  }
627
699
  /**
628
700
  * `session_end`: the agent session this instance was talking to is gone.
@@ -643,11 +715,12 @@ function applyStopToTurn(key, record, generation) {
643
715
  function applySessionEndToTurn(key, record) {
644
716
  const turn = fencedTurn(key);
645
717
  if (turn === null)
646
- return;
718
+ return { kind: 'session-end-rejected', reason: 'no-turn' };
647
719
  if (!(0, provisional_turn_1.closesTurn)(turn, record.sessionId))
648
- return;
720
+ return { kind: 'session-end-rejected', reason: 'other-session' };
649
721
  turn.closedAt = record.at;
650
722
  turn.closedBy = 'session_end';
723
+ return { kind: 'session-ended', turnId: turn.turnId };
651
724
  }
652
725
  /**
653
726
  * The notification rows of the transition table.
@@ -663,10 +736,9 @@ function applyNotificationToTurn(key, record, generation) {
663
736
  // reached the agent. There is no dialog and there never was one for a
664
737
  // human to answer — opening a record for it published `waiting` for the
665
738
  // whole of the tool call that followed (measured at eight seconds).
666
- releaseSettledDecision(key, record);
667
- return;
739
+ return releaseSettledDecision(key, record);
668
740
  }
669
- openDecision(key, generation, {
741
+ const opened = openDecision(key, generation, {
670
742
  source: 'notification',
671
743
  at: record.at,
672
744
  message: record.message ?? null,
@@ -679,16 +751,17 @@ function applyNotificationToTurn(key, record, generation) {
679
751
  patterns: record.decisionPatterns ?? null,
680
752
  decisionId: record.decisionId ?? null,
681
753
  bootstrapDisplay: displayOf(record),
754
+ sessionId: record.sessionId,
682
755
  });
683
- return;
756
+ return { kind: 'decision-opened', ...opened };
684
757
  }
685
758
  if (record.detail === agent_event_types_1.PERMISSION_REPLIED_DETAIL) {
686
759
  // Issue #1898. The agent's own statement that the dialog is gone — whoever
687
760
  // answered it. Not a word this build reads a status from, so it decides
688
761
  // nothing; all it does is retire the record.
689
762
  if (record.promptSettled === true)
690
- releaseSettledDecision(key, record);
691
- return;
763
+ return releaseSettledDecision(key, record);
764
+ return { kind: 'none' };
692
765
  }
693
766
  if (record.detail === 'idle_prompt') {
694
767
  // The agent reporting it is sitting at the composer waiting for input is the
@@ -697,10 +770,10 @@ function applyNotificationToTurn(key, record, generation) {
697
770
  const turn = fencedTurn(key);
698
771
  if (turn !== null && turn.closedAt === null) {
699
772
  turn.displayEvent = displayOf(record);
700
- return;
773
+ return { kind: 'none' };
701
774
  }
702
775
  if (turn !== null)
703
- return;
776
+ return { kind: 'none' };
704
777
  // Nothing to attach it to — the first thing this instance ever said, or the
705
778
  // first since a generation. It still carries a verdict (`ready`), and #1723
706
779
  // publishes it, so a display-only record is opened to hold it. `openedAt`
@@ -718,10 +791,11 @@ function applyNotificationToTurn(key, record, generation) {
718
791
  scraperCompletionPolls: 0,
719
792
  });
720
793
  boundTurnMap();
721
- return;
794
+ return { kind: 'none' };
722
795
  }
723
796
  // An unrecognised notification type is not evidence of anything, and guessing
724
797
  // would be worse than the scraper.
798
+ return { kind: 'none' };
725
799
  }
726
800
  /**
727
801
  * Open, or refresh, a dialog record on this instance's turn.
@@ -736,7 +810,7 @@ function openDecision(key, generation, input) {
736
810
  if (turn === null) {
737
811
  turn = {
738
812
  turnId: nextTurnId(input.at),
739
- sessionId: null,
813
+ sessionId: input.sessionId ?? null,
740
814
  openedAt: null,
741
815
  closedAt: null,
742
816
  closedBy: null,
@@ -754,7 +828,7 @@ function openDecision(key, generation, input) {
754
828
  // late. Re-open a dialog-only record rather than resurrecting the turn.
755
829
  turn = {
756
830
  turnId: nextTurnId(input.at),
757
- sessionId: null,
831
+ sessionId: input.sessionId ?? null,
758
832
  openedAt: null,
759
833
  closedAt: null,
760
834
  closedBy: null,
@@ -766,6 +840,15 @@ function openDecision(key, generation, input) {
766
840
  exports.agentTurns.set(key, turn);
767
841
  boundTurnMap();
768
842
  }
843
+ else if (turn.openedAt === null && turn.sessionId === null) {
844
+ // A dialog-only record bootstrapped by a forecast with no session learns
845
+ // the session from the report that confirms it.
846
+ turn.sessionId = input.sessionId ?? null;
847
+ }
848
+ const opened = {
849
+ recordTurnId: turn.turnId,
850
+ recordKind: turn.openedAt !== null ? 'turn' : 'dialog-only',
851
+ };
769
852
  // Issue #1930 / S1: an id that fails validation is DISCARDED, not truncated —
770
853
  // a truncated id compares equal to a different id sharing its prefix, and the
771
854
  // reply to one approval would then retire another's record.
@@ -807,14 +890,14 @@ function openDecision(key, generation, input) {
807
890
  existing.source = 'notification';
808
891
  existing.confirmedAt ??= input.at;
809
892
  }
810
- return;
893
+ return opened;
811
894
  }
812
895
  if (turn.pendingDecisions.length >= provisional_turn_1.MAX_PENDING_DECISIONS_PER_TURN) {
813
896
  // S14(d). Counted rather than dropped in silence: an agent raising more
814
897
  // approvals than this in one turn is a fact an operator has to be able to
815
898
  // see, and the oldest is the one a human has been looking at.
816
899
  (0, agent_event_dedup_1.dropsFor)(key).decisionOverflow += 1;
817
- return;
900
+ return opened;
818
901
  }
819
902
  turn.pendingDecisions.push({
820
903
  decisionId,
@@ -827,6 +910,7 @@ function openDecision(key, generation, input) {
827
910
  scraperCorroborated: false,
828
911
  recorded: false,
829
912
  });
913
+ return opened;
830
914
  }
831
915
  /** Retire every dialog this instance was holding. */
832
916
  function releaseAllDecisions(key) {
@@ -846,15 +930,25 @@ function releaseAllDecisions(key) {
846
930
  function releaseSettledDecision(key, record) {
847
931
  const turn = fencedTurn(key);
848
932
  if (turn === null || turn.pendingDecisions.length === 0)
849
- return;
933
+ return { kind: 'none' };
934
+ const before = turn.pendingDecisions.length;
850
935
  const settledId = record.decisionId === null || record.decisionId === undefined
851
936
  ? null
852
937
  : (0, provisional_turn_1.acceptExternalId)(record.decisionId);
853
938
  if (settledId === null) {
854
939
  turn.pendingDecisions = [];
855
- return;
856
940
  }
857
- turn.pendingDecisions = turn.pendingDecisions.filter((decision) => decision.decisionId !== null && decision.decisionId !== settledId);
941
+ else {
942
+ turn.pendingDecisions = turn.pendingDecisions.filter((decision) => decision.decisionId !== null && decision.decisionId !== settledId);
943
+ }
944
+ // Issue #3798: an explicit answer — the one release that ends a wait.
945
+ return {
946
+ kind: 'decision-answered',
947
+ recordTurnId: turn.turnId,
948
+ recordKind: turn.openedAt !== null ? 'turn' : 'dialog-only',
949
+ before,
950
+ remaining: turn.pendingDecisions.length,
951
+ };
858
952
  }
859
953
  /** Keep the turn map bounded the way every other map in this module is. */
860
954
  function boundTurnMap() {
@@ -35,6 +35,14 @@ const session_status_options_1 = require("../../lib/tmux/session-status-options"
35
35
  const tmux_1 = require("../../lib/tmux/tmux");
36
36
  const tmux_session_surface_1 = require("./tmux-session-surface");
37
37
  const logger = (0, logger_1.createLogger)('cli-session');
38
+ /** Tell the observer this capture runs for, if any, where its frame came from (Issue #3798). */
39
+ function reportFrameMeta(meta) {
40
+ globalThis.__captureFrameMetaSink?.getStore()?.(meta);
41
+ }
42
+ /** Tell the observer this capture runs for, if any, whether its window cut the pane's top (Issue #3881 N4). */
43
+ function reportHeadCut(headCut) {
44
+ globalThis.__captureHeadCutSink?.getStore()?.(headCut);
45
+ }
38
46
  function getDefaultTransport() {
39
47
  return (0, polling_tmux_transport_1.getPollingTmuxTransport)();
40
48
  }
@@ -95,7 +103,11 @@ async function captureSessionOutput(worktreeId, cliToolId, lines = 1000, instanc
95
103
  throw new Error(`${cliTool.name} session ${sessionName} does not exist`);
96
104
  }
97
105
  return await transport.captureSnapshot(sessionName, { startLine: -tmux_capture_cache_1.CACHE_MAX_CAPTURE_LINES });
98
- });
106
+ },
107
+ // Issue #3798: this call's own frame, to the observer it runs for
108
+ reportFrameMeta,
109
+ // Issue #3881 (third review N4): and whether the window cut its top
110
+ reportHeadCut);
99
111
  log.debug('captureSessionOutput:success', {
100
112
  actualLines: output.split('\n').length,
101
113
  lastFewLines: output.split('\n').slice(-3).join(' | '),
@@ -132,18 +144,25 @@ async function captureSessionOutputFresh(worktreeId, cliToolId, lines = 5000, in
132
144
  const transport = getDefaultTransport();
133
145
  // Issue #3734: snapshot the generation before the capture starts
134
146
  const generation = (0, tmux_capture_cache_1.getCaptureGeneration)(sessionName);
147
+ // Issue #3798: and the time, so the cache says when this frame was fetched,
148
+ // not when a slow capture came back
149
+ const fetchStartedAt = Date.now();
135
150
  try {
136
151
  const output = await transport.captureSnapshot(sessionName, { startLine: -lines });
137
152
  // Write back to cache if non-empty [SEC4-007]. Skip it when the session was
138
153
  // invalidated while waiting: the output may predate a send (Issue #3734).
139
154
  if (output.length > 0) {
140
155
  if ((0, tmux_capture_cache_1.isCaptureGenerationCurrent)(sessionName, generation)) {
141
- (0, tmux_capture_cache_1.setCachedCapture)(sessionName, output, lines);
156
+ (0, tmux_capture_cache_1.setCachedCapture)(sessionName, output, lines, fetchStartedAt);
142
157
  }
143
158
  }
144
159
  else {
145
160
  (0, tmux_capture_cache_1.invalidateCache)(sessionName);
146
161
  }
162
+ reportFrameMeta({ fetchStartedAt, source: 'fetched' });
163
+ const headCutSink = globalThis.__captureHeadCutSink?.getStore();
164
+ if (headCutSink)
165
+ headCutSink((0, tmux_capture_cache_1.sliceCutsHead)(output, lines));
147
166
  return (0, tmux_capture_cache_1.sliceOutput)(output, lines);
148
167
  }
149
168
  catch (error) {
@@ -30,13 +30,60 @@
30
30
  * frame back to the browser.
31
31
  */
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.COMPOSER_CLEAR_REDRAW_DELAY_MS = exports.MAX_COMPOSER_CLEAR_PASSES = void 0;
33
+ exports.COMPOSER_CLEAR_REDRAW_DELAY_MS = exports.MAX_COMPOSER_CLEAR_PASSES = exports.findCodexLiveComposerRow = exports.codexDialogBelow = void 0;
34
+ exports.isCodexPasteTokenOnly = isCodexPasteTokenOnly;
34
35
  exports.clearComposer = clearComposer;
35
36
  const tmux_1 = require("../../lib/tmux/tmux");
36
37
  const tmux_capture_cache_1 = require("../../lib/tmux/tmux-capture-cache");
37
38
  const composer_text_1 = require("../../lib/detection/composer-text");
39
+ Object.defineProperty(exports, "codexDialogBelow", { enumerable: true, get: function () { return composer_text_1.codexDialogBelow; } });
40
+ Object.defineProperty(exports, "findCodexLiveComposerRow", { enumerable: true, get: function () { return composer_text_1.findCodexLiveComposerRow; } });
38
41
  const logger_1 = require("../../lib/logger");
39
42
  const logger = (0, logger_1.createLogger)('composer-clear');
43
+ /**
44
+ * The composer as this loop reads it.
45
+ *
46
+ * {@link extractLiveComposerText} — the reading the unsent bar is drawn from
47
+ * (Issue #3927) — and for codex one more reading when it finds no
48
+ * composer (Issue #3906): a body of more paragraphs than the extractor's four
49
+ * blocks — the partly arrived paste the sender reads as `pasting` and withdraws
50
+ * through this function — is still a composer holding text. Only `content` is
51
+ * taken from that reading; anything else stays `no_composer`, so a frame this
52
+ * reading cannot vouch for is never reported as emptied.
53
+ *
54
+ * A composer the extractor does find is still not the live one when a dialog
55
+ * option is drawn below it ({@link codexDialogBelow}): that frame is
56
+ * `no_composer`, so no `C-e`+`C-u` goes into the dialog.
57
+ */
58
+ function readClearComposer(capture, cliToolId) {
59
+ const read = (0, composer_text_1.extractLiveComposerText)(capture, cliToolId);
60
+ if (cliToolId !== 'codex' || read.state !== 'no_composer')
61
+ return read;
62
+ const rows = capture.split('\n');
63
+ const row = (0, composer_text_1.findCodexLiveComposerRow)(rows);
64
+ if (row < 0)
65
+ return read;
66
+ const held = (0, composer_text_1.readCodexComposerFrom)(rows, row);
67
+ return held.state === 'content' ? held : read;
68
+ }
69
+ /**
70
+ * A codex composer holding exactly one collapsed paste placeholder and nothing
71
+ * else (Issue #3937) — the one frame a pass sends `C-e`+`BSpace` for instead of
72
+ * `C-e`+`C-u` ({@link clearComposerPasteToken}).
73
+ *
74
+ * Anything more than the bare placeholder keeps the `C-e`+`C-u` pass, because
75
+ * none of it has been measured on a live codex: a placeholder with typed text
76
+ * after it (`C-e`+`BSpace` would eat the last typed character, not the
77
+ * placeholder), two placeholders, and a body quoting the placeholder's wording
78
+ * among other text. A body that is nothing but that wording typed out is not
79
+ * told apart here; one `BSpace` takes its `]`, and from the next read on it is
80
+ * ordinary text again — `C-e`+`C-u` — so the read-back still decides.
81
+ */
82
+ const CODEX_PASTE_TOKEN_ONLY = /^\[Pasted Content \d+ chars?\]$/;
83
+ /** Whether a pass over this reading should send `C-e`+`BSpace` (Issue #3937). */
84
+ function isCodexPasteTokenOnly(read, cliToolId) {
85
+ return cliToolId === 'codex' && read.state === 'content' && CODEX_PASTE_TOKEN_ONLY.test(read.text.trim());
86
+ }
40
87
  /**
41
88
  * Upper bound on `C-e`+`C-u` passes.
42
89
  *
@@ -67,15 +114,20 @@ async function clearComposer(sessionName, cliToolId, options = {}) {
67
114
  const delay = options.delay ?? defaultDelay;
68
115
  const maxPasses = options.maxPasses ?? exports.MAX_COMPOSER_CLEAR_PASSES;
69
116
  let passes = 0;
70
- let result = (0, composer_text_1.extractComposerText)(await capture(sessionName), cliToolId);
117
+ let result = readClearComposer(await capture(sessionName), cliToolId);
71
118
  // Snapshot before the first pass: every later read shows less of it (a pass
72
119
  // eats one row), so this is the only moment the full text exists.
73
120
  const discardedText = result.state === 'content' ? result.text : '';
74
121
  while (result.state === 'content' && passes < maxPasses) {
75
- await sendClear(sessionName);
122
+ if (isCodexPasteTokenOnly(result, cliToolId)) {
123
+ await (options.sendClearPasteToken ?? tmux_1.clearComposerPasteToken)(sessionName);
124
+ }
125
+ else {
126
+ await sendClear(sessionName);
127
+ }
76
128
  passes++;
77
129
  await delay(exports.COMPOSER_CLEAR_REDRAW_DELAY_MS);
78
- result = (0, composer_text_1.extractComposerText)(await capture(sessionName), cliToolId);
130
+ result = readClearComposer(await capture(sessionName), cliToolId);
79
131
  }
80
132
  // Whatever happened above, the cached frame is now stale: the poller and the
81
133
  // WebSocket push both read through `captureSessionOutput`, and serving the