commandmate 0.47.2 → 0.48.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 (396) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +215 -215
  3. package/.next/app-path-routes-manifest.json +41 -41
  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_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 +12 -12
  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 +41 -41
  232. package/.next/server/chunks/1191.js +11 -4
  233. package/.next/server/chunks/1501.js +1 -1
  234. package/.next/server/chunks/1601.js +2 -2
  235. package/.next/server/chunks/1656.js +2 -2
  236. package/.next/server/chunks/1945.js +3 -3
  237. package/.next/server/chunks/1990.js +103 -0
  238. package/.next/server/chunks/2119.js +1 -1
  239. package/.next/server/chunks/2404.js +1 -1
  240. package/.next/server/chunks/2422.js +1 -1
  241. package/.next/server/chunks/2445.js +1 -1
  242. package/.next/server/chunks/2534.js +1 -1
  243. package/.next/server/chunks/255.js +1 -1
  244. package/.next/server/chunks/3241.js +1 -1
  245. package/.next/server/chunks/3505.js +2 -2
  246. package/.next/server/chunks/4248.js +1 -1
  247. package/.next/server/chunks/4280.js +1 -0
  248. package/.next/server/chunks/5209.js +1 -1
  249. package/.next/server/chunks/6119.js +1 -1
  250. package/.next/server/chunks/6130.js +1 -1
  251. package/.next/server/chunks/6401.js +1 -1
  252. package/.next/server/chunks/6486.js +9 -8
  253. package/.next/server/chunks/6781.js +1 -1
  254. package/.next/server/chunks/720.js +103 -0
  255. package/.next/server/chunks/7604.js +2 -0
  256. package/.next/server/chunks/7905.js +1 -1
  257. package/.next/server/chunks/8581.js +7 -7
  258. package/.next/server/chunks/8728.js +3 -3
  259. package/.next/server/chunks/8791.js +1 -1
  260. package/.next/server/chunks/8807.js +19 -18
  261. package/.next/server/chunks/8918.js +2 -104
  262. package/.next/server/chunks/936.js +1 -1
  263. package/.next/server/chunks/9390.js +1 -1
  264. package/.next/server/chunks/9540.js +1 -1
  265. package/.next/server/chunks/9627.js +3 -3
  266. package/.next/server/chunks/9731.js +2 -2
  267. package/.next/server/middleware-manifest.json +5 -5
  268. package/.next/server/pages/500.html +1 -1
  269. package/.next/server/server-reference-manifest.json +1 -1
  270. package/.next/static/chunks/2099-c3e0ab70a1b95dd3.js +1 -0
  271. package/.next/static/chunks/{2407-a6533805a86d05bd.js → 2407-26139a8a2f1adbe8.js} +1 -1
  272. package/.next/static/chunks/{2619-04bc32f026a0d946.js → 2619-a305ad4810f1393a.js} +1 -1
  273. package/.next/static/chunks/{2863-6a07ec82fb52f4dd.js → 2863-f0121af1cbbedb3b.js} +1 -1
  274. package/.next/static/chunks/{8165-263172c17ae8e8c3.js → 8165-c68b3dc844210e6a.js} +1 -1
  275. package/.next/static/chunks/8407-35bbfc84793d7004.js +1 -0
  276. package/.next/static/chunks/9079-406b84d3cc891a87.js +1 -0
  277. package/.next/static/chunks/app/{layout-538d8d2746ad1588.js → layout-46b4cbf07520d9b6.js} +1 -1
  278. package/.next/static/chunks/app/sessions/page-fb241bed579c67aa.js +1 -0
  279. package/.next/static/chunks/app/worktrees/[id]/page-cbc7749a33450cc5.js +1 -0
  280. package/.next/static/chunks/app/worktrees/[id]/terminal/{page-373ea37b16d930c7.js → page-c601f3b3ece6557e.js} +1 -1
  281. package/.next/trace +13 -13
  282. package/dist/cli/commands/auto-yes.d.ts +24 -0
  283. package/dist/cli/commands/auto-yes.d.ts.map +1 -1
  284. package/dist/cli/commands/auto-yes.js +73 -3
  285. package/dist/cli/commands/instances.d.ts.map +1 -1
  286. package/dist/cli/commands/instances.js +10 -1
  287. package/dist/cli/commands/prompt.d.ts.map +1 -1
  288. package/dist/cli/commands/prompt.js +5 -3
  289. package/dist/cli/commands/send.d.ts.map +1 -1
  290. package/dist/cli/commands/send.js +15 -0
  291. package/dist/cli/commands/wait.d.ts.map +1 -1
  292. package/dist/cli/commands/wait.js +101 -13
  293. package/dist/cli/docs/agent-operations.d.ts +2 -2
  294. package/dist/cli/docs/agent-operations.d.ts.map +1 -1
  295. package/dist/cli/docs/agent-operations.js +27 -0
  296. package/dist/cli/types/api-responses.d.ts +116 -2
  297. package/dist/cli/types/api-responses.d.ts.map +1 -1
  298. package/dist/cli/types/index.d.ts +4 -0
  299. package/dist/cli/types/index.d.ts.map +1 -1
  300. package/dist/cli/utils/resource-resolvers.d.ts +0 -18
  301. package/dist/cli/utils/resource-resolvers.d.ts.map +1 -1
  302. package/dist/cli/utils/resource-resolvers.js +1 -51
  303. package/dist/lib/polling/auto-yes-suppression-reason.d.ts +54 -2
  304. package/dist/lib/polling/auto-yes-suppression-reason.d.ts.map +1 -1
  305. package/dist/lib/polling/auto-yes-suppression-reason.js +33 -2
  306. package/dist/lib/prompt-observation/types.d.ts +13 -0
  307. package/dist/lib/prompt-observation/types.d.ts.map +1 -1
  308. package/dist/server/locales/en/worktree.json +2 -1
  309. package/dist/server/locales/ja/worktree.json +2 -1
  310. package/dist/server/src/lib/auto-yes-poller-answer-target.js +38 -0
  311. package/dist/server/src/lib/auto-yes-poller-keys.js +35 -0
  312. package/dist/server/src/lib/auto-yes-poller-session-presence.js +26 -0
  313. package/dist/server/src/lib/auto-yes-poller-tick.js +233 -0
  314. package/dist/server/src/lib/auto-yes-poller.js +337 -376
  315. package/dist/server/src/lib/auto-yes-state.js +50 -2
  316. package/dist/server/src/lib/cli-tools/submit-verified-sender.js +107 -14
  317. package/dist/server/src/lib/db/chat-db.js +5 -1
  318. package/dist/server/src/lib/db/verification-db.js +23 -2
  319. package/dist/server/src/lib/detection/option-recommendation.js +120 -0
  320. package/dist/server/src/lib/detection/prompt-detect-multiple-choice-approval-context.js +290 -0
  321. package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +396 -350
  322. package/dist/server/src/lib/detection/prompt-detector.js +92 -21
  323. package/dist/server/src/lib/detection/prompt-screen-key.js +60 -0
  324. package/dist/server/src/lib/detection/tools/antigravity/dialog.js +158 -35
  325. package/dist/server/src/lib/detection/tools/claude/detect.js +111 -10
  326. package/dist/server/src/lib/detection/tools/command-code/dialog.js +67 -0
  327. package/dist/server/src/lib/detection/tools/dialog-block.js +16 -0
  328. package/dist/server/src/lib/detection/waiting-screen-reading.js +98 -0
  329. package/dist/server/src/lib/hooks/permission-decision-service.js +7 -0
  330. package/dist/server/src/lib/polling/auto-yes-confirm-page.js +2 -2
  331. package/dist/server/src/lib/polling/auto-yes-confirmation-ledger-types.js +3 -0
  332. package/dist/server/src/lib/polling/auto-yes-confirmation-ledger.js +34 -3
  333. package/dist/server/src/lib/polling/auto-yes-decision-state.js +195 -0
  334. package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +139 -10
  335. package/dist/server/src/lib/polling/auto-yes-enter-fallback.js +14 -0
  336. package/dist/server/src/lib/polling/auto-yes-manual-answer.js +122 -0
  337. package/dist/server/src/lib/polling/auto-yes-option-effect.js +157 -0
  338. package/dist/server/src/lib/polling/auto-yes-policy.js +11 -5
  339. package/dist/server/src/lib/polling/auto-yes-poller-capture.js +15 -2
  340. package/dist/server/src/lib/polling/auto-yes-poller-generation.js +42 -1
  341. package/dist/server/src/lib/polling/auto-yes-poller-receipt-log.js +42 -5
  342. package/dist/server/src/lib/polling/auto-yes-poller-state.js +147 -49
  343. package/dist/server/src/lib/polling/auto-yes-poller-steps.js +172 -2
  344. package/dist/server/src/lib/polling/auto-yes-prompt-suppression.js +2 -2
  345. package/dist/server/src/lib/polling/auto-yes-question-choice.js +57 -0
  346. package/dist/server/src/lib/polling/auto-yes-resolver.js +96 -21
  347. package/dist/server/src/lib/polling/auto-yes-suppression-reason.js +33 -2
  348. package/dist/server/src/lib/polling/auto-yes-suppression-state.js +25 -1
  349. package/dist/server/src/lib/polling/prompt-screen-reading.js +232 -0
  350. package/dist/server/src/lib/polling/response-checker-dialog-gate.js +39 -0
  351. package/dist/server/src/lib/polling/response-checker.js +133 -43
  352. package/dist/server/src/lib/prompt-answer-sender.js +104 -10
  353. package/dist/server/src/lib/push/notification-dedup.js +15 -2
  354. package/dist/server/src/lib/push/prompt-card-state.js +140 -19
  355. package/dist/server/src/lib/push/prompt-push-gate.js +158 -12
  356. package/dist/server/src/lib/push/push-sender.js +23 -3
  357. package/dist/server/src/lib/push/resolution-push-notifier.js +14 -0
  358. package/dist/server/src/lib/push/waiting-push-notifier.js +139 -17
  359. package/dist/server/src/lib/realtime/terminal-broadcast.js +16 -0
  360. package/dist/server/src/lib/session/agent-event-state.js +25 -5
  361. package/dist/server/src/lib/session/agent-event-turn.js +140 -46
  362. package/dist/server/src/lib/session/cli-session.js +21 -2
  363. package/dist/server/src/lib/session/current-output-builder.js +64 -11
  364. package/dist/server/src/lib/session/send-attempt-state.js +23 -7
  365. package/dist/server/src/lib/session/waiting-episode-binding-observation.js +289 -0
  366. package/dist/server/src/lib/session/waiting-episode-binding-resolve.js +38 -0
  367. package/dist/server/src/lib/session/waiting-episode-binding.js +276 -0
  368. package/dist/server/src/lib/session/waiting-episode-state.js +307 -17
  369. package/dist/server/src/lib/session/waiting-episode-verdict.js +174 -0
  370. package/dist/server/src/lib/tmux/tmux-capture-cache.js +76 -11
  371. package/dist/server/src/lib/tmux/tmux.js +54 -9
  372. package/dist/server/src/lib/verification/gate-runner.js +162 -13
  373. package/dist/server/src/lib/verification/machine-lock.js +5 -0
  374. package/dist/server/src/lib/ws-server.js +18 -3
  375. package/dist/server/src/types/auto-yes-answer-mode.js +38 -0
  376. package/dist/server/src/types/auto-yes-decision.js +61 -0
  377. package/dist/server/src/types/auto-yes.js +6 -0
  378. package/dist/server/src/types/prompt-reading.js +32 -0
  379. package/dist/types/auto-yes-answer-mode.d.ts +35 -0
  380. package/dist/types/auto-yes-answer-mode.d.ts.map +1 -0
  381. package/dist/types/auto-yes-answer-mode.js +38 -0
  382. package/docs/en/user-guide/webapp-guide.md +33 -4
  383. package/package.json +1 -1
  384. package/public/sw.js +76 -4
  385. package/release-notes/0.48.0.json +57 -0
  386. package/.next/server/chunks/1559.js +0 -2
  387. package/.next/server/chunks/2460.js +0 -1
  388. package/.next/server/chunks/5595.js +0 -1
  389. package/.next/server/chunks/610.js +0 -1
  390. package/.next/static/chunks/602-1c1488959215e140.js +0 -1
  391. package/.next/static/chunks/8407-155f84e5ba05f1d5.js +0 -1
  392. package/.next/static/chunks/9079-24f9fa549ed298f1.js +0 -1
  393. package/.next/static/chunks/app/sessions/page-e02f1adb1d1c1ccc.js +0 -1
  394. package/.next/static/chunks/app/worktrees/[id]/page-46aced20b2b1c010.js +0 -1
  395. /package/.next/static/{etorRtpxbQqqOzdUeXdw2 → PTlAswXLq8PAe2vUJ8dVP}/_buildManifest.js +0 -0
  396. /package/.next/static/{etorRtpxbQqqOzdUeXdw2 → PTlAswXLq8PAe2vUJ8dVP}/_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) {
@@ -33,7 +33,11 @@ const cli_session_1 = require("../../lib/session/cli-session");
33
33
  const status_detector_1 = require("../../lib/detection/status-detector");
34
34
  const auto_yes_manager_1 = require("../../lib/polling/auto-yes-manager");
35
35
  const auto_yes_suppression_state_1 = require("../../lib/polling/auto-yes-suppression-state");
36
- const auto_yes_enter_fallback_1 = require("../../lib/polling/auto-yes-enter-fallback");
36
+ const auto_yes_poller_state_1 = require("../../lib/polling/auto-yes-poller-state");
37
+ const waiting_episode_state_1 = require("../../lib/session/waiting-episode-state");
38
+ const auto_yes_state_1 = require("../../lib/auto-yes-state");
39
+ const auto_yes_decision_state_1 = require("../../lib/polling/auto-yes-decision-state");
40
+ const antigravity_receipt_episodes_1 = require("../../lib/polling/antigravity-receipt-episodes");
37
41
  const prompt_dedup_state_1 = require("../../lib/polling/prompt-dedup-state");
38
42
  const status_capture_config_1 = require("../../config/status-capture-config");
39
43
  const tmux_capture_cache_1 = require("../../lib/tmux/tmux-capture-cache");
@@ -45,6 +49,7 @@ const status_evidence_1 = require("../../lib/session/status-evidence");
45
49
  const ask_user_question_prompt_1 = require("../../lib/session/ask-user-question-prompt");
46
50
  const prompt_view_1 = require("../../lib/session/prompt-view");
47
51
  const auto_yes_dialog_gate_1 = require("../../lib/polling/auto-yes-dialog-gate");
52
+ const prompt_screen_reading_1 = require("../../lib/polling/prompt-screen-reading");
48
53
  const layer_disagreement_1 = require("../../lib/session/layer-disagreement");
49
54
  const structured_prompt_1 = require("../../lib/session/structured-prompt");
50
55
  const chat_turn_progress_1 = require("./chat-turn-progress");
@@ -226,7 +231,7 @@ function readAgentEvents(worktreeId, cliToolId, instanceId, resolvedInstanceId)
226
231
  * every value below is derived from the arguments, and nothing is assigned
227
232
  * outside this function.
228
233
  */
229
- function composePromptData({ worktreeId, cliToolId, output, statusResult, startingSince, promptWaiting, askUserQuestion, eventSource, }) {
234
+ function composePromptData({ worktreeId, cliToolId, output, captureWindowLines, statusResult, startingSince, promptWaiting, askUserQuestion, eventSource, }) {
230
235
  const scraperPromptWaiting = statusResult.hasActivePrompt;
231
236
  // Issue #1726: the agent's own account of what it asked. It contributes only
232
237
  // where some other layer has already established that a dialog is on screen —
@@ -238,7 +243,14 @@ function composePromptData({ worktreeId, cliToolId, output, statusResult, starti
238
243
  // takes it there today (the decision entries publish the same episode's
239
244
  // choices) — and this line now re-uses it, so the two surfaces cannot describe
240
245
  // different instants.
241
- const scraperPromptData = statusResult.promptDetection.promptData;
246
+ //
247
+ // Issue #3881 (second review N3): with the capture's top as the Auto-Yes
248
+ // poller reads it — an approval target whose upward scan reached a top that
249
+ // may be cut carries `approvalTargetCompleteness: 'top-unknown'`, so the
250
+ // contract re-evaluation of `observe=1` (`prompt-observation/observe.ts`)
251
+ // and `wait` read the same completeness the poller acted on, from the same
252
+ // `captureTopOf` on this payload's own capture window.
253
+ const scraperPromptData = (0, prompt_screen_reading_1.withCaptureTopCompleteness)(statusResult.promptDetection, (0, prompt_screen_reading_1.captureTopOf)(output, captureWindowLines, cliToolId)).promptData;
242
254
  const correctedPromptData = scraperPromptData && askUserQuestion
243
255
  ? (0, ask_user_question_prompt_1.applyAskUserQuestion)(scraperPromptData, askUserQuestion.spec)
244
256
  : null;
@@ -468,12 +480,26 @@ function logDetectionDivergence(worktreeId, cliToolId, resolvedInstanceId, statu
468
480
  });
469
481
  }
470
482
  }
483
+ /**
484
+ * Issue #3821: the agy hook call the receipt on screen was accepted for, for
485
+ * the decision to be matched against; null when unknown. Read only, never throws.
486
+ */
487
+ function acceptedAgyCallId(worktreeId, instanceId) {
488
+ try {
489
+ return (0, antigravity_receipt_episodes_1.getAntigravityAcceptedReceiptCallId)(worktreeId, instanceId);
490
+ }
491
+ catch {
492
+ return null;
493
+ }
494
+ }
471
495
  /**
472
496
  * The payload of a running session (Issue #3272). Split out of
473
497
  * {@link buildPayload} as it stood there, so the keys keep their order and the
474
498
  * reads inside it keep theirs.
475
499
  */
476
- function buildRunningPayload({ worktreeId, cliToolId, instanceId, sessionName, published, merged, newContent, output, realtimeSnippet, totalLines, lastCapturedLine, isPromptWaiting, promptData, promptAnswerable, autoYesState, lastEnterFallback, isSelectionListActive, isPagerActive, isDismissablePanelActive, startingSince, lastKnown, lastServerResponseTimestamp, compositeKey, stopEventAt, structuredEvents, model, effort, upstreamFaultMatch, paneObstruction, composer, }) {
500
+ function buildRunningPayload({ worktreeId, cliToolId, instanceId, sessionName, published, merged, newContent, output, realtimeSnippet, totalLines, lastCapturedLine, isPromptWaiting, promptData, promptAnswerable, autoYesState, lastEnterFallback, autoYesDecision, isSelectionListActive, isPagerActive, isDismissablePanelActive, startingSince, lastKnown, lastServerResponseTimestamp, compositeKey, stopEventAt, structuredEvents, model, effort, upstreamFaultMatch, paneObstruction, composer, }) {
501
+ const lastSuppression = (0, auto_yes_suppression_state_1.getLastPolicySuppression)(worktreeId, cliToolId, instanceId);
502
+ const waitingEpisodeId = (0, waiting_episode_state_1.getWaitingEpisodeRecord)(worktreeId, cliToolId, instanceId)?.episodeId ?? null;
477
503
  return {
478
504
  isRunning: true,
479
505
  sessionName,
@@ -496,14 +522,29 @@ function buildRunningPayload({ worktreeId, cliToolId, instanceId, sessionName, p
496
522
  enabled: autoYesState?.enabled ?? false,
497
523
  expiresAt: autoYesState?.enabled ? autoYesState.expiresAt : null,
498
524
  stopReason: autoYesState?.stopReason,
499
- lastSuppression: (0, auto_yes_suppression_state_1.getLastPolicySuppression)(worktreeId, cliToolId, instanceId),
525
+ lastSuppression,
526
+ // Issue #3798: read in the same step as the record above, which names the
527
+ // wait it was written for — `cmate wait` holds the two against each other.
528
+ waitingEpisodeId,
500
529
  // Issue #1694: undefined (so the key is absent from the JSON) unless a
501
530
  // stop pattern actually fired — the state clears it on every other path.
502
531
  stopMatchedText: autoYesState?.stopMatchedText,
503
532
  // Issue #3397: appended last, after the published fields above. Null when
504
- // Auto-Yes never sent its Enter to an unreadable choice screen here.
533
+ // Auto-Yes never sent its Enter to an unreadable choice screen here —
534
+ // always, since Issue #3821 retired the Enter.
505
535
  lastEnterFallback,
536
+ // Issue #3798: appended last. Whether the poller answered the open wait
537
+ // after the record above was written — the push gate's own reading, so
538
+ // `cmate wait` does not take that record for this wait's reason.
539
+ lastSuppressionAnswered: lastSuppression !== null &&
540
+ (0, auto_yes_suppression_state_1.suppressionPredatesAnswer)(lastSuppression, waitingEpisodeId, (0, auto_yes_poller_state_1.getAutoYesLastAnswer)(compositeKey)),
506
541
  },
542
+ // Issue #3821: next to `autoYes`, and about `promptData` above — whether
543
+ // Auto-Yes is answering it, has left it to a human, or neither.
544
+ autoYesDecision,
545
+ // Issue #3863: how a question on this screen is treated while Auto-Yes is
546
+ // on; the key is absent while it is off.
547
+ ...(autoYesState?.enabled ? { autoYesAnswerMode: (0, auto_yes_state_1.autoYesAnswerModeOf)(autoYesState) } : {}),
507
548
  isSelectionListActive,
508
549
  isPagerActive,
509
550
  isDismissablePanelActive,
@@ -664,7 +705,8 @@ async function buildPayload(db, worktreeId, cliToolId, instanceId) {
664
705
  // The effective window is the smaller of what this path asks for and what the
665
706
  // capture layer will ever fetch — captureSessionOutput() reads at most
666
707
  // CACHE_MAX_CAPTURE_LINES regardless of the request.
667
- const captureWindowSaturated = (0, tmux_capture_cache_1.isCaptureWindowSaturated)(totalLines, Math.min(status_capture_config_1.STATUS_CAPTURE_LINES, tmux_capture_cache_1.CACHE_MAX_CAPTURE_LINES));
708
+ const captureWindowLines = Math.min(status_capture_config_1.STATUS_CAPTURE_LINES, tmux_capture_cache_1.CACHE_MAX_CAPTURE_LINES);
709
+ const captureWindowSaturated = (0, tmux_capture_cache_1.isCaptureWindowSaturated)(totalLines, captureWindowLines);
668
710
  // Issue #1910: saturation of the capture WINDOW is only one of the two ways
669
711
  // the cursor dies, and it is the one that never fires for the alternate-screen
670
712
  // tools — their pane is 1000 rows (claude / copilot) or 200 (opencode), so a
@@ -761,6 +803,7 @@ async function buildPayload(db, worktreeId, cliToolId, instanceId) {
761
803
  worktreeId,
762
804
  cliToolId,
763
805
  output,
806
+ captureWindowLines,
764
807
  statusResult,
765
808
  startingSince,
766
809
  promptWaiting,
@@ -922,10 +965,20 @@ async function buildPayload(db, worktreeId, cliToolId, instanceId) {
922
965
  promptData,
923
966
  promptAnswerable,
924
967
  autoYesState,
925
- // Issue #3397: judged against the screen-read prompt only — the one
926
- // `promptAnswerable` is published for, and the one the poller sent its
927
- // Enter to. A structured (hook / degraded) prompt is never that screen.
928
- lastEnterFallback: (0, auto_yes_enter_fallback_1.publishEnterFallback)((0, auto_yes_enter_fallback_1.getLastEnterFallback)(worktreeId, cliToolId, instanceId), promptAnswerable !== undefined ? statusResult.promptDetection.promptData : null),
968
+ // Issue #3821: the Enter is retired; the key is kept, and is null.
969
+ lastEnterFallback: null,
970
+ // Issue #3821: judged against the screen-read prompt only — the one
971
+ // `promptAnswerable` is published for, and the only kind the poller
972
+ // answers. A structured (hook / degraded) prompt is never that screen, and
973
+ // reads `none`.
974
+ autoYesDecision: (0, auto_yes_decision_state_1.publishAutoYesDecision)({
975
+ compositeKey,
976
+ grant: autoYesState,
977
+ promptData: promptData !== null && promptAnswerable !== undefined ? statusResult.promptDetection.promptData : null,
978
+ // agy: the decision is tied to the hook call its receipt was accepted for.
979
+ callId: cliToolId === 'antigravity' ? acceptedAgyCallId(worktreeId, instanceId) : null,
980
+ pollerActive: (0, auto_yes_manager_1.isPollerActive)(compositeKey),
981
+ }),
929
982
  isSelectionListActive,
930
983
  isPagerActive,
931
984
  isDismissablePanelActive,
@@ -82,6 +82,12 @@ function getLastSendAttempt(instance) {
82
82
  function clearSendAttempts() {
83
83
  records.clear();
84
84
  }
85
+ /**
86
+ * The wordings of a failed tmux call that can carry the message body: `tmux.ts`
87
+ * wraps the child_process error (`Command failed: tmux …argv…`) as
88
+ * `Failed to send keys to tmux session: …` and the like (Issue #3880).
89
+ */
90
+ const TMUX_TRANSPORT_FAILURE = /Command failed: tmux |Failed to send (?:special )?keys? to tmux session|Failed to send special key:|Failed to paste message into tmux session/;
85
91
  /**
86
92
  * Where a failed `ICLITool.sendMessage` stopped, read from its error.
87
93
  *
@@ -103,13 +109,10 @@ function classifySendFailure(error) {
103
109
  return { state: 'not-sent', reason: 'plan-review' };
104
110
  }
105
111
  const message = error instanceof Error ? error.message : String(error);
106
- // The readiness waits of every tool throw before typing anything.
107
- if (/prompt not ready/i.test(message))
108
- return { state: 'not-sent', reason: 'prompt-not-ready' };
109
- // #1880: refused before the body, after only the clear keys (C-e / C-u).
110
- if (/still holds unsent text after \d+ clear passes/.test(message)) {
111
- return { state: 'not-sent', reason: 'composer-not-empty' };
112
- }
112
+ // Issue #3880: the "after the body was typed" wordings are matched FIRST. A
113
+ // body-not-landed error quotes what the composer shows — the user's own text —
114
+ // and a body that says `prompt not ready` must not turn "may have been typed"
115
+ // into "was not typed". Indeterminate wins whenever its wording is present.
113
116
  // #2464 / #3366: typed, never submitted, taken back out best-effort.
114
117
  if (/Enter was not pressed, so nothing was submitted/.test(message)) {
115
118
  return { state: 'indeterminate', reason: 'body-not-landed' };
@@ -122,6 +125,19 @@ function classifySendFailure(error) {
122
125
  if (/submit could not be confirmed/i.test(message)) {
123
126
  return { state: 'indeterminate', reason: 'submit-unconfirmed' };
124
127
  }
128
+ // Issue #3880 (N2): a failed tmux call quotes its argv — and the argv of a
129
+ // literal send IS the body (`Command failed: tmux send-keys -t =s: -l -- <body>`).
130
+ // Whether any of the body reached the pane is unknown, and the body's own words
131
+ // (`Explain prompt not ready.`) must not be read as a readiness refusal below.
132
+ if (TMUX_TRANSPORT_FAILURE.test(message))
133
+ return { state: 'indeterminate', reason: 'send-error' };
134
+ // The readiness waits of every tool throw before typing anything.
135
+ if (/prompt not ready/i.test(message))
136
+ return { state: 'not-sent', reason: 'prompt-not-ready' };
137
+ // #1880: refused before the body, after only the clear keys (C-e / C-u).
138
+ if (/still holds unsent text after \d+ clear passes/.test(message)) {
139
+ return { state: 'not-sent', reason: 'composer-not-empty' };
140
+ }
125
141
  return { state: 'indeterminate', reason: 'send-error' };
126
142
  }
127
143
  /** The whitespace-free form two renderings of one text share. */