commandmate 0.23.0 → 0.24.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 (662) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +393 -384
  3. package/.next/app-path-routes-manifest.json +15 -14
  4. package/.next/build-manifest.json +5 -5
  5. package/.next/prerender-manifest.json +9 -9
  6. package/.next/react-loadable-manifest.json +1 -1
  7. package/.next/required-server-files.json +1 -1
  8. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/app/update-check/route.js +1 -1
  11. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  12. package/.next/server/app/api/assistant/conversation/route.js +1 -1
  13. package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
  14. package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
  15. package/.next/server/app/api/assistant/current-output/route.js +1 -1
  16. package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
  17. package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
  18. package/.next/server/app/api/assistant/messages/route.js +1 -1
  19. package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
  20. package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/assistant/session/route.js +1 -1
  22. package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
  23. package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
  24. package/.next/server/app/api/assistant/start/route.js +1 -1
  25. package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
  26. package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
  27. package/.next/server/app/api/assistant/terminal/route.js +2 -2
  28. package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
  29. package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
  30. package/.next/server/app/api/assistant/tools/route.js +1 -1
  31. package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
  32. package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/daily-summary/route.js +1 -1
  37. package/.next/server/app/api/daily-summary/route.js.nft.json +1 -1
  38. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/daily-summary/status/route.js +1 -1
  40. package/.next/server/app/api/daily-summary/status/route.js.nft.json +1 -1
  41. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  46. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  47. package/.next/server/app/api/hooks/agent-event/route.js +1 -1
  48. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  49. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/hooks/claude-done/route.js +1 -1
  51. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  52. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  53. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  54. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  55. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  58. package/.next/server/app/api/push/escalation/route.js +1 -0
  59. package/.next/server/app/api/push/escalation/route.js.nft.json +1 -0
  60. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -0
  61. package/.next/server/app/api/push/subscriptions/route.js +1 -1
  62. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  63. package/.next/server/app/api/push/vapid/route.js +1 -1
  64. package/.next/server/app/api/push/vapid/route.js.nft.json +1 -1
  65. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  66. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  67. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route.js +1 -1
  68. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/repositories/[id]/todos/route.js +1 -1
  70. package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
  71. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  72. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  73. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  74. package/.next/server/app/api/repositories/clone/route.js +1 -1
  75. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  76. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  78. package/.next/server/app/api/repositories/restore/route.js +1 -1
  79. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  80. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/repositories/route.js +1 -1
  82. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  83. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/repositories/scan/route.js +1 -1
  85. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  86. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/repositories/sync/route.js +1 -1
  88. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  89. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  94. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  95. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  97. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/tasks/[taskId]/route.js +1 -1
  100. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/todos/route.js +1 -1
  104. package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/verification/runs/[runId]/route.js +1 -1
  106. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  107. package/.next/server/app/api/verification/runs/route.js +1 -1
  108. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  111. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  114. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route.js.nft.json +1 -1
  119. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  122. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/execution-logs/route.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/branches/route.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/commit/route.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/log/route.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/git/staged/route.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  150. package/.next/server/app/api/worktrees/[id]/git/stash/push/route.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/git/stash/route.js +1 -1
  153. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/git/status/route.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  156. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/git/working-diff/route.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  161. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  164. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  167. package/.next/server/app/api/worktrees/[id]/marp-render/route.js +5 -5
  168. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -1
  172. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/messages/route.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  175. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  176. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  177. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  179. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  180. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  183. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  184. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +2 -2
  185. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js.nft.json +1 -1
  186. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  187. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/schedules/active/route.js.nft.json +1 -1
  189. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/schedules/route.js +3 -3
  191. package/.next/server/app/api/worktrees/[id]/schedules/route.js.nft.json +1 -1
  192. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  196. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  199. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  203. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/skills/route.js +1 -1
  207. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  212. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/start-polling/route.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +1 -1
  215. package/.next/server/app/api/worktrees/[id]/start-polling/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/tasks/route.js +2 -2
  217. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  218. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
  219. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  220. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  221. package/.next/server/app/api/worktrees/[id]/timers/history/route.js +1 -1
  222. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  223. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  224. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  225. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  226. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js +1 -1
  227. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/api/worktrees/[id]/todos/route.js +1 -1
  229. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  230. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js +1 -1
  231. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  232. package/.next/server/app/api/worktrees/[id]/tree/route.js +1 -1
  233. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  234. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  235. package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
  236. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  237. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route.js +1 -1
  238. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  239. package/.next/server/app/api/worktrees/[id]/verify/runs/route.js +1 -1
  240. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  241. package/.next/server/app/api/worktrees/[id]/viewed/route.js +1 -1
  242. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  243. package/.next/server/app/api/worktrees/route.js +1 -1
  244. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  245. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  246. package/.next/server/app/chat/page.js +2 -2
  247. package/.next/server/app/chat/page.js.nft.json +1 -1
  248. package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  249. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  250. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  251. package/.next/server/app/more/page.js +2 -2
  252. package/.next/server/app/more/page.js.nft.json +1 -1
  253. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  254. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  255. package/.next/server/app/page.js +1 -1
  256. package/.next/server/app/page.js.nft.json +1 -1
  257. package/.next/server/app/page_client-reference-manifest.js +1 -1
  258. package/.next/server/app/proxy/[...path]/route.js +1 -1
  259. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  260. package/.next/server/app/repositories/page.js +2 -2
  261. package/.next/server/app/repositories/page.js.nft.json +1 -1
  262. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  263. package/.next/server/app/review/page.js +1 -1
  264. package/.next/server/app/review/page.js.nft.json +1 -1
  265. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  266. package/.next/server/app/sessions/page.js +1 -1
  267. package/.next/server/app/sessions/page.js.nft.json +1 -1
  268. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  269. package/.next/server/app/skills/[skillId]/page.js +2 -2
  270. package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
  271. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  272. package/.next/server/app/skills/installed/page.js +2 -2
  273. package/.next/server/app/skills/installed/page.js.nft.json +1 -1
  274. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  275. package/.next/server/app/skills/page.js +1 -1
  276. package/.next/server/app/skills/page.js.nft.json +1 -1
  277. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  278. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  279. package/.next/server/app/worktrees/[id]/page.js +6 -6
  280. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  281. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  282. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  283. package/.next/server/app-paths-manifest.json +15 -14
  284. package/.next/server/chunks/1029.js +1 -1
  285. package/.next/server/chunks/1296.js +1 -1
  286. package/.next/server/chunks/1366.js +1 -1
  287. package/.next/server/chunks/1601.js +7 -0
  288. package/.next/server/chunks/1825.js +1 -1
  289. package/.next/server/chunks/2119.js +1 -1
  290. package/.next/server/chunks/2445.js +1 -1
  291. package/.next/server/chunks/2546.js +1 -1
  292. package/.next/server/chunks/3417.js +1 -1
  293. package/.next/server/chunks/3451.js +1 -1
  294. package/.next/server/chunks/3480.js +1 -1
  295. package/.next/server/chunks/3543.js +1 -1
  296. package/.next/server/chunks/3945.js +1 -1
  297. package/.next/server/chunks/4393.js +1 -0
  298. package/.next/server/chunks/4444.js +1 -1
  299. package/.next/server/chunks/4455.js +1 -0
  300. package/.next/server/chunks/5164.js +1 -0
  301. package/.next/server/chunks/5959.js +5 -5
  302. package/.next/server/chunks/5998.js +1 -1
  303. package/.next/server/chunks/6130.js +1 -1
  304. package/.next/server/chunks/6159.js +1 -1
  305. package/.next/server/chunks/6274.js +2 -2
  306. package/.next/server/chunks/6401.js +1 -1
  307. package/.next/server/chunks/7458.js +5 -5
  308. package/.next/server/chunks/8536.js +1 -1
  309. package/.next/server/chunks/880.js +21 -0
  310. package/.next/server/chunks/8807.js +134 -129
  311. package/.next/server/chunks/9058.js +1 -1
  312. package/.next/server/chunks/9123.js +8 -8
  313. package/.next/server/chunks/9358.js +1 -1
  314. package/.next/server/chunks/9373.js +3 -3
  315. package/.next/server/chunks/9687.js +1 -1
  316. package/.next/server/middleware-build-manifest.js +1 -1
  317. package/.next/server/middleware-manifest.json +5 -5
  318. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  319. package/.next/server/pages/500.html +1 -1
  320. package/.next/server/server-reference-manifest.json +1 -1
  321. package/.next/static/chunks/4322-dfd5a7119b5ba4fc.js +1 -0
  322. package/.next/static/chunks/{4974-eaf66770bfa9dea0.js → 4974-35592ec312322124.js} +1 -1
  323. package/.next/static/chunks/5229-0610b4e3288e777d.js +1 -0
  324. package/.next/static/chunks/6381-18a6a02a94d00d76.js +1 -0
  325. package/.next/static/chunks/7229.7f0f5a7032b612b4.js +1 -0
  326. package/.next/static/chunks/{744-fa8c0ae444c8338c.js → 744-3ad06d8c8ca482fc.js} +1 -1
  327. package/.next/static/chunks/app/api/app/update/{route-973ec48531555712.js → route-fae89f8d4cc3ff97.js} +1 -1
  328. package/.next/static/chunks/app/api/app/update-check/{route-973ec48531555712.js → route-fae89f8d4cc3ff97.js} +1 -1
  329. package/.next/static/chunks/app/api/assistant/conversation/{route-973ec48531555712.js → route-fae89f8d4cc3ff97.js} +1 -1
  330. package/.next/static/chunks/app/api/assistant/current-output/{route-973ec48531555712.js → route-fae89f8d4cc3ff97.js} +1 -1
  331. package/.next/static/chunks/app/api/assistant/messages/route-fae89f8d4cc3ff97.js +1 -0
  332. package/.next/static/chunks/app/api/assistant/session/route-fae89f8d4cc3ff97.js +1 -0
  333. package/.next/static/chunks/app/api/assistant/start/route-fae89f8d4cc3ff97.js +1 -0
  334. package/.next/static/chunks/app/api/assistant/terminal/route-fae89f8d4cc3ff97.js +1 -0
  335. package/.next/static/chunks/app/api/assistant/tools/route-fae89f8d4cc3ff97.js +1 -0
  336. package/.next/static/chunks/app/api/auth/login/route-fae89f8d4cc3ff97.js +1 -0
  337. package/.next/static/chunks/app/api/auth/logout/route-fae89f8d4cc3ff97.js +1 -0
  338. package/.next/static/chunks/app/api/auth/status/route-fae89f8d4cc3ff97.js +1 -0
  339. package/.next/static/chunks/app/api/daily-summary/route-fae89f8d4cc3ff97.js +1 -0
  340. package/.next/static/chunks/app/api/daily-summary/status/route-fae89f8d4cc3ff97.js +1 -0
  341. package/.next/static/chunks/app/api/external-apps/[id]/health/route-fae89f8d4cc3ff97.js +1 -0
  342. package/.next/static/chunks/app/api/external-apps/[id]/route-fae89f8d4cc3ff97.js +1 -0
  343. package/.next/static/chunks/app/api/external-apps/route-fae89f8d4cc3ff97.js +1 -0
  344. package/.next/static/chunks/app/api/fs/browse/route-fae89f8d4cc3ff97.js +1 -0
  345. package/.next/static/chunks/app/api/fs/recent-paths/route-fae89f8d4cc3ff97.js +1 -0
  346. package/.next/static/chunks/app/api/hooks/agent-event/route-fae89f8d4cc3ff97.js +1 -0
  347. package/.next/static/chunks/app/api/hooks/claude-done/route-fae89f8d4cc3ff97.js +1 -0
  348. package/.next/static/chunks/app/api/hooks/permission-request/route-fae89f8d4cc3ff97.js +1 -0
  349. package/.next/static/chunks/app/api/metrics/vibe/route-fae89f8d4cc3ff97.js +1 -0
  350. package/.next/static/chunks/app/api/ollama/models/route-fae89f8d4cc3ff97.js +1 -0
  351. package/.next/static/chunks/app/api/push/escalation/route-fae89f8d4cc3ff97.js +1 -0
  352. package/.next/static/chunks/app/api/push/subscriptions/route-fae89f8d4cc3ff97.js +1 -0
  353. package/.next/static/chunks/app/api/push/vapid/route-fae89f8d4cc3ff97.js +1 -0
  354. package/.next/static/chunks/app/api/repositories/[id]/route-fae89f8d4cc3ff97.js +1 -0
  355. package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-fae89f8d4cc3ff97.js +1 -0
  356. package/.next/static/chunks/app/api/repositories/[id]/todos/route-fae89f8d4cc3ff97.js +1 -0
  357. package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-fae89f8d4cc3ff97.js +1 -0
  358. package/.next/static/chunks/app/api/repositories/clone/route-fae89f8d4cc3ff97.js +1 -0
  359. package/.next/static/chunks/app/api/repositories/excluded/route-fae89f8d4cc3ff97.js +1 -0
  360. package/.next/static/chunks/app/api/repositories/restore/route-fae89f8d4cc3ff97.js +1 -0
  361. package/.next/static/chunks/app/api/repositories/route-fae89f8d4cc3ff97.js +1 -0
  362. package/.next/static/chunks/app/api/repositories/scan/route-fae89f8d4cc3ff97.js +1 -0
  363. package/.next/static/chunks/app/api/repositories/sync/route-fae89f8d4cc3ff97.js +1 -0
  364. package/.next/static/chunks/app/api/repositories/validate-path/route-fae89f8d4cc3ff97.js +1 -0
  365. package/.next/static/chunks/app/api/sidebar/group-order/route-fae89f8d4cc3ff97.js +1 -0
  366. package/.next/static/chunks/app/api/skills/[id]/route-fae89f8d4cc3ff97.js +1 -0
  367. package/.next/static/chunks/app/api/skills/installations/route-fae89f8d4cc3ff97.js +1 -0
  368. package/.next/static/chunks/app/api/skills/operations/route-fae89f8d4cc3ff97.js +1 -0
  369. package/.next/static/chunks/app/api/skills/reindex/route-fae89f8d4cc3ff97.js +1 -0
  370. package/.next/static/chunks/app/api/skills/route-fae89f8d4cc3ff97.js +1 -0
  371. package/.next/static/chunks/app/api/slash-commands/route-fae89f8d4cc3ff97.js +1 -0
  372. package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-fae89f8d4cc3ff97.js +1 -0
  373. package/.next/static/chunks/app/api/tasks/[taskId]/route-fae89f8d4cc3ff97.js +1 -0
  374. package/.next/static/chunks/app/api/templates/[id]/route-fae89f8d4cc3ff97.js +1 -0
  375. package/.next/static/chunks/app/api/templates/route-fae89f8d4cc3ff97.js +1 -0
  376. package/.next/static/chunks/app/api/todos/route-fae89f8d4cc3ff97.js +1 -0
  377. package/.next/static/chunks/app/api/verification/runs/[runId]/route-fae89f8d4cc3ff97.js +1 -0
  378. package/.next/static/chunks/app/api/verification/runs/route-fae89f8d4cc3ff97.js +1 -0
  379. package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-fae89f8d4cc3ff97.js +1 -0
  380. package/.next/static/chunks/app/api/worktrees/[id]/capture/route-fae89f8d4cc3ff97.js +1 -0
  381. package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-fae89f8d4cc3ff97.js +1 -0
  382. package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-fae89f8d4cc3ff97.js +1 -0
  383. package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-fae89f8d4cc3ff97.js +1 -0
  384. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-fae89f8d4cc3ff97.js +1 -0
  385. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-fae89f8d4cc3ff97.js +1 -0
  386. package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-fae89f8d4cc3ff97.js +1 -0
  387. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-fae89f8d4cc3ff97.js +1 -0
  388. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-fae89f8d4cc3ff97.js +1 -0
  389. package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-fae89f8d4cc3ff97.js +1 -0
  390. package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-fae89f8d4cc3ff97.js +1 -0
  391. package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-fae89f8d4cc3ff97.js +1 -0
  392. package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-fae89f8d4cc3ff97.js +1 -0
  393. package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-fae89f8d4cc3ff97.js +1 -0
  394. package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-fae89f8d4cc3ff97.js +1 -0
  395. package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-fae89f8d4cc3ff97.js +1 -0
  396. package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-fae89f8d4cc3ff97.js +1 -0
  397. package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-fae89f8d4cc3ff97.js +1 -0
  398. package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-fae89f8d4cc3ff97.js +1 -0
  399. package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-fae89f8d4cc3ff97.js +1 -0
  400. package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-fae89f8d4cc3ff97.js +1 -0
  401. package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-fae89f8d4cc3ff97.js +1 -0
  402. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-fae89f8d4cc3ff97.js +1 -0
  403. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-fae89f8d4cc3ff97.js +1 -0
  404. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-fae89f8d4cc3ff97.js +1 -0
  405. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-fae89f8d4cc3ff97.js +1 -0
  406. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-fae89f8d4cc3ff97.js +1 -0
  407. package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-fae89f8d4cc3ff97.js +1 -0
  408. package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-fae89f8d4cc3ff97.js +1 -0
  409. package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-fae89f8d4cc3ff97.js +1 -0
  410. package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-fae89f8d4cc3ff97.js +1 -0
  411. package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-fae89f8d4cc3ff97.js +1 -0
  412. package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-fae89f8d4cc3ff97.js +1 -0
  413. package/.next/static/chunks/app/api/worktrees/[id]/logs/route-fae89f8d4cc3ff97.js +1 -0
  414. package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-fae89f8d4cc3ff97.js +1 -0
  415. package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-fae89f8d4cc3ff97.js +1 -0
  416. package/.next/static/chunks/app/api/worktrees/[id]/memos/route-fae89f8d4cc3ff97.js +1 -0
  417. package/.next/static/chunks/app/api/worktrees/[id]/messages/route-fae89f8d4cc3ff97.js +1 -0
  418. package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-fae89f8d4cc3ff97.js +1 -0
  419. package/.next/static/chunks/app/api/worktrees/[id]/respond/route-fae89f8d4cc3ff97.js +1 -0
  420. package/.next/static/chunks/app/api/worktrees/[id]/route-fae89f8d4cc3ff97.js +1 -0
  421. package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-fae89f8d4cc3ff97.js +1 -0
  422. package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-fae89f8d4cc3ff97.js +1 -0
  423. package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-fae89f8d4cc3ff97.js +1 -0
  424. package/.next/static/chunks/app/api/worktrees/[id]/search/route-fae89f8d4cc3ff97.js +1 -0
  425. package/.next/static/chunks/app/api/worktrees/[id]/send/route-fae89f8d4cc3ff97.js +1 -0
  426. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-fae89f8d4cc3ff97.js +1 -0
  427. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-fae89f8d4cc3ff97.js +1 -0
  428. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-fae89f8d4cc3ff97.js +1 -0
  429. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-fae89f8d4cc3ff97.js +1 -0
  430. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-fae89f8d4cc3ff97.js +1 -0
  431. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-fae89f8d4cc3ff97.js +1 -0
  432. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-fae89f8d4cc3ff97.js +1 -0
  433. package/.next/static/chunks/app/api/worktrees/[id]/skills/route-fae89f8d4cc3ff97.js +1 -0
  434. package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-fae89f8d4cc3ff97.js +1 -0
  435. package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-fae89f8d4cc3ff97.js +1 -0
  436. package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-fae89f8d4cc3ff97.js +1 -0
  437. package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-fae89f8d4cc3ff97.js +1 -0
  438. package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-fae89f8d4cc3ff97.js +1 -0
  439. package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-fae89f8d4cc3ff97.js +1 -0
  440. package/.next/static/chunks/app/api/worktrees/[id]/timers/route-fae89f8d4cc3ff97.js +1 -0
  441. package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-fae89f8d4cc3ff97.js +1 -0
  442. package/.next/static/chunks/app/api/worktrees/[id]/todos/route-fae89f8d4cc3ff97.js +1 -0
  443. package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-fae89f8d4cc3ff97.js +1 -0
  444. package/.next/static/chunks/app/api/worktrees/[id]/tree/route-fae89f8d4cc3ff97.js +1 -0
  445. package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-fae89f8d4cc3ff97.js +1 -0
  446. package/.next/static/chunks/app/api/worktrees/[id]/verify/route-fae89f8d4cc3ff97.js +1 -0
  447. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-fae89f8d4cc3ff97.js +1 -0
  448. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-fae89f8d4cc3ff97.js +1 -0
  449. package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-fae89f8d4cc3ff97.js +1 -0
  450. package/.next/static/chunks/app/api/worktrees/route-fae89f8d4cc3ff97.js +1 -0
  451. package/.next/static/chunks/app/chat/page-15d13fc024d78f5d.js +1 -0
  452. package/.next/static/chunks/app/layout-6a26ea22d5cf03dc.js +1 -0
  453. package/.next/static/chunks/app/manifest.webmanifest/route-fae89f8d4cc3ff97.js +1 -0
  454. package/.next/static/chunks/app/more/page-b8ba537baeac8d5b.js +1 -0
  455. package/.next/static/chunks/app/page-afc64708362f31e5.js +1 -0
  456. package/.next/static/chunks/app/proxy/[...path]/route-fae89f8d4cc3ff97.js +1 -0
  457. package/.next/static/chunks/app/repositories/page-3469dacb6be7842f.js +1 -0
  458. package/.next/static/chunks/app/review/page-2d9cb7e068f8f35a.js +1 -0
  459. package/.next/static/chunks/app/sessions/page-7470c2bfd89e0df9.js +1 -0
  460. package/.next/static/chunks/app/skills/[skillId]/page-5e24481162f7ea78.js +1 -0
  461. package/.next/static/chunks/app/skills/installed/page-efd2d710a27f9735.js +1 -0
  462. package/.next/static/chunks/app/skills/page-0498adfc6e48684b.js +1 -0
  463. package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-9ddcb224594f620f.js +1 -0
  464. package/.next/static/chunks/app/worktrees/[id]/layout-fae89f8d4cc3ff97.js +1 -0
  465. package/.next/static/chunks/app/worktrees/[id]/page-e611d30e47989e5d.js +1 -0
  466. package/.next/static/chunks/{webpack-180bebdee221b6f4.js → webpack-3534d858912a6c92.js} +1 -1
  467. package/.next/static/css/3ac44cfc082d02ad.css +1 -0
  468. package/.next/static/smu4mnL7qMf8w38n9dQJE/_buildManifest.js +1 -0
  469. package/.next/trace +12 -12
  470. package/.next/types/app/api/push/escalation/route.ts +347 -0
  471. package/.next/types/routes.d.ts +2 -1
  472. package/.next/types/validator.ts +9 -0
  473. package/dist/cli/commands/capture.d.ts.map +1 -1
  474. package/dist/cli/commands/capture.js +6 -0
  475. package/dist/cli/commands/instances.d.ts.map +1 -1
  476. package/dist/cli/commands/instances.js +19 -1
  477. package/dist/cli/commands/task.d.ts.map +1 -1
  478. package/dist/cli/commands/task.js +6 -0
  479. package/dist/cli/commands/verify.js +6 -1
  480. package/dist/cli/types/api-responses.d.ts +46 -0
  481. package/dist/cli/types/api-responses.d.ts.map +1 -1
  482. package/dist/cli/utils/verify-runner.d.ts.map +1 -1
  483. package/dist/cli/utils/verify-runner.js +17 -1
  484. package/dist/server/locales/en/notifications.json +20 -1
  485. package/dist/server/locales/ja/notifications.json +20 -1
  486. package/dist/server/server.js +23 -0
  487. package/dist/server/src/lib/db/db.js +2 -1
  488. package/dist/server/src/lib/db/migrations/index.js +2 -0
  489. package/dist/server/src/lib/db/migrations/runner.js +1 -1
  490. package/dist/server/src/lib/db/migrations/v56-gate-result-source.js +58 -0
  491. package/dist/server/src/lib/db/verification-db.js +26 -6
  492. package/dist/server/src/lib/detection/model-info-extractor.js +384 -0
  493. package/dist/server/src/lib/hooks/sources/antigravity/source.js +4 -0
  494. package/dist/server/src/lib/hooks/sources/claude/source.js +7 -0
  495. package/dist/server/src/lib/hooks/sources/codex/source.js +5 -0
  496. package/dist/server/src/lib/hooks/sources/define-source.js +8 -0
  497. package/dist/server/src/lib/hooks/sources/event-mapper.js +20 -0
  498. package/dist/server/src/lib/hooks/sources/opencode/ingest.js +6 -0
  499. package/dist/server/src/lib/hooks/sources/opencode/mappers.js +22 -0
  500. package/dist/server/src/lib/hooks/sources/opencode/source.js +3 -0
  501. package/dist/server/src/lib/polling/response-checker.js +47 -0
  502. package/dist/server/src/lib/push/escalation-settings.js +114 -0
  503. package/dist/server/src/lib/push/index.js +21 -1
  504. package/dist/server/src/lib/push/notification-dedup.js +35 -0
  505. package/dist/server/src/lib/push/push-sender.js +66 -7
  506. package/dist/server/src/lib/push/waiting-push-notifier.js +231 -0
  507. package/dist/server/src/lib/realtime/waiting-broadcast.js +93 -0
  508. package/dist/server/src/lib/session/agent-event-state.js +260 -0
  509. package/dist/server/src/lib/session/current-output-builder.js +24 -0
  510. package/dist/server/src/lib/session/next-action-helper.js +93 -0
  511. package/dist/server/src/lib/session/prompt-waiting-composition.js +38 -0
  512. package/dist/server/src/lib/session/waiting-episode-state.js +136 -0
  513. package/dist/server/src/lib/session/waiting-kind.js +59 -0
  514. package/dist/server/src/lib/tasks/contract-message.js +64 -21
  515. package/dist/server/src/lib/tasks/contract-parser.js +58 -12
  516. package/dist/server/src/lib/verification/gate-runner.js +64 -22
  517. package/dist/server/src/lib/verification/verify-config.js +84 -51
  518. package/dist/server/src/lib/ws-server.js +9 -0
  519. package/dist/server/src/types/sidebar.js +68 -0
  520. package/package.json +1 -1
  521. package/.next/server/chunks/6283.js +0 -1
  522. package/.next/server/chunks/646.js +0 -21
  523. package/.next/static/chunks/4560-0917ae2e6a0e5400.js +0 -1
  524. package/.next/static/chunks/6488-95ba9d24a76f0cc5.js +0 -1
  525. package/.next/static/chunks/7229.edb331fb9fbafa27.js +0 -1
  526. package/.next/static/chunks/app/api/assistant/messages/route-973ec48531555712.js +0 -1
  527. package/.next/static/chunks/app/api/assistant/session/route-973ec48531555712.js +0 -1
  528. package/.next/static/chunks/app/api/assistant/start/route-973ec48531555712.js +0 -1
  529. package/.next/static/chunks/app/api/assistant/terminal/route-973ec48531555712.js +0 -1
  530. package/.next/static/chunks/app/api/assistant/tools/route-973ec48531555712.js +0 -1
  531. package/.next/static/chunks/app/api/auth/login/route-973ec48531555712.js +0 -1
  532. package/.next/static/chunks/app/api/auth/logout/route-973ec48531555712.js +0 -1
  533. package/.next/static/chunks/app/api/auth/status/route-973ec48531555712.js +0 -1
  534. package/.next/static/chunks/app/api/daily-summary/route-973ec48531555712.js +0 -1
  535. package/.next/static/chunks/app/api/daily-summary/status/route-973ec48531555712.js +0 -1
  536. package/.next/static/chunks/app/api/external-apps/[id]/health/route-973ec48531555712.js +0 -1
  537. package/.next/static/chunks/app/api/external-apps/[id]/route-973ec48531555712.js +0 -1
  538. package/.next/static/chunks/app/api/external-apps/route-973ec48531555712.js +0 -1
  539. package/.next/static/chunks/app/api/fs/browse/route-973ec48531555712.js +0 -1
  540. package/.next/static/chunks/app/api/fs/recent-paths/route-973ec48531555712.js +0 -1
  541. package/.next/static/chunks/app/api/hooks/agent-event/route-973ec48531555712.js +0 -1
  542. package/.next/static/chunks/app/api/hooks/claude-done/route-973ec48531555712.js +0 -1
  543. package/.next/static/chunks/app/api/hooks/permission-request/route-973ec48531555712.js +0 -1
  544. package/.next/static/chunks/app/api/metrics/vibe/route-973ec48531555712.js +0 -1
  545. package/.next/static/chunks/app/api/ollama/models/route-973ec48531555712.js +0 -1
  546. package/.next/static/chunks/app/api/push/subscriptions/route-973ec48531555712.js +0 -1
  547. package/.next/static/chunks/app/api/push/vapid/route-973ec48531555712.js +0 -1
  548. package/.next/static/chunks/app/api/repositories/[id]/route-973ec48531555712.js +0 -1
  549. package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-973ec48531555712.js +0 -1
  550. package/.next/static/chunks/app/api/repositories/[id]/todos/route-973ec48531555712.js +0 -1
  551. package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-973ec48531555712.js +0 -1
  552. package/.next/static/chunks/app/api/repositories/clone/route-973ec48531555712.js +0 -1
  553. package/.next/static/chunks/app/api/repositories/excluded/route-973ec48531555712.js +0 -1
  554. package/.next/static/chunks/app/api/repositories/restore/route-973ec48531555712.js +0 -1
  555. package/.next/static/chunks/app/api/repositories/route-973ec48531555712.js +0 -1
  556. package/.next/static/chunks/app/api/repositories/scan/route-973ec48531555712.js +0 -1
  557. package/.next/static/chunks/app/api/repositories/sync/route-973ec48531555712.js +0 -1
  558. package/.next/static/chunks/app/api/repositories/validate-path/route-973ec48531555712.js +0 -1
  559. package/.next/static/chunks/app/api/sidebar/group-order/route-973ec48531555712.js +0 -1
  560. package/.next/static/chunks/app/api/skills/[id]/route-973ec48531555712.js +0 -1
  561. package/.next/static/chunks/app/api/skills/installations/route-973ec48531555712.js +0 -1
  562. package/.next/static/chunks/app/api/skills/operations/route-973ec48531555712.js +0 -1
  563. package/.next/static/chunks/app/api/skills/reindex/route-973ec48531555712.js +0 -1
  564. package/.next/static/chunks/app/api/skills/route-973ec48531555712.js +0 -1
  565. package/.next/static/chunks/app/api/slash-commands/route-973ec48531555712.js +0 -1
  566. package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-973ec48531555712.js +0 -1
  567. package/.next/static/chunks/app/api/tasks/[taskId]/route-973ec48531555712.js +0 -1
  568. package/.next/static/chunks/app/api/templates/[id]/route-973ec48531555712.js +0 -1
  569. package/.next/static/chunks/app/api/templates/route-973ec48531555712.js +0 -1
  570. package/.next/static/chunks/app/api/todos/route-973ec48531555712.js +0 -1
  571. package/.next/static/chunks/app/api/verification/runs/[runId]/route-973ec48531555712.js +0 -1
  572. package/.next/static/chunks/app/api/verification/runs/route-973ec48531555712.js +0 -1
  573. package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-973ec48531555712.js +0 -1
  574. package/.next/static/chunks/app/api/worktrees/[id]/capture/route-973ec48531555712.js +0 -1
  575. package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-973ec48531555712.js +0 -1
  576. package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-973ec48531555712.js +0 -1
  577. package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-973ec48531555712.js +0 -1
  578. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-973ec48531555712.js +0 -1
  579. package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-973ec48531555712.js +0 -1
  580. package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-973ec48531555712.js +0 -1
  581. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-973ec48531555712.js +0 -1
  582. package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-973ec48531555712.js +0 -1
  583. package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-973ec48531555712.js +0 -1
  584. package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-973ec48531555712.js +0 -1
  585. package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-973ec48531555712.js +0 -1
  586. package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-973ec48531555712.js +0 -1
  587. package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-973ec48531555712.js +0 -1
  588. package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-973ec48531555712.js +0 -1
  589. package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-973ec48531555712.js +0 -1
  590. package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-973ec48531555712.js +0 -1
  591. package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-973ec48531555712.js +0 -1
  592. package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-973ec48531555712.js +0 -1
  593. package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-973ec48531555712.js +0 -1
  594. package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-973ec48531555712.js +0 -1
  595. package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-973ec48531555712.js +0 -1
  596. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-973ec48531555712.js +0 -1
  597. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-973ec48531555712.js +0 -1
  598. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-973ec48531555712.js +0 -1
  599. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-973ec48531555712.js +0 -1
  600. package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-973ec48531555712.js +0 -1
  601. package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-973ec48531555712.js +0 -1
  602. package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-973ec48531555712.js +0 -1
  603. package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-973ec48531555712.js +0 -1
  604. package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-973ec48531555712.js +0 -1
  605. package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-973ec48531555712.js +0 -1
  606. package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-973ec48531555712.js +0 -1
  607. package/.next/static/chunks/app/api/worktrees/[id]/logs/route-973ec48531555712.js +0 -1
  608. package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-973ec48531555712.js +0 -1
  609. package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-973ec48531555712.js +0 -1
  610. package/.next/static/chunks/app/api/worktrees/[id]/memos/route-973ec48531555712.js +0 -1
  611. package/.next/static/chunks/app/api/worktrees/[id]/messages/route-973ec48531555712.js +0 -1
  612. package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-973ec48531555712.js +0 -1
  613. package/.next/static/chunks/app/api/worktrees/[id]/respond/route-973ec48531555712.js +0 -1
  614. package/.next/static/chunks/app/api/worktrees/[id]/route-973ec48531555712.js +0 -1
  615. package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-973ec48531555712.js +0 -1
  616. package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-973ec48531555712.js +0 -1
  617. package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-973ec48531555712.js +0 -1
  618. package/.next/static/chunks/app/api/worktrees/[id]/search/route-973ec48531555712.js +0 -1
  619. package/.next/static/chunks/app/api/worktrees/[id]/send/route-973ec48531555712.js +0 -1
  620. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-973ec48531555712.js +0 -1
  621. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-973ec48531555712.js +0 -1
  622. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-973ec48531555712.js +0 -1
  623. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-973ec48531555712.js +0 -1
  624. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-973ec48531555712.js +0 -1
  625. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-973ec48531555712.js +0 -1
  626. package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-973ec48531555712.js +0 -1
  627. package/.next/static/chunks/app/api/worktrees/[id]/skills/route-973ec48531555712.js +0 -1
  628. package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-973ec48531555712.js +0 -1
  629. package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-973ec48531555712.js +0 -1
  630. package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-973ec48531555712.js +0 -1
  631. package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-973ec48531555712.js +0 -1
  632. package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-973ec48531555712.js +0 -1
  633. package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-973ec48531555712.js +0 -1
  634. package/.next/static/chunks/app/api/worktrees/[id]/timers/route-973ec48531555712.js +0 -1
  635. package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-973ec48531555712.js +0 -1
  636. package/.next/static/chunks/app/api/worktrees/[id]/todos/route-973ec48531555712.js +0 -1
  637. package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-973ec48531555712.js +0 -1
  638. package/.next/static/chunks/app/api/worktrees/[id]/tree/route-973ec48531555712.js +0 -1
  639. package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-973ec48531555712.js +0 -1
  640. package/.next/static/chunks/app/api/worktrees/[id]/verify/route-973ec48531555712.js +0 -1
  641. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-973ec48531555712.js +0 -1
  642. package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-973ec48531555712.js +0 -1
  643. package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-973ec48531555712.js +0 -1
  644. package/.next/static/chunks/app/api/worktrees/route-973ec48531555712.js +0 -1
  645. package/.next/static/chunks/app/chat/page-83a2238ab453afaa.js +0 -1
  646. package/.next/static/chunks/app/layout-86574192bd3c0e6b.js +0 -1
  647. package/.next/static/chunks/app/manifest.webmanifest/route-973ec48531555712.js +0 -1
  648. package/.next/static/chunks/app/more/page-1619018cac999bbc.js +0 -1
  649. package/.next/static/chunks/app/page-a34d26812f085b6c.js +0 -1
  650. package/.next/static/chunks/app/proxy/[...path]/route-973ec48531555712.js +0 -1
  651. package/.next/static/chunks/app/repositories/page-202680fe6ec169c8.js +0 -1
  652. package/.next/static/chunks/app/review/page-b559bfb11c46931b.js +0 -1
  653. package/.next/static/chunks/app/sessions/page-3fa7e767d0ab3889.js +0 -1
  654. package/.next/static/chunks/app/skills/[skillId]/page-10d6f983e5f06ffb.js +0 -1
  655. package/.next/static/chunks/app/skills/installed/page-6641f95e6a6e5f9d.js +0 -1
  656. package/.next/static/chunks/app/skills/page-184f8e23e31a3667.js +0 -1
  657. package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-6041d3c3db326317.js +0 -1
  658. package/.next/static/chunks/app/worktrees/[id]/layout-973ec48531555712.js +0 -1
  659. package/.next/static/chunks/app/worktrees/[id]/page-966a451ae7b0903a.js +0 -1
  660. package/.next/static/css/d3453a6876553d32.css +0 -1
  661. package/.next/static/wH6K6QNPHSdATFkVoIcy3/_buildManifest.js +0 -1
  662. /package/.next/static/{wH6K6QNPHSdATFkVoIcy3 → smu4mnL7qMf8w38n9dQJE}/_ssgManifest.js +0 -0
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ /**
3
+ * The "still waiting" reminder setting (Issue #1790).
4
+ *
5
+ * A wait that nobody answers is the case push notifications exist for, and one
6
+ * notification is easy to miss — so after a threshold the server sends exactly
7
+ * one more. How long to wait, and whether to do it at all, is a user decision,
8
+ * and it is a *server-side* one: the check runs in the background with no
9
+ * request and no browser attached, so it cannot read a device's localStorage the
10
+ * way #1788's in-app toggle does. It is therefore stored once for the install
11
+ * and applies to every subscribed device.
12
+ *
13
+ * ## Why the SQL lives here
14
+ *
15
+ * `app_settings` (migration v27) is the generic key-value store this rides on,
16
+ * so no migration is added. Its typed helpers live in `db/app-settings-db`, but
17
+ * both existing ones are `string[]`-shaped and this value is an object with two
18
+ * fields of different types; a third helper there would be a fourth reader of
19
+ * the same table with no shared logic to gain. Keeping the accessor beside its
20
+ * only consumer also keeps the defaults — which the escalation tick applies on
21
+ * every failure path — in one file.
22
+ *
23
+ * Every read is total: a missing row, malformed JSON, an out-of-range threshold
24
+ * or an unopenable database all resolve to {@link DEFAULT_ESCALATION_SETTINGS}
25
+ * rather than throwing. The caller is a background timer whose failure mode
26
+ * must be "no reminder", never "the server logs an exception every minute".
27
+ *
28
+ * @module lib/push/escalation-settings
29
+ */
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.MAX_ESCALATION_THRESHOLD_MINUTES = exports.MIN_ESCALATION_THRESHOLD_MINUTES = exports.ESCALATION_THRESHOLD_CHOICES = exports.DEFAULT_ESCALATION_SETTINGS = exports.ESCALATION_SETTINGS_KEY = void 0;
32
+ exports.normalizeEscalationSettings = normalizeEscalationSettings;
33
+ exports.getPushEscalationSettings = getPushEscalationSettings;
34
+ exports.setPushEscalationSettings = setPushEscalationSettings;
35
+ const db_instance_1 = require("../../lib/db/db-instance");
36
+ const logger_1 = require("../../lib/logger");
37
+ const logger = (0, logger_1.createLogger)('push/escalation-settings');
38
+ /** `app_settings.key` this setting is stored under. */
39
+ exports.ESCALATION_SETTINGS_KEY = 'push_escalation';
40
+ /**
41
+ * On by default at ten minutes, per the Issue.
42
+ *
43
+ * Defaulting to *on* is the same call #1788 made for the in-app toast: a user
44
+ * who never opened the settings screen is the one most likely to walk away from
45
+ * a waiting agent, and the cost of being wrong is one extra notification per
46
+ * unanswered wait — bounded, because there is only ever one.
47
+ */
48
+ exports.DEFAULT_ESCALATION_SETTINGS = {
49
+ enabled: true,
50
+ thresholdMinutes: 10,
51
+ };
52
+ /** The thresholds the settings UI offers, in minutes. */
53
+ exports.ESCALATION_THRESHOLD_CHOICES = [5, 10, 30, 60];
54
+ /** Guard rails for a hand-written value: at least a minute, at most a day. */
55
+ exports.MIN_ESCALATION_THRESHOLD_MINUTES = 1;
56
+ exports.MAX_ESCALATION_THRESHOLD_MINUTES = 1440;
57
+ /**
58
+ * Narrow arbitrary input to a usable setting, filling each field independently.
59
+ *
60
+ * Field-by-field rather than all-or-nothing so that a bad threshold does not
61
+ * silently switch the reminder back on (or off): the half the user did set is
62
+ * the half that is honoured.
63
+ */
64
+ function normalizeEscalationSettings(value) {
65
+ if (typeof value !== 'object' || value === null)
66
+ return { ...exports.DEFAULT_ESCALATION_SETTINGS };
67
+ const record = value;
68
+ const enabled = typeof record.enabled === 'boolean' ? record.enabled : exports.DEFAULT_ESCALATION_SETTINGS.enabled;
69
+ const raw = record.thresholdMinutes;
70
+ const thresholdMinutes = typeof raw === 'number' &&
71
+ Number.isFinite(raw) &&
72
+ raw >= exports.MIN_ESCALATION_THRESHOLD_MINUTES &&
73
+ raw <= exports.MAX_ESCALATION_THRESHOLD_MINUTES
74
+ ? Math.round(raw)
75
+ : exports.DEFAULT_ESCALATION_SETTINGS.thresholdMinutes;
76
+ return { enabled, thresholdMinutes };
77
+ }
78
+ /** Read the setting. Never throws — see the module docblock. */
79
+ function getPushEscalationSettings() {
80
+ try {
81
+ const row = (0, db_instance_1.getDbInstance)()
82
+ .prepare('SELECT value FROM app_settings WHERE key = ?')
83
+ .get(exports.ESCALATION_SETTINGS_KEY);
84
+ if (!row)
85
+ return { ...exports.DEFAULT_ESCALATION_SETTINGS };
86
+ return normalizeEscalationSettings(JSON.parse(row.value));
87
+ }
88
+ catch (error) {
89
+ logger.warn('escalation-settings-read-failed', {
90
+ error: error instanceof Error ? error.message : String(error),
91
+ });
92
+ return { ...exports.DEFAULT_ESCALATION_SETTINGS };
93
+ }
94
+ }
95
+ /**
96
+ * Persist the setting, normalizing first so a malformed request cannot store a
97
+ * value later reads would have to reject anyway.
98
+ *
99
+ * @returns What was actually written.
100
+ */
101
+ function setPushEscalationSettings(value) {
102
+ const settings = normalizeEscalationSettings(value);
103
+ const now = Date.now();
104
+ (0, db_instance_1.getDbInstance)()
105
+ .prepare(`
106
+ INSERT INTO app_settings (key, value, created_at, updated_at)
107
+ VALUES (?, ?, ?, ?)
108
+ ON CONFLICT(key) DO UPDATE SET
109
+ value = excluded.value,
110
+ updated_at = excluded.updated_at
111
+ `)
112
+ .run(exports.ESCALATION_SETTINGS_KEY, JSON.stringify(settings), now, now);
113
+ return settings;
114
+ }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  /** Web Push module barrel (Issue #1125). */
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.DEFAULT_DEDUP_WINDOW_MS = exports.resetNotificationDedup = exports.shouldSendNotification = exports.resolvePushLocale = exports.buildExcerpt = exports.buildPushPayload = exports.notifyPushSubscribers = exports.getVapidPublicKey = exports.isPushConfigured = exports.getVapidConfig = void 0;
4
+ exports.MAX_ESCALATION_THRESHOLD_MINUTES = exports.MIN_ESCALATION_THRESHOLD_MINUTES = exports.ESCALATION_SETTINGS_KEY = exports.ESCALATION_THRESHOLD_CHOICES = exports.DEFAULT_ESCALATION_SETTINGS = exports.normalizeEscalationSettings = exports.setPushEscalationSettings = exports.getPushEscalationSettings = exports.ESCALATION_TICK_MS = exports.pendingEscalationCount = exports.runEscalationTick = exports.handleWaitingTransition = exports.isWaitingPushNotifierActive = exports.stopWaitingPushNotifier = exports.startWaitingPushNotifier = exports.resetWaitingPushDedup = exports.shouldSendWaitingPush = exports.DEFAULT_DEDUP_WINDOW_MS = exports.resetNotificationDedup = exports.shouldSendNotification = exports.resolvePushLocale = exports.buildExcerpt = exports.buildPushPayload = exports.notifyPushSubscribers = exports.getVapidPublicKey = exports.isPushConfigured = exports.getVapidConfig = void 0;
5
5
  var vapid_1 = require("./vapid");
6
6
  Object.defineProperty(exports, "getVapidConfig", { enumerable: true, get: function () { return vapid_1.getVapidConfig; } });
7
7
  Object.defineProperty(exports, "isPushConfigured", { enumerable: true, get: function () { return vapid_1.isPushConfigured; } });
@@ -15,3 +15,23 @@ var notification_dedup_1 = require("./notification-dedup");
15
15
  Object.defineProperty(exports, "shouldSendNotification", { enumerable: true, get: function () { return notification_dedup_1.shouldSendNotification; } });
16
16
  Object.defineProperty(exports, "resetNotificationDedup", { enumerable: true, get: function () { return notification_dedup_1.resetNotificationDedup; } });
17
17
  Object.defineProperty(exports, "DEFAULT_DEDUP_WINDOW_MS", { enumerable: true, get: function () { return notification_dedup_1.DEFAULT_DEDUP_WINDOW_MS; } });
18
+ Object.defineProperty(exports, "shouldSendWaitingPush", { enumerable: true, get: function () { return notification_dedup_1.shouldSendWaitingPush; } });
19
+ Object.defineProperty(exports, "resetWaitingPushDedup", { enumerable: true, get: function () { return notification_dedup_1.resetWaitingPushDedup; } });
20
+ // Waiting-edge driven notifications (Issue #1790).
21
+ var waiting_push_notifier_1 = require("./waiting-push-notifier");
22
+ Object.defineProperty(exports, "startWaitingPushNotifier", { enumerable: true, get: function () { return waiting_push_notifier_1.startWaitingPushNotifier; } });
23
+ Object.defineProperty(exports, "stopWaitingPushNotifier", { enumerable: true, get: function () { return waiting_push_notifier_1.stopWaitingPushNotifier; } });
24
+ Object.defineProperty(exports, "isWaitingPushNotifierActive", { enumerable: true, get: function () { return waiting_push_notifier_1.isWaitingPushNotifierActive; } });
25
+ Object.defineProperty(exports, "handleWaitingTransition", { enumerable: true, get: function () { return waiting_push_notifier_1.handleWaitingTransition; } });
26
+ Object.defineProperty(exports, "runEscalationTick", { enumerable: true, get: function () { return waiting_push_notifier_1.runEscalationTick; } });
27
+ Object.defineProperty(exports, "pendingEscalationCount", { enumerable: true, get: function () { return waiting_push_notifier_1.pendingEscalationCount; } });
28
+ Object.defineProperty(exports, "ESCALATION_TICK_MS", { enumerable: true, get: function () { return waiting_push_notifier_1.ESCALATION_TICK_MS; } });
29
+ var escalation_settings_1 = require("./escalation-settings");
30
+ Object.defineProperty(exports, "getPushEscalationSettings", { enumerable: true, get: function () { return escalation_settings_1.getPushEscalationSettings; } });
31
+ Object.defineProperty(exports, "setPushEscalationSettings", { enumerable: true, get: function () { return escalation_settings_1.setPushEscalationSettings; } });
32
+ Object.defineProperty(exports, "normalizeEscalationSettings", { enumerable: true, get: function () { return escalation_settings_1.normalizeEscalationSettings; } });
33
+ Object.defineProperty(exports, "DEFAULT_ESCALATION_SETTINGS", { enumerable: true, get: function () { return escalation_settings_1.DEFAULT_ESCALATION_SETTINGS; } });
34
+ Object.defineProperty(exports, "ESCALATION_THRESHOLD_CHOICES", { enumerable: true, get: function () { return escalation_settings_1.ESCALATION_THRESHOLD_CHOICES; } });
35
+ Object.defineProperty(exports, "ESCALATION_SETTINGS_KEY", { enumerable: true, get: function () { return escalation_settings_1.ESCALATION_SETTINGS_KEY; } });
36
+ Object.defineProperty(exports, "MIN_ESCALATION_THRESHOLD_MINUTES", { enumerable: true, get: function () { return escalation_settings_1.MIN_ESCALATION_THRESHOLD_MINUTES; } });
37
+ Object.defineProperty(exports, "MAX_ESCALATION_THRESHOLD_MINUTES", { enumerable: true, get: function () { return escalation_settings_1.MAX_ESCALATION_THRESHOLD_MINUTES; } });
@@ -15,6 +15,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.DEFAULT_DEDUP_WINDOW_MS = void 0;
16
16
  exports.shouldSendNotification = shouldSendNotification;
17
17
  exports.resetNotificationDedup = resetNotificationDedup;
18
+ exports.shouldSendWaitingPush = shouldSendWaitingPush;
19
+ exports.resetWaitingPushDedup = resetWaitingPushDedup;
18
20
  const crypto_1 = require("crypto");
19
21
  /** Default suppression window: repeats of identical content within this are dropped. */
20
22
  exports.DEFAULT_DEDUP_WINDOW_MS = 30_000;
@@ -40,3 +42,36 @@ function shouldSendNotification(event, now = Date.now(), windowMs = exports.DEFA
40
42
  function resetNotificationDedup() {
41
43
  lastSent.clear();
42
44
  }
45
+ const waitingSent = globalThis.__waitingPushDedup ??
46
+ (globalThis.__waitingPushDedup = new Map());
47
+ /**
48
+ * Whether this waiting notification should be sent, recording it if so.
49
+ *
50
+ * Replaces the content hash for the waiting path (Issue #1790). Content was
51
+ * never the right key here: two identical `Do you want to proceed?` prompts
52
+ * seconds apart are two separate waits a human has to answer twice, and the
53
+ * 30 s window dropped the second one — while a single wait that outlives the
54
+ * window could be notified again for the same question. The episode's `since`
55
+ * is the wait's identity, so "one notification per wait" becomes exact:
56
+ *
57
+ * - first notification of an episode → sent, recorded;
58
+ * - any repeat for the same `since` → suppressed, however it arrived (the
59
+ * poller and the edge listener both report the same wait);
60
+ * - the escalation → allowed exactly once per episode;
61
+ * - a new episode (the wait ended and another began) → sent again, even if the
62
+ * prompt text and the elapsed time are identical.
63
+ */
64
+ function shouldSendWaitingPush(event) {
65
+ const key = `${event.worktreeId}::${event.instanceId}`;
66
+ const escalated = event.escalated === true;
67
+ const prev = waitingSent.get(key);
68
+ if (prev && prev.since === event.since && (prev.escalated || !escalated)) {
69
+ return false;
70
+ }
71
+ waitingSent.set(key, { since: event.since, escalated });
72
+ return true;
73
+ }
74
+ /** Clear the episode-scoped state (for tests). */
75
+ function resetWaitingPushDedup() {
76
+ waitingSent.clear();
77
+ }
@@ -64,6 +64,36 @@ function buildExcerpt(text, maxLength = MAX_EXCERPT_LENGTH) {
64
64
  return collapsed;
65
65
  return collapsed.slice(0, maxLength - 1).trimEnd() + '…';
66
66
  }
67
+ /**
68
+ * Whether this wait can only be dealt with at the terminal (Issue #1790).
69
+ *
70
+ * A `menu` (selection list / pager) and an `unclassified` wait share the one
71
+ * fact the reader acts on: tapping the notification will not present anything
72
+ * to answer. `prompt` — and an absent kind, which is every pre-#1790 caller —
73
+ * keeps the original "waiting for your reply" wording.
74
+ */
75
+ function needsTerminal(waitingKind) {
76
+ return waitingKind === 'menu' || waitingKind === 'unclassified';
77
+ }
78
+ /** The body for a waiting notification, in the reader's language. */
79
+ function buildWaitingBody(event, messages, excerpt, now) {
80
+ const terminal = needsTerminal(event.waitingKind);
81
+ if (event.escalated) {
82
+ // The excerpt is dropped on purpose: after ten minutes the question is no
83
+ // longer news, the elapsed time is.
84
+ const elapsedMs = now - (event.waitingSince ?? now);
85
+ const minutes = String(Math.max(1, Math.floor(elapsedMs / 60_000)));
86
+ return (terminal ? messages.stillWaitingTerminal : messages.stillWaitingPrompt).replace('{minutes}', minutes);
87
+ }
88
+ if (terminal) {
89
+ return excerpt
90
+ ? messages.terminalAttentionWithExcerpt.replace('{excerpt}', excerpt)
91
+ : messages.terminalAttention;
92
+ }
93
+ return excerpt
94
+ ? messages.promptWaitingWithExcerpt.replace('{excerpt}', excerpt)
95
+ : messages.promptWaiting;
96
+ }
67
97
  /** Build the minimal notification payload for an event, in the reader's language. */
68
98
  function buildPushPayload(event, locale = i18n_config_1.DEFAULT_LOCALE, now = Date.now()) {
69
99
  const excerpt = buildExcerpt(event.excerpt);
@@ -71,9 +101,7 @@ function buildPushPayload(event, locale = i18n_config_1.DEFAULT_LOCALE, now = Da
71
101
  const title = `${event.worktreeName}${agentSuffix}`;
72
102
  const messages = PUSH_MESSAGES[resolvePushLocale(locale)];
73
103
  const body = event.kind === 'prompt'
74
- ? excerpt
75
- ? messages.promptWaitingWithExcerpt.replace('{excerpt}', excerpt)
76
- : messages.promptWaiting
104
+ ? buildWaitingBody(event, messages, excerpt, now)
77
105
  : excerpt
78
106
  ? messages.completionWithExcerpt.replace('{excerpt}', excerpt)
79
107
  : messages.completion;
@@ -83,8 +111,12 @@ function buildPushPayload(event, locale = i18n_config_1.DEFAULT_LOCALE, now = Da
83
111
  body,
84
112
  worktreeId: event.worktreeId,
85
113
  url: `/worktrees/${event.worktreeId}`,
114
+ // Unchanged by #1790, and deliberately: the escalation carries the same tag
115
+ // as the notification it follows up, so the Service Worker replaces the
116
+ // stale one instead of stacking a second card for the same wait.
86
117
  tag: `${event.worktreeId}:${event.kind}`,
87
118
  timestamp: now,
119
+ ...(event.waitingKind ? { waitingKind: event.waitingKind } : {}),
88
120
  };
89
121
  }
90
122
  async function sendToOne(sub, payload) {
@@ -102,19 +134,46 @@ async function sendToOne(sub, payload) {
102
134
  logger.warn('push-send-failed', { statusCode: statusCode ?? 'unknown' });
103
135
  }
104
136
  }
137
+ /**
138
+ * Which guard applies to this event (Issue #1790).
139
+ *
140
+ * An episode-scoped waiting notification is deduped by the wait it belongs to;
141
+ * everything else — every completion, and any prompt event that predates the
142
+ * episode store — keeps the content hash and its 30 s window. Both record as
143
+ * they decide, so this must be called exactly once per event.
144
+ */
145
+ function passesDedup(event) {
146
+ if (event.kind === 'prompt' && typeof event.waitingSince === 'number') {
147
+ return (0, notification_dedup_1.shouldSendWaitingPush)({
148
+ worktreeId: event.worktreeId,
149
+ instanceId: event.instanceId ?? event.agentName ?? '',
150
+ since: event.waitingSince,
151
+ escalated: event.escalated,
152
+ });
153
+ }
154
+ return (0, notification_dedup_1.shouldSendNotification)({
155
+ worktreeId: event.worktreeId,
156
+ kind: event.kind,
157
+ content: event.excerpt,
158
+ });
159
+ }
105
160
  /**
106
161
  * Fan out a notification to all subscriptions opted into this event's kind.
107
162
  * Never throws — push is advisory and must not disrupt the poller. No-op when
108
163
  * push is unconfigured, deduped, or there are no matching subscriptions.
164
+ *
165
+ * `now` is injectable because the escalation body quotes how long the wait has
166
+ * lasted (Issue #1790): the reminder is raised from a periodic check that knows
167
+ * the tick's time, and reading the clock again here would report a different
168
+ * elapsed time from the one that decided to send.
109
169
  */
110
- async function notifyPushSubscribers(event) {
170
+ async function notifyPushSubscribers(event, now = Date.now()) {
111
171
  try {
112
172
  const config = (0, vapid_1.getVapidConfig)();
113
173
  if (!config)
114
174
  return;
115
- if (!(0, notification_dedup_1.shouldSendNotification)({ worktreeId: event.worktreeId, kind: event.kind, content: event.excerpt })) {
175
+ if (!passesDedup(event))
116
176
  return;
117
- }
118
177
  const db = (0, db_instance_1.getDbInstance)();
119
178
  const subscriptions = (0, push_subscriptions_db_1.getPushSubscriptionsForKind)(db, event.kind);
120
179
  if (subscriptions.length === 0)
@@ -132,7 +191,7 @@ async function notifyPushSubscribers(event) {
132
191
  byLocale.set(locale, [sub]);
133
192
  }
134
193
  await Promise.all(Array.from(byLocale, ([locale, subs]) => {
135
- const payload = JSON.stringify(buildPushPayload(event, locale));
194
+ const payload = JSON.stringify(buildPushPayload(event, locale, now));
136
195
  return Promise.all(subs.map((sub) => sendToOne(sub, payload)));
137
196
  }));
138
197
  }
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ /**
3
+ * Send a push notification when an agent starts waiting, and one reminder if it
4
+ * is still waiting later (Issue #1790).
5
+ *
6
+ * ## Why this subscribes rather than detects
7
+ *
8
+ * The prompt notification used to be raised from one line inside the response
9
+ * poller, which made it inherit every one of that poller's boundaries: it only
10
+ * runs when a send-family API or Auto-Yes started it, it stops itself on the
11
+ * first prompt of a turn, it gives up after `MAX_POLLING_DURATION`, and it can
12
+ * only see waits the screen scraper classified as `isPrompt`. A wait that began
13
+ * after a `tmux` keystroke, a second prompt in the same turn, a wait that only
14
+ * the agent's own hook events reported, and a selection list were all silently
15
+ * unnotifiable.
16
+ *
17
+ * #1786 made the waiting edge observable exactly once, in
18
+ * `waiting-episode-state`, and #1788 already subscribes to it for the WebSocket
19
+ * frame. This module is the same subscription for push — it captures no pane,
20
+ * runs no detector, and keeps no "was it waiting last time?" of its own.
21
+ *
22
+ * ## The poller still notifies, and that is deliberate
23
+ *
24
+ * Contrary to the Issue's premise, the edge is *not* observed by a background
25
+ * process: `observeWaitingEdge`'s only caller is `worktree-status-helper`, on
26
+ * the worktree list / detail API probe. So the edge fires when a client is
27
+ * looking, and moving push onto it *alone* would have swapped one blind spot
28
+ * (no poller) for a worse one (nobody has the app open — the very situation a
29
+ * phone notification is for). The poller therefore keeps its call, and
30
+ * `response-checker` opens the same episode through `observeWaitingEdge` so both
31
+ * producers name the wait identically; `shouldSendWaitingPush` then collapses
32
+ * them to one notification. See the commit message for the measurement.
33
+ *
34
+ * ## Escalation
35
+ *
36
+ * There is no existing server-side sweep over waiting sessions to ride on, so
37
+ * this keeps a small interval of its own. It exists only while some wait is
38
+ * outstanding — created on the first open episode, cleared when the last one
39
+ * closes — so an install with nothing waiting has no timer, and one that never
40
+ * configured VAPID never even gets that far.
41
+ *
42
+ * Everything here is advisory: a failure must not disturb the status read that
43
+ * observed the edge (`emit` contains listener throws) nor the poller.
44
+ *
45
+ * @module lib/push/waiting-push-notifier
46
+ */
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.ESCALATION_TICK_MS = void 0;
49
+ exports.handleWaitingTransition = handleWaitingTransition;
50
+ exports.runEscalationTick = runEscalationTick;
51
+ exports.startWaitingPushNotifier = startWaitingPushNotifier;
52
+ exports.stopWaitingPushNotifier = stopWaitingPushNotifier;
53
+ exports.isWaitingPushNotifierActive = isWaitingPushNotifierActive;
54
+ exports.pendingEscalationCount = pendingEscalationCount;
55
+ const auto_yes_state_1 = require("../../lib/auto-yes-state");
56
+ const db_instance_1 = require("../../lib/db/db-instance");
57
+ const worktree_db_1 = require("../../lib/db/worktree-db");
58
+ const logger_1 = require("../../lib/logger");
59
+ const waiting_episode_state_1 = require("../../lib/session/waiting-episode-state");
60
+ const escalation_settings_1 = require("./escalation-settings");
61
+ const push_sender_1 = require("./push-sender");
62
+ const vapid_1 = require("./vapid");
63
+ const logger = (0, logger_1.createLogger)('push/waiting-notifier');
64
+ /** How often outstanding waits are re-checked. Minute granularity is enough. */
65
+ exports.ESCALATION_TICK_MS = 60_000;
66
+ const pending = globalThis.__waitingPushPending ??
67
+ (globalThis.__waitingPushPending = new Map());
68
+ /**
69
+ * The worktree's display name, for the notification title.
70
+ *
71
+ * Falls back to the id rather than dropping the notification: a database that
72
+ * cannot answer is a reason to send a less readable title, not a reason to
73
+ * leave the user waiting in silence.
74
+ */
75
+ function resolveWorktreeName(worktreeId) {
76
+ try {
77
+ return (0, worktree_db_1.getWorktreeById)((0, db_instance_1.getDbInstance)(), worktreeId)?.name ?? worktreeId;
78
+ }
79
+ catch {
80
+ return worktreeId;
81
+ }
82
+ }
83
+ /** Fan one waiting notification out. Never throws. */
84
+ async function sendWaitingPush(wait, escalated, now) {
85
+ const instanceId = wait.instanceId ?? wait.cliToolId;
86
+ try {
87
+ await (0, push_sender_1.notifyPushSubscribers)({
88
+ worktreeId: wait.worktreeId,
89
+ worktreeName: resolveWorktreeName(wait.worktreeId),
90
+ kind: 'prompt',
91
+ agentName: instanceId,
92
+ instanceId,
93
+ waitingKind: wait.kind,
94
+ waitingSince: wait.since,
95
+ escalated,
96
+ },
97
+ // The deciding tick's clock, not a fresh reading: the reminder's body
98
+ // quotes the elapsed time this call was made on.
99
+ now);
100
+ }
101
+ catch (error) {
102
+ logger.warn('waiting-push-failed', {
103
+ worktreeId: wait.worktreeId,
104
+ instanceId,
105
+ escalated,
106
+ error: error instanceof Error ? error.message : String(error),
107
+ });
108
+ }
109
+ }
110
+ function startEscalationTimer() {
111
+ if (globalThis.__waitingPushEscalationTimer !== undefined)
112
+ return;
113
+ const timer = setInterval(() => {
114
+ runEscalationTick();
115
+ }, exports.ESCALATION_TICK_MS);
116
+ // Never hold the process open for a reminder; the server exiting is a far
117
+ // stronger signal than "someone might still be waiting".
118
+ timer.unref?.();
119
+ globalThis.__waitingPushEscalationTimer = timer;
120
+ }
121
+ function stopEscalationTimerIfIdle() {
122
+ if (pending.size > 0)
123
+ return;
124
+ const timer = globalThis.__waitingPushEscalationTimer;
125
+ if (timer !== undefined) {
126
+ clearInterval(timer);
127
+ globalThis.__waitingPushEscalationTimer = undefined;
128
+ }
129
+ }
130
+ /**
131
+ * Handle one crossing of the waiting edge.
132
+ *
133
+ * Exported for tests, which drive it directly rather than through the
134
+ * subscription so a failure points at this function and not at #1786's store.
135
+ */
136
+ function handleWaitingTransition(transition) {
137
+ // Nothing downstream can do anything without VAPID keys, so an install
138
+ // without push does not track waits, does not read the database and does not
139
+ // start a timer — it is inert rather than merely quiet.
140
+ if (!(0, vapid_1.isPushConfigured)())
141
+ return;
142
+ const key = (0, auto_yes_state_1.buildCompositeKey)(transition.worktreeId, transition.cliToolId, transition.instanceId);
143
+ if (!transition.waiting || transition.since === null) {
144
+ pending.delete(key);
145
+ stopEscalationTimerIfIdle();
146
+ return;
147
+ }
148
+ const wait = {
149
+ worktreeId: transition.worktreeId,
150
+ cliToolId: transition.cliToolId,
151
+ instanceId: transition.instanceId,
152
+ since: transition.since,
153
+ kind: transition.kind,
154
+ };
155
+ pending.set(key, wait);
156
+ startEscalationTimer();
157
+ void sendWaitingPush(wait, false, transition.at);
158
+ }
159
+ /**
160
+ * Re-notify every wait that has outlived the threshold, once each.
161
+ *
162
+ * Exported so tests can advance a fake clock instead of a real minute.
163
+ */
164
+ function runEscalationTick(now = Date.now()) {
165
+ if (pending.size === 0) {
166
+ stopEscalationTimerIfIdle();
167
+ return;
168
+ }
169
+ const settings = (0, escalation_settings_1.getPushEscalationSettings)();
170
+ const thresholdMs = settings.thresholdMinutes * 60_000;
171
+ for (const [key, wait] of Array.from(pending)) {
172
+ // The episode store, not this map, is the authority on whether the wait is
173
+ // still going: it is written by the status probe, so an answer given in
174
+ // another tab — or a wait whose closing edge this module never saw — is
175
+ // caught here even when `pending` still lists it.
176
+ const episode = (0, waiting_episode_state_1.getWaitingEpisode)(wait.worktreeId, wait.cliToolId, wait.instanceId);
177
+ if (episode === null || episode.since !== wait.since) {
178
+ pending.delete(key);
179
+ continue;
180
+ }
181
+ if (!settings.enabled)
182
+ continue;
183
+ if (now - wait.since < thresholdMs)
184
+ continue;
185
+ // Dropped before sending, not after: the reminder is once per episode, and
186
+ // an in-flight fan-out must not be able to earn a second one.
187
+ pending.delete(key);
188
+ void sendWaitingPush({ ...wait, kind: episode.kind ?? wait.kind }, true, now);
189
+ }
190
+ stopEscalationTimerIfIdle();
191
+ }
192
+ /**
193
+ * Subscribe to the waiting edge.
194
+ *
195
+ * Idempotent by replacement, like #1788's broadcast: calling it again drops the
196
+ * previous subscription rather than adding a second one, so a module evaluated
197
+ * twice cannot double-notify.
198
+ *
199
+ * @returns The unsubscribe function (also reachable as
200
+ * {@link stopWaitingPushNotifier}).
201
+ */
202
+ function startWaitingPushNotifier() {
203
+ stopWaitingPushNotifier();
204
+ const unsubscribe = (0, waiting_episode_state_1.onWaitingTransition)((transition) => {
205
+ handleWaitingTransition(transition);
206
+ });
207
+ globalThis.__waitingPushUnsubscribe = unsubscribe;
208
+ return unsubscribe;
209
+ }
210
+ /**
211
+ * Drop the subscription, the outstanding waits and the timer. Safe when none is
212
+ * active, and the seam a test uses to leave no interval behind (CI runs the
213
+ * whole suite in one process).
214
+ */
215
+ function stopWaitingPushNotifier() {
216
+ const existing = globalThis.__waitingPushUnsubscribe;
217
+ if (existing) {
218
+ existing();
219
+ globalThis.__waitingPushUnsubscribe = undefined;
220
+ }
221
+ pending.clear();
222
+ stopEscalationTimerIfIdle();
223
+ }
224
+ /** Whether a subscription is currently active. Test seam. */
225
+ function isWaitingPushNotifierActive() {
226
+ return globalThis.__waitingPushUnsubscribe !== undefined;
227
+ }
228
+ /** How many waits are awaiting their reminder. Test seam. */
229
+ function pendingEscalationCount() {
230
+ return pending.size;
231
+ }
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ /**
3
+ * Push the waiting edge to every subscriber of a worktree room (Issue #1788).
4
+ *
5
+ * ## Why this file exists rather than a detector
6
+ *
7
+ * Issue #1786 made the false→true / true→false crossing observable exactly once,
8
+ * in `waiting-episode-state`, and handed out `onWaitingTransition` for the
9
+ * surfaces that need the instant rather than the level. This module is that
10
+ * subscription and nothing more: it translates a {@link WaitingTransition} into
11
+ * a {@link SessionStatusEvent} and publishes it. It does not capture a pane, does
12
+ * not read the structured events, and does not keep a "was it waiting last
13
+ * time?" of its own — three surfaces each keeping their own answer to that is
14
+ * precisely what #1786 exists to prevent.
15
+ *
16
+ * Because it subscribes to the edge and not to the response poller, a wait that
17
+ * only the agent's own hook events could see (#1725) broadcasts exactly like one
18
+ * the screen scraper read, and a wait that lasts twenty minutes broadcasts once.
19
+ *
20
+ * ## Why `publish` is injected
21
+ *
22
+ * `ws-server` owns the rooms and starts this subscription from
23
+ * `setupWebSocket`, so importing `broadcast` here would close an import cycle
24
+ * (ws-server → waiting-broadcast → ws-server). Taking the publisher as an
25
+ * argument also makes the translation testable without standing up a server.
26
+ *
27
+ * ## Authorization
28
+ *
29
+ * None is bypassed. The publisher is the room broadcaster, and a socket only
30
+ * joins a room through the authenticated `subscribe` path (#331/#332): a client
31
+ * that never subscribed to a worktree still never hears about it.
32
+ *
33
+ * @module lib/realtime/waiting-broadcast
34
+ */
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.buildWaitingStatusEvent = buildWaitingStatusEvent;
37
+ exports.startWaitingStatusBroadcast = startWaitingStatusBroadcast;
38
+ exports.stopWaitingStatusBroadcast = stopWaitingStatusBroadcast;
39
+ exports.isWaitingStatusBroadcastActive = isWaitingStatusBroadcastActive;
40
+ const waiting_episode_state_1 = require("../../lib/session/waiting-episode-state");
41
+ /**
42
+ * Translate a waiting crossing into the frame clients receive.
43
+ *
44
+ * `isRunning` is deliberately omitted — see the field's doc on
45
+ * {@link SessionStatusEvent}. `instance` is normalized to the instance id the
46
+ * per-instance status map is keyed by (the CLI tool id for the primary), so a
47
+ * client can look the entry up without re-deriving the convention.
48
+ */
49
+ function buildWaitingStatusEvent(transition) {
50
+ return {
51
+ type: 'session_status_changed',
52
+ worktreeId: transition.worktreeId,
53
+ cliTool: transition.cliToolId,
54
+ instance: transition.instanceId ?? transition.cliToolId,
55
+ isWaitingForResponse: transition.waiting,
56
+ waitingKind: transition.kind ?? null,
57
+ waitingSince: transition.since,
58
+ };
59
+ }
60
+ /**
61
+ * Subscribe to the waiting edge and publish it to the worktree's room.
62
+ *
63
+ * Idempotent: calling it again replaces the previous subscription rather than
64
+ * adding a second one, so a re-entered `setupWebSocket` cannot double-send.
65
+ *
66
+ * @param publish - Room broadcaster, normally `ws-server`'s internal one.
67
+ * @returns The unsubscribe function (also reachable as
68
+ * {@link stopWaitingStatusBroadcast}).
69
+ */
70
+ function startWaitingStatusBroadcast(publish) {
71
+ stopWaitingStatusBroadcast();
72
+ const unsubscribe = (0, waiting_episode_state_1.onWaitingTransition)((transition) => {
73
+ publish(transition.worktreeId, buildWaitingStatusEvent(transition));
74
+ });
75
+ globalThis.__waitingStatusBroadcastUnsubscribe = unsubscribe;
76
+ return unsubscribe;
77
+ }
78
+ /**
79
+ * Drop the subscription, if any. Safe to call when none is active — and called
80
+ * from `closeWebSocket`, so a suite that stands a server up and tears it down
81
+ * does not leave a listener pointed at a dead room map.
82
+ */
83
+ function stopWaitingStatusBroadcast() {
84
+ const existing = globalThis.__waitingStatusBroadcastUnsubscribe;
85
+ if (existing) {
86
+ existing();
87
+ globalThis.__waitingStatusBroadcastUnsubscribe = undefined;
88
+ }
89
+ }
90
+ /** Whether a subscription is currently active. Test seam. */
91
+ function isWaitingStatusBroadcastActive() {
92
+ return globalThis.__waitingStatusBroadcastUnsubscribe !== undefined;
93
+ }