commandmate 0.30.2 → 0.31.1

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 (442) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +151 -151
  3. package/.next/app-path-routes-manifest.json +25 -25
  4. package/.next/build-manifest.json +2 -2
  5. package/.next/prerender-manifest.json +9 -9
  6. package/.next/required-server-files.json +1 -1
  7. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  8. package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  11. package/.next/server/app/api/app/update-check/route.js +1 -1
  12. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  13. package/.next/server/app/api/assistant/conversation/route.js +1 -1
  14. package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
  15. package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/assistant/current-output/route.js +1 -1
  17. package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
  18. package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
  19. package/.next/server/app/api/assistant/messages/route.js +1 -1
  20. package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
  21. package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
  22. package/.next/server/app/api/assistant/session/route.js +1 -1
  23. package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
  24. package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/assistant/start/route.js +3 -3
  26. package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
  27. package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
  28. package/.next/server/app/api/assistant/terminal/route.js +4 -4
  29. package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
  30. package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
  31. package/.next/server/app/api/assistant/tools/route.js +1 -1
  32. package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
  33. package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/capabilities/route.js +1 -1
  38. package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  41. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  46. package/.next/server/app/api/hooks/agent-event/route.js +1 -1
  47. package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
  48. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  49. package/.next/server/app/api/hooks/claude-done/route.js +1 -1
  50. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
  51. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  52. package/.next/server/app/api/hooks/permission-request/route.js +1 -1
  53. package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
  54. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  55. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  58. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  60. package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
  61. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  63. package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
  64. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
  65. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
  66. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  67. package/.next/server/app/api/repositories/clone/route.js +1 -1
  68. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
  69. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  70. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  71. package/.next/server/app/api/repositories/restore/route.js +1 -1
  72. package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
  73. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  74. package/.next/server/app/api/repositories/route.js +1 -1
  75. package/.next/server/app/api/repositories/route.js.nft.json +1 -1
  76. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/repositories/scan/route.js +1 -1
  78. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
  79. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/repositories/sync/route.js +1 -1
  81. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
  82. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  83. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/settings/default-agents/route.js +1 -1
  85. package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
  86. package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
  88. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  89. package/.next/server/app/api/skills/[id]/route.js +1 -1
  90. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  94. package/.next/server/app/api/skills/route.js +1 -1
  95. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/slash-commands/route.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_client-reference-manifest.js +1 -1
  100. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  104. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
  107. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
  110. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
  113. package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
  119. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  134. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  135. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  136. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  137. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  138. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  139. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  140. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  142. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  143. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  144. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  145. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  146. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  147. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  148. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
  150. package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
  151. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
  152. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
  153. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  154. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
  155. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
  156. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  157. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  158. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  159. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  160. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  161. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  162. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  163. package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
  164. package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
  165. package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
  166. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
  167. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
  168. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  169. package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
  170. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
  171. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
  172. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  173. package/.next/server/app/api/worktrees/[id]/route.js +1 -1
  174. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
  175. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  176. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +4 -3
  177. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  178. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  179. package/.next/server/app/api/worktrees/[id]/schedules/route.js +4 -3
  180. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  181. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  182. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
  183. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
  184. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  185. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +2 -2
  186. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
  187. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  188. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  189. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  190. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  191. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  192. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  193. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  194. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  195. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
  196. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  197. package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
  198. package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
  199. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  200. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  201. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
  202. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
  203. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  204. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  205. package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
  206. package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
  207. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  208. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  209. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  210. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  211. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  212. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  213. package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
  214. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  215. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
  216. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  217. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  218. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  219. package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
  220. package/.next/server/app/api/worktrees/route.js +1 -1
  221. package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
  222. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  223. package/.next/server/app/chat/page.js +2 -2
  224. package/.next/server/app/chat/page.js.nft.json +1 -1
  225. package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  226. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  227. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  228. package/.next/server/app/more/page.js +2 -2
  229. package/.next/server/app/more/page.js.nft.json +1 -1
  230. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  231. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  232. package/.next/server/app/page.js +1 -1
  233. package/.next/server/app/page.js.nft.json +1 -1
  234. package/.next/server/app/page_client-reference-manifest.js +1 -1
  235. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  236. package/.next/server/app/repositories/page.js +2 -2
  237. package/.next/server/app/repositories/page.js.nft.json +1 -1
  238. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  239. package/.next/server/app/review/page.js +1 -1
  240. package/.next/server/app/review/page.js.nft.json +1 -1
  241. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  242. package/.next/server/app/sessions/page.js +1 -1
  243. package/.next/server/app/sessions/page.js.nft.json +1 -1
  244. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  245. package/.next/server/app/skills/[skillId]/page.js +2 -2
  246. package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
  247. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  248. package/.next/server/app/skills/installed/page.js +2 -2
  249. package/.next/server/app/skills/installed/page.js.nft.json +1 -1
  250. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  251. package/.next/server/app/skills/page.js +1 -1
  252. package/.next/server/app/skills/page.js.nft.json +1 -1
  253. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  254. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  255. package/.next/server/app/worktrees/[id]/page.js +11 -11
  256. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  257. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  258. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  259. package/.next/server/app-paths-manifest.json +25 -25
  260. package/.next/server/chunks/1058.js +1 -1
  261. package/.next/server/chunks/1068.js +1 -1
  262. package/.next/server/chunks/1262.js +1 -1
  263. package/.next/server/chunks/1886.js +3 -3
  264. package/.next/server/chunks/1990.js +103 -0
  265. package/.next/server/chunks/2119.js +1 -1
  266. package/.next/server/chunks/2328.js +1 -1
  267. package/.next/server/chunks/2404.js +1 -1
  268. package/.next/server/chunks/2445.js +1 -1
  269. package/.next/server/chunks/261.js +1 -1
  270. package/.next/server/chunks/3123.js +1 -1
  271. package/.next/server/chunks/3241.js +1 -1
  272. package/.next/server/chunks/3480.js +5 -4
  273. package/.next/server/chunks/4299.js +1 -1
  274. package/.next/server/chunks/4393.js +1 -1
  275. package/.next/server/chunks/4443.js +1 -5
  276. package/.next/server/chunks/4802.js +1 -0
  277. package/.next/server/chunks/5017.js +1 -1
  278. package/.next/server/chunks/5043.js +1 -1
  279. package/.next/server/chunks/5164.js +1 -1
  280. package/.next/server/chunks/552.js +2 -2
  281. package/.next/server/chunks/6072.js +1 -1
  282. package/.next/server/chunks/6130.js +1 -1
  283. package/.next/server/chunks/663.js +4 -3
  284. package/.next/server/chunks/6894.js +2 -2
  285. package/.next/server/chunks/7187.js +1 -0
  286. package/.next/server/chunks/7472.js +1 -1
  287. package/.next/server/chunks/{880.js → 7859.js} +6 -6
  288. package/.next/server/chunks/7905.js +1 -1
  289. package/.next/server/chunks/8800.js +2 -2
  290. package/.next/server/chunks/8918.js +7 -0
  291. package/.next/server/chunks/9123.js +2 -2
  292. package/.next/server/chunks/9130.js +4 -4
  293. package/.next/server/chunks/9627.js +1 -1
  294. package/.next/server/chunks/9696.js +1 -1
  295. package/.next/server/chunks/9798.js +1 -1
  296. package/.next/server/middleware-manifest.json +5 -5
  297. package/.next/server/pages/500.html +1 -1
  298. package/.next/server/pages-manifest.json +1 -1
  299. package/.next/server/server-reference-manifest.json +1 -1
  300. package/.next/static/chunks/1783-11c9b4d8a52ebd91.js +1 -0
  301. package/.next/static/chunks/4718-46e1d2f07c8423ba.js +1 -0
  302. package/.next/static/chunks/6022-2fa0b5a82d4ce7b6.js +1 -0
  303. package/.next/static/chunks/{5229-6c89475b61bd2c8b.js → 6170-951b9f5fe6b4b3b5.js} +1 -1
  304. package/.next/static/chunks/app/chat/{page-9aa2011410895b0d.js → page-37d7615d17d7e2a0.js} +1 -1
  305. package/.next/static/chunks/app/layout-4c2f21e3f653ee4c.js +1 -0
  306. package/.next/static/chunks/app/more/{page-333bba1c8bbc9c11.js → page-353a3924e6d7968e.js} +1 -1
  307. package/.next/static/chunks/app/{page-214f7ffa13a0cf10.js → page-c2bf871d953a1d6f.js} +1 -1
  308. package/.next/static/chunks/app/repositories/{page-4951cac905e50224.js → page-7d0f26df0537254c.js} +1 -1
  309. package/.next/static/chunks/app/review/{page-a0899b2d285318c3.js → page-e3f141b2829973e9.js} +1 -1
  310. package/.next/static/chunks/app/sessions/{page-fb36145ec732092a.js → page-53f188ed9ca49e5f.js} +1 -1
  311. package/.next/static/chunks/app/skills/[skillId]/{page-9099e26b60442873.js → page-80569b720aea59cc.js} +1 -1
  312. package/.next/static/chunks/app/skills/installed/{page-182e32368696d824.js → page-dbd2690ad72da95b.js} +1 -1
  313. package/.next/static/chunks/app/skills/{page-d3fdc88239ebe0ab.js → page-dacd36f9c11aa7da.js} +1 -1
  314. package/.next/static/chunks/app/worktrees/[id]/page-64d4ec3051971760.js +1 -0
  315. package/.next/static/css/5c13ea243dfdcb66.css +1 -0
  316. package/.next/trace +13 -13
  317. package/README.md +37 -11
  318. package/dist/cli/commands/attach.d.ts +50 -0
  319. package/dist/cli/commands/attach.d.ts.map +1 -0
  320. package/dist/cli/commands/attach.js +204 -0
  321. package/dist/cli/commands/capture.d.ts.map +1 -1
  322. package/dist/cli/commands/capture.js +114 -0
  323. package/dist/cli/commands/instances.d.ts.map +1 -1
  324. package/dist/cli/commands/instances.js +23 -2
  325. package/dist/cli/commands/ls.d.ts.map +1 -1
  326. package/dist/cli/commands/ls.js +41 -1
  327. package/dist/cli/config/cli-dependencies.d.ts.map +1 -1
  328. package/dist/cli/config/cli-dependencies.js +34 -0
  329. package/dist/cli/program.d.ts.map +1 -1
  330. package/dist/cli/program.js +5 -0
  331. package/dist/cli/types/index.d.ts +36 -0
  332. package/dist/cli/types/index.d.ts.map +1 -1
  333. package/dist/config/tmux-pane-config.d.ts +153 -0
  334. package/dist/config/tmux-pane-config.d.ts.map +1 -0
  335. package/dist/config/tmux-pane-config.js +172 -0
  336. package/dist/lib/cli-tools/session-name.d.ts +44 -0
  337. package/dist/lib/cli-tools/session-name.d.ts.map +1 -0
  338. package/dist/lib/cli-tools/session-name.js +57 -0
  339. package/dist/lib/cli-tools/types.d.ts +1 -1
  340. package/dist/lib/cli-tools/types.d.ts.map +1 -1
  341. package/dist/lib/cli-tools/types.js +6 -1
  342. package/dist/lib/cli-tools/validation.d.ts +34 -0
  343. package/dist/lib/cli-tools/validation.d.ts.map +1 -0
  344. package/dist/lib/cli-tools/validation.js +41 -0
  345. package/dist/lib/detection/status-reason.d.ts +18 -0
  346. package/dist/lib/detection/status-reason.d.ts.map +1 -1
  347. package/dist/lib/detection/status-reason.js +18 -0
  348. package/dist/lib/detection/tools/verified-against.d.ts +57 -7
  349. package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
  350. package/dist/lib/detection/tools/verified-against.js +59 -8
  351. package/dist/lib/detection/version-probes.d.ts +26 -5
  352. package/dist/lib/detection/version-probes.d.ts.map +1 -1
  353. package/dist/lib/detection/version-probes.js +28 -6
  354. package/dist/lib/session/tmux-session-surface.d.ts +369 -0
  355. package/dist/lib/session/tmux-session-surface.d.ts.map +1 -0
  356. package/dist/lib/session/tmux-session-surface.js +525 -0
  357. package/dist/server/src/config/cli-tool-timing-config.js +12 -1
  358. package/dist/server/src/config/detection-evidence-config.js +5 -0
  359. package/dist/server/src/config/schedule-config.js +28 -1
  360. package/dist/server/src/lib/cli-tools/antigravity.js +2 -2
  361. package/dist/server/src/lib/cli-tools/base.js +13 -8
  362. package/dist/server/src/lib/cli-tools/claude.js +20 -0
  363. package/dist/server/src/lib/cli-tools/codex.js +205 -61
  364. package/dist/server/src/lib/cli-tools/command-code.js +349 -0
  365. package/dist/server/src/lib/cli-tools/composer-spec.js +6 -0
  366. package/dist/server/src/lib/cli-tools/copilot.js +2 -2
  367. package/dist/server/src/lib/cli-tools/gemini.js +2 -2
  368. package/dist/server/src/lib/cli-tools/graceful-exit.js +16 -1
  369. package/dist/server/src/lib/cli-tools/index.js +4 -1
  370. package/dist/server/src/lib/cli-tools/install-hints.js +131 -0
  371. package/dist/server/src/lib/cli-tools/liveness-spec.js +18 -0
  372. package/dist/server/src/lib/cli-tools/manager.js +2 -0
  373. package/dist/server/src/lib/cli-tools/opencode.js +2 -2
  374. package/dist/server/src/lib/cli-tools/start-availability.js +18 -11
  375. package/dist/server/src/lib/cli-tools/types.js +6 -1
  376. package/dist/server/src/lib/cli-tools/vibe-local.js +2 -2
  377. package/dist/server/src/lib/cmate-parser.js +6 -0
  378. package/dist/server/src/lib/detection/cli-patterns.js +441 -8
  379. package/dist/server/src/lib/detection/opencode-modal-overlay.js +66 -100
  380. package/dist/server/src/lib/detection/selection-shape.js +341 -0
  381. package/dist/server/src/lib/detection/sgr-background.js +210 -0
  382. package/dist/server/src/lib/detection/status-detector.js +6 -0
  383. package/dist/server/src/lib/detection/status-reason.js +18 -0
  384. package/dist/server/src/lib/detection/tools/antigravity/detect.js +38 -15
  385. package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +392 -0
  386. package/dist/server/src/lib/detection/tools/codex/detect.js +83 -2
  387. package/dist/server/src/lib/detection/tools/command-code/detect.js +159 -0
  388. package/dist/server/src/lib/detection/tools/registry.js +6 -4
  389. package/dist/server/src/lib/detection/tools/verified-against.js +59 -8
  390. package/dist/server/src/lib/detection/version-probes.js +28 -6
  391. package/dist/server/src/lib/hooks/sources/antigravity/history.js +77 -16
  392. package/dist/server/src/lib/hooks/sources/claude/history.js +94 -18
  393. package/dist/server/src/lib/hooks/sources/codex/history.js +84 -15
  394. package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +130 -17
  395. package/dist/server/src/lib/hooks/sources/codex/relay-install.js +145 -0
  396. package/dist/server/src/lib/hooks/sources/command-code/history.js +865 -0
  397. package/dist/server/src/lib/hooks/sources/command-code/hooks-config.js +390 -0
  398. package/dist/server/src/lib/hooks/sources/command-code/source.js +290 -0
  399. package/dist/server/src/lib/hooks/sources/command-code/tool-id.js +18 -0
  400. package/dist/server/src/lib/hooks/sources/command-code/transcript.js +604 -0
  401. package/dist/server/src/lib/hooks/sources/index.js +3 -1
  402. package/dist/server/src/lib/hooks/sources/opencode/history.js +57 -3
  403. package/dist/server/src/lib/hooks/sources/opencode/transcript.js +24 -28
  404. package/dist/server/src/lib/hooks/sources/registry.js +4 -0
  405. package/dist/server/src/lib/hooks/sources/turn-body.js +77 -19
  406. package/dist/server/src/lib/job-executor.js +12 -0
  407. package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +6 -0
  408. package/dist/server/src/lib/polling/response-checker.js +112 -7
  409. package/dist/server/src/lib/polling/structured-history-gate.js +15 -8
  410. package/dist/server/src/lib/realtime/types.js +15 -5
  411. package/dist/server/src/lib/response-cleaner.js +24 -1
  412. package/dist/server/src/lib/response-extractor.js +11 -0
  413. package/dist/server/src/lib/session/claude-executor.js +223 -4
  414. package/dist/server/src/lib/session/cli-session.js +52 -0
  415. package/dist/server/src/lib/session/tmux-session-surface.js +525 -0
  416. package/dist/server/src/lib/skills/compatibility-matrix.js +117 -1
  417. package/dist/server/src/lib/tmux/geometry-delegation.js +143 -0
  418. package/dist/server/src/lib/tmux/read-mode-pager.js +76 -10
  419. package/dist/server/src/lib/tmux/read-mode.js +44 -2
  420. package/dist/server/src/lib/tmux/session-hook-scripts.js +249 -0
  421. package/dist/server/src/lib/tmux/session-hooks.js +122 -0
  422. package/dist/server/src/lib/tmux/session-status-options.js +213 -0
  423. package/dist/server/src/lib/tmux/tmux.js +79 -2
  424. package/dist/server/src/lib/version-checker.js +110 -0
  425. package/dist/server/src/lib/ws-server.js +16 -10
  426. package/dist/server/src/types/agent-transcript.js +73 -1
  427. package/dist/server/src/types/terminal-keys.js +131 -3
  428. package/dist/types/terminal-keys.d.ts +100 -3
  429. package/dist/types/terminal-keys.d.ts.map +1 -1
  430. package/dist/types/terminal-keys.js +131 -3
  431. package/package.json +1 -1
  432. package/.next/server/chunks/3099.js +0 -5
  433. package/.next/server/chunks/7824.js +0 -1
  434. package/.next/server/chunks/848.js +0 -1
  435. package/.next/static/chunks/3916-0e929d089282dc5d.js +0 -1
  436. package/.next/static/chunks/6022-7a7d1760fc9814c7.js +0 -1
  437. package/.next/static/chunks/6381-147dde2a967e9458.js +0 -1
  438. package/.next/static/chunks/app/layout-6a26ea22d5cf03dc.js +0 -1
  439. package/.next/static/chunks/app/worktrees/[id]/page-2f73d69187936627.js +0 -1
  440. package/.next/static/css/23f9c40ecc458c77.css +0 -1
  441. /package/.next/static/{QXxQbXWoo7ldUyOcv7PCZ → 60mm4_QBuFtFTfo5UMyKU}/_buildManifest.js +0 -0
  442. /package/.next/static/{QXxQbXWoo7ldUyOcv7PCZ → 60mm4_QBuFtFTfo5UMyKU}/_ssgManifest.js +0 -0
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ /**
3
+ * Server side of Issue #2317's session-scoped hooks and geometry hand-back.
4
+ *
5
+ * Two jobs, both keyed off one session name:
6
+ *
7
+ * - {@link ensureSessionHooks} reconciles the two OPT-IN `client-attached`
8
+ * hooks (Phase C's auto popup, Phase D's delegate-on-hand-attach) with what
9
+ * the environment asks for. Like #1623's key binding it CONVERGES: turning an
10
+ * option off removes the hook a previous run installed, rather than merely
11
+ * not installing it again.
12
+ * - {@link reconcileDelegatedGeometry} is the safety net the Issue asked a
13
+ * `client-detached` hook to be. tmux 3.5a does not fire that hook
14
+ * session-scoped (measured — see the table in `live-attach.ts`), so the
15
+ * restore runs from the status poll instead: every couple of seconds, for
16
+ * every session, "is this delegated while no human is looking at it?".
17
+ *
18
+ * Nothing here throws. All of it hangs off the status poll and off session
19
+ * creation, and neither may be failed by a convenience feature.
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.ensureSessionHooks = ensureSessionHooks;
23
+ exports.reconcileDelegatedGeometry = reconcileDelegatedGeometry;
24
+ exports.forgetSessionHooks = forgetSessionHooks;
25
+ const child_process_1 = require("child_process");
26
+ const util_1 = require("util");
27
+ const tmux_session_surface_1 = require("../session/tmux-session-surface");
28
+ const session_hook_scripts_1 = require("./session-hook-scripts");
29
+ const geometry_delegation_1 = require("./geometry-delegation");
30
+ const logger_1 = require("../logger");
31
+ const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
32
+ const logger = (0, logger_1.createLogger)('tmux-session-hooks');
33
+ /** tmux calls here are interactive-latency, not long-running. */
34
+ const TMUX_TIMEOUT = 5000;
35
+ const ensured = globalThis.__cmEnsuredSessionHooks ?? (globalThis.__cmEnsuredSessionHooks = new Set());
36
+ /**
37
+ * Reconcile a session's opt-in `client-attached` hooks with the environment.
38
+ *
39
+ * Runs once per session per process; call it freely. Both hooks are removed when
40
+ * their option is off, so `CM_READ_MODE_AUTO_POPUP=on` followed by a restart
41
+ * without it leaves no hook behind.
42
+ *
43
+ * @param sessionName - Target session
44
+ */
45
+ async function ensureSessionHooks(sessionName) {
46
+ if (!(0, tmux_session_surface_1.isCommandMateSession)(sessionName))
47
+ return;
48
+ if (ensured.has(sessionName))
49
+ return;
50
+ ensured.add(sessionName);
51
+ try {
52
+ if ((0, tmux_session_surface_1.isLiveAttachHookEnabled)() && (0, tmux_session_surface_1.isLiveAttachEligibleSession)(sessionName)) {
53
+ // The restore script rides along with the delegate one: a user whose
54
+ // server is down needs the manual way back, and materializing it here is
55
+ // the only moment we know the delegate path is in use at all.
56
+ (0, session_hook_scripts_1.materializeLiveRestoreScript)();
57
+ const args = (0, tmux_session_surface_1.buildInstallDelegateHookArgs)(sessionName, (0, session_hook_scripts_1.materializeLiveDelegateScript)());
58
+ if (args)
59
+ await execFileAsync('tmux', args, { timeout: TMUX_TIMEOUT });
60
+ }
61
+ else {
62
+ await execFileAsync('tmux', (0, tmux_session_surface_1.buildRemoveDelegateHookArgs)(sessionName), {
63
+ timeout: TMUX_TIMEOUT,
64
+ });
65
+ }
66
+ if ((0, tmux_session_surface_1.isAutoPopupEnabled)()) {
67
+ const args = (0, tmux_session_surface_1.buildInstallAutoPopupHookArgs)(sessionName, (0, session_hook_scripts_1.materializeAutoPopupScript)());
68
+ if (args)
69
+ await execFileAsync('tmux', args, { timeout: TMUX_TIMEOUT });
70
+ }
71
+ else {
72
+ await execFileAsync('tmux', (0, tmux_session_surface_1.buildRemoveAutoPopupHookArgs)(sessionName), {
73
+ timeout: TMUX_TIMEOUT,
74
+ });
75
+ }
76
+ }
77
+ catch (error) {
78
+ logger.debug('session-hooks:reconcile-failed', {
79
+ sessionName,
80
+ error: error instanceof Error ? error.message : String(error),
81
+ });
82
+ }
83
+ }
84
+ /**
85
+ * Take a delegated session's geometry back when no human is attached.
86
+ *
87
+ * The Phase D safety net. Restores unconditionally once the two conditions hold,
88
+ * because the sequence is idempotent — a session already at `manual` 200x1000
89
+ * with no `@cm_delegated` is left byte-identical by it.
90
+ *
91
+ * Also self-healing for a flag left behind by a CLI that was killed: the flag
92
+ * alone never keeps a window unpinned, because this runs whenever nobody is
93
+ * looking.
94
+ *
95
+ * @param sessionName - Target session
96
+ * @returns true when the geometry was handed back by this call
97
+ */
98
+ async function reconcileDelegatedGeometry(sessionName) {
99
+ try {
100
+ if (!(await (0, geometry_delegation_1.isGeometryDelegated)(sessionName)))
101
+ return false;
102
+ if (await (0, geometry_delegation_1.hasHumanClientAttached)(sessionName))
103
+ return false;
104
+ for (const args of (0, tmux_session_surface_1.buildRestoreGeometryCommands)(sessionName)) {
105
+ await execFileAsync('tmux', args, { timeout: TMUX_TIMEOUT });
106
+ }
107
+ logger.info('session-hooks:geometry-restored', { sessionName });
108
+ return true;
109
+ }
110
+ catch (error) {
111
+ logger.debug('session-hooks:geometry-restore-failed', {
112
+ sessionName,
113
+ error: error instanceof Error ? error.message : String(error),
114
+ });
115
+ return false;
116
+ }
117
+ }
118
+ /** Forget a session's hook bookkeeping — call when it is known to be gone. */
119
+ function forgetSessionHooks(sessionName) {
120
+ ensured.delete(sessionName);
121
+ (0, geometry_delegation_1.forgetGeometryDelegation)(sessionName);
122
+ }
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ /**
3
+ * Phase B of Issue #2317: publish the session's state ONTO the tmux session.
4
+ *
5
+ * Before this module, `running` / `waiting` / `ready` / `idle` existed only
6
+ * inside CommandMate. `tmux ls` showed a name and a window count, an attached
7
+ * status line showed tmux's stock clock, and an operator who wanted to know what
8
+ * an agent was doing had to open the web UI or run `commandmate ls`. Two writes
9
+ * per transition fix that:
10
+ *
11
+ * - **user options** (`@cm_status` and friends) — readable without attaching:
12
+ * `tmux ls -F '#{session_name} #{@cm_status}'`;
13
+ * - **a session-scoped `status-right`** — readable while attached, rendered
14
+ * from those same options so the line updates without being rewritten.
15
+ *
16
+ * ## Everything here is session-scoped, and that is the point
17
+ *
18
+ * `set-option -t <session>` writes the SESSION's option table. The tmux server's
19
+ * global table — which every session on the machine inherits, including ones
20
+ * CommandMate knows nothing about — is never touched, and
21
+ * `tests/unit/tmux/session-status-options-2317.test.ts` asserts that by
22
+ * inspecting the argv of every call this module makes. #1623's `bind-key` is the
23
+ * one global mutation CommandMate makes and it is not made here.
24
+ *
25
+ * ## Writes happen on TRANSITION, not on every poll
26
+ *
27
+ * `GET /api/worktrees` probes every tool of every worktree every couple of
28
+ * seconds. Setting five options on each of those polls would be a few hundred
29
+ * `execFile` round-trips a minute for a value that changes a few times an hour,
30
+ * so {@link publishSessionStatus} keeps the last published tuple per session and
31
+ * returns without touching tmux when nothing moved. The memo is keyed by session
32
+ * name and dropped by {@link forgetSessionStatus} when the session goes away.
33
+ *
34
+ * ## The opt-out converges, without a startup hook
35
+ *
36
+ * `CM_TMUX_STATUS=off` does not merely stop writing: the first status poll after
37
+ * the restart REMOVES the `@cm_*` options and the CommandMate `status-right`
38
+ * from each session it visits, once per session. That is the same "an opt-out
39
+ * that uninstalls" contract #1623 gave `CM_READ_MODE`, and it is done from the
40
+ * poll rather than from a startup sweep for two reasons — the poll already knows
41
+ * which sessions exist (a sweep would have to ask tmux again), and it keeps this
42
+ * feature from needing a wire into `server.ts`, whose startup path is
43
+ * deliberately a single dynamic import per module graph.
44
+ *
45
+ * ## Nothing here may ever throw
46
+ *
47
+ * This is a convenience surface hanging off the status poll. A tmux hiccup must
48
+ * not be able to fail the poll that the sidebar, `commandmate ls` and the header
49
+ * chip all read, so every entry point swallows its errors and logs at debug.
50
+ */
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ exports.publishSessionStatus = publishSessionStatus;
53
+ exports.ensureSessionStatusLine = ensureSessionStatusLine;
54
+ exports.clearSessionStatus = clearSessionStatus;
55
+ exports.forgetSessionStatus = forgetSessionStatus;
56
+ exports.publishedSessionCount = publishedSessionCount;
57
+ const child_process_1 = require("child_process");
58
+ const util_1 = require("util");
59
+ const tmux_session_surface_1 = require("../session/tmux-session-surface");
60
+ const logger_1 = require("../logger");
61
+ const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
62
+ const logger = (0, logger_1.createLogger)('tmux-session-status');
63
+ /** tmux calls here are interactive-latency, not long-running. */
64
+ const TMUX_TIMEOUT = 5000;
65
+ const published = globalThis.__cmPublishedTmuxStatus ??
66
+ (globalThis.__cmPublishedTmuxStatus = new Map());
67
+ /** Sessions this process has already uninstalled the surface from. */
68
+ const cleared = globalThis.__cmClearedTmuxStatus ?? (globalThis.__cmClearedTmuxStatus = new Set());
69
+ /**
70
+ * Write one session's state onto its tmux session, if it changed.
71
+ *
72
+ * @param publication - Session identity plus the status word to publish
73
+ * @returns What was done, for tests and for the caller's logging
74
+ */
75
+ async function publishSessionStatus(publication) {
76
+ const { sessionName, worktreeId, cliToolId, instanceId, status } = publication;
77
+ if (!(0, tmux_session_surface_1.isTmuxStatusEnabled)()) {
78
+ // The uninstall path. Once per session per process: `clearSessionStatus`
79
+ // issues six `execFile` calls, and repeating them on every poll of a server
80
+ // that has the surface turned off would be the cost the feature was turned
81
+ // off to avoid.
82
+ if (!cleared.has(sessionName)) {
83
+ cleared.add(sessionName);
84
+ await clearSessionStatus(sessionName);
85
+ }
86
+ return 'disabled';
87
+ }
88
+ const previous = published.get(sessionName);
89
+ if (previous &&
90
+ previous.status === status &&
91
+ previous.worktreeId === worktreeId &&
92
+ previous.cliToolId === cliToolId &&
93
+ previous.instanceId === instanceId) {
94
+ return 'unchanged';
95
+ }
96
+ const updated = (publication.now ?? new Date()).toISOString();
97
+ const writes = [
98
+ [tmux_session_surface_1.CM_STATUS_OPTION, status],
99
+ [tmux_session_surface_1.CM_WORKTREE_OPTION, worktreeId],
100
+ [tmux_session_surface_1.CM_TOOL_OPTION, cliToolId],
101
+ [tmux_session_surface_1.CM_INSTANCE_OPTION, instanceId],
102
+ [tmux_session_surface_1.CM_UPDATED_OPTION, updated],
103
+ ];
104
+ try {
105
+ for (const [option, value] of writes) {
106
+ await execFileAsync('tmux', (0, tmux_session_surface_1.buildSetSessionOptionArgs)(sessionName, option, value), {
107
+ timeout: TMUX_TIMEOUT,
108
+ });
109
+ }
110
+ published.set(sessionName, { status, worktreeId, cliToolId, instanceId });
111
+ // The line renders FROM the options above, so it is installed after them —
112
+ // a status-right referencing `#{@cm_status}` on a session that has none
113
+ // paints an empty pair of brackets until the first write lands.
114
+ await ensureSessionStatusLine(sessionName);
115
+ return 'written';
116
+ }
117
+ catch (error) {
118
+ // A session that was killed between the poll and this write is the ordinary
119
+ // case, not an incident. Drop the memo so the next live session under the
120
+ // same name republishes rather than being deduped against a dead one.
121
+ published.delete(sessionName);
122
+ logger.debug('session-status:write-failed', {
123
+ sessionName,
124
+ error: error instanceof Error ? error.message : String(error),
125
+ });
126
+ return 'error';
127
+ }
128
+ }
129
+ /**
130
+ * Install the session-scoped `status-right`, unless the session already has one.
131
+ *
132
+ * "Already has one" means a SESSION-scoped value, which is exactly what
133
+ * `show-options -t <session> status-right` reports: measured on tmux 3.5a, a
134
+ * session that never set it answers with empty stdout (the global value is not
135
+ * echoed), and one that did answers `status-right "…"`. So a user who
136
+ * customised this session in `.tmux.conf` — or who set it by hand — keeps their
137
+ * line, and everyone else gets CommandMate's.
138
+ *
139
+ * Idempotent: once installed, the value contains {@link CM_STATUS_RIGHT_FORMAT}
140
+ * and is recognised as ours, so a restart re-installs nothing.
141
+ *
142
+ * @param sessionName - Target session
143
+ * @returns true when the line is CommandMate's after this call
144
+ */
145
+ async function ensureSessionStatusLine(sessionName) {
146
+ try {
147
+ const { stdout } = await execFileAsync('tmux', (0, tmux_session_surface_1.buildShowSessionOptionArgs)(sessionName, 'status-right'), { timeout: TMUX_TIMEOUT });
148
+ const existing = stdout.trim();
149
+ if (existing !== '' && !existing.includes(tmux_session_surface_1.CM_STATUS_RIGHT_FORMAT)) {
150
+ logger.debug('session-status:status-right-user-owned', { sessionName, existing });
151
+ return false;
152
+ }
153
+ if (existing === '') {
154
+ await execFileAsync('tmux', (0, tmux_session_surface_1.buildSetStatusRightArgs)(sessionName, tmux_session_surface_1.CM_STATUS_RIGHT_FORMAT), { timeout: TMUX_TIMEOUT });
155
+ }
156
+ return true;
157
+ }
158
+ catch (error) {
159
+ logger.debug('session-status:status-right-failed', {
160
+ sessionName,
161
+ error: error instanceof Error ? error.message : String(error),
162
+ });
163
+ return false;
164
+ }
165
+ }
166
+ /**
167
+ * Remove every `@cm_*` option and the session-scoped `status-right` we own.
168
+ *
169
+ * The `status-right` is only removed when it is still ours — a user who rebound
170
+ * it after us owns it now, and clobbering that would be the same rudeness
171
+ * {@link ensureSessionStatusLine} exists to avoid.
172
+ *
173
+ * @param sessionName - Target session
174
+ */
175
+ async function clearSessionStatus(sessionName) {
176
+ published.delete(sessionName);
177
+ for (const option of tmux_session_surface_1.CM_SESSION_OPTIONS) {
178
+ try {
179
+ await execFileAsync('tmux', (0, tmux_session_surface_1.buildUnsetSessionOptionArgs)(sessionName, option), {
180
+ timeout: TMUX_TIMEOUT,
181
+ });
182
+ }
183
+ catch {
184
+ // Unsetting an option that was never set exits non-zero on some builds.
185
+ }
186
+ }
187
+ try {
188
+ const { stdout } = await execFileAsync('tmux', (0, tmux_session_surface_1.buildShowSessionOptionArgs)(sessionName, 'status-right'), { timeout: TMUX_TIMEOUT });
189
+ if (stdout.includes(tmux_session_surface_1.CM_STATUS_RIGHT_FORMAT)) {
190
+ await execFileAsync('tmux', (0, tmux_session_surface_1.buildUnsetStatusRightArgs)(sessionName), {
191
+ timeout: TMUX_TIMEOUT,
192
+ });
193
+ }
194
+ }
195
+ catch {
196
+ // Same reasoning as above: nothing here may fail a caller.
197
+ }
198
+ }
199
+ /**
200
+ * Forget a session's published state without touching tmux.
201
+ *
202
+ * Called when a session is known to be gone. The next session created under the
203
+ * same name then publishes from scratch instead of being deduped against the
204
+ * dead one's last status.
205
+ */
206
+ function forgetSessionStatus(sessionName) {
207
+ published.delete(sessionName);
208
+ cleared.delete(sessionName);
209
+ }
210
+ /** Test seam: how many sessions currently have a memoised publication. */
211
+ function publishedSessionCount() {
212
+ return published.size;
213
+ }
@@ -4,7 +4,7 @@
4
4
  * Provides functions to manage tmux sessions for Claude CLI integration
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.NAVIGATION_KEY_VALUES = exports.SPECIAL_KEY_VALUES = void 0;
7
+ exports.REPAINT_INVALIDATE_DELAY_MS = exports.NAVIGATION_KEY_VALUES = exports.SPECIAL_KEY_VALUES = void 0;
8
8
  exports.exactTarget = exactTarget;
9
9
  exports.reconcileSessionGeometry = reconcileSessionGeometry;
10
10
  exports.isTmuxAvailable = isTmuxAvailable;
@@ -28,6 +28,7 @@ exports.sendSpecialKeysAndInvalidate = sendSpecialKeysAndInvalidate;
28
28
  const child_process_1 = require("child_process");
29
29
  const util_1 = require("util");
30
30
  const tmux_capture_cache_1 = require("./tmux-capture-cache");
31
+ const geometry_delegation_1 = require("./geometry-delegation");
31
32
  const validation_1 = require("../../lib/cli-tools/validation");
32
33
  const tmux_pane_config_1 = require("../../config/tmux-pane-config");
33
34
  const logger_1 = require("../../lib/logger");
@@ -77,6 +78,24 @@ function exactTarget(sessionName) {
77
78
  * Failures are intentionally non-fatal: geometry improves capture fidelity but
78
79
  * must never make an otherwise healthy CLI session unusable.
79
80
  *
81
+ * ## It stands down while a human is attached (Issue #2317, Phase D)
82
+ *
83
+ * `commandmate attach --live` hands the window to the terminal looking at it so
84
+ * the transcript is readable at all; every `send` to a running session reaches
85
+ * here through `reconcileExistingSession()`, and snapping the canvas back to
86
+ * 200x1000 mid-read would undo that under the reader's hands. So when the
87
+ * geometry does NOT already match, this asks whether a NON-control-mode client
88
+ * is attached and leaves the window alone if one is.
89
+ *
90
+ * Two properties of that ordering are load-bearing:
91
+ *
92
+ * - the question is asked only on the path that would actually resize, so the
93
+ * overwhelmingly common "already correct" call still costs exactly the two
94
+ * tmux round-trips it always has;
95
+ * - it keys off a live client rather than off `@cm_delegated`, so a flag left
96
+ * behind by a CLI that was killed can never pin a window open forever — the
97
+ * next reconcile with nobody attached repairs it.
98
+ *
80
99
  * @returns true when at least one tmux option was changed.
81
100
  */
82
101
  async function reconcileSessionGeometry(sessionName, options = {}) {
@@ -103,6 +122,13 @@ async function reconcileSessionGeometry(sessionName, options = {}) {
103
122
  const sizeMatches = currentWidth === windowWidth && currentHeight === windowHeight;
104
123
  if (modeMatches && sizeMatches)
105
124
  return false;
125
+ // Issue #2317: a human is reading this pane at their terminal's size. See the
126
+ // docblock — asked here, after the cheap match, so the ordinary call is
127
+ // unchanged.
128
+ if ((options.respectAttachedClient ?? true) && (await (0, geometry_delegation_1.hasHumanClientAttached)(sessionName))) {
129
+ logger.info('session-geometry:delegated-to-client', { sessionName });
130
+ return false;
131
+ }
106
132
  try {
107
133
  if (!modeMatches) {
108
134
  await execFileAsync('tmux', ['set-window-option', '-t', target, 'window-size', 'manual'], { timeout: DEFAULT_TIMEOUT });
@@ -316,7 +342,13 @@ async function createSession(sessionNameOrOptions, cwd) {
316
342
  // replaced (verified: `show-window-options -v window-size` came back empty),
317
343
  // so reconciling first would have the setting thrown away and leave the pane
318
344
  // tracking the latest client again.
319
- await reconcileSessionGeometry(sessionName, { windowWidth, windowHeight });
345
+ await reconcileSessionGeometry(sessionName, {
346
+ windowWidth,
347
+ windowHeight,
348
+ // Nothing can be attached to a session this call is still creating, so the
349
+ // Phase D client probe would be a round-trip with one possible answer.
350
+ respectAttachedClient: false,
351
+ });
320
352
  }
321
353
  catch (error) {
322
354
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -433,6 +465,20 @@ const ALLOWED_SPECIAL_KEYS = new Set([
433
465
  // are tmux named keys; 'q' is the pager's literal "quit" character (sent verbatim by
434
466
  // `tmux send-keys`, no injection risk — single fixed char via execFile, not a shell).
435
467
  'PageUp', 'PageDown', 'Home', 'End', 'q',
468
+ // Issue #2254: the answer characters `1`-`9` / `y` / `n`, so a dialog nobody
469
+ // could parse can be answered from the chat surface's dialog card instead of
470
+ // only from the terminal. Literal characters on the wire like `q` above.
471
+ // `n` was already deliverable as an opencode chord letter and is not repeated.
472
+ '1', '2', '3', '4', '5', '6', '7', '8', '9', 'y',
473
+ // Issue #2297: claude's "use this session only" key. Its `/model` footer reads
474
+ // `Enter to set as default · s to use this session only · Esc to cancel`, and
475
+ // `Enter` there rewrites `model` in ~/.claude/settings.json (#1495) — so
476
+ // without this the chat surface could deliver the destructive half of that
477
+ // footer and not the safe half. A literal character like `q` / `y` above.
478
+ // Deliverable here for every session; only claude and Command Code DECLARE it
479
+ // (`CLAUDE_NAVIGATION_KEY_VALUES`), so the route answers 400 for anyone else —
480
+ // which matters, because `s` is `sort:relevance` on copilot's session picker.
481
+ 's',
436
482
  // Issue #2046: opencode's own chords. `C-x` is its leader prefix (measured
437
483
  // default of 1.18.22, 2000 ms window), `C-p` opens the command palette and
438
484
  // `C-t` cycles the model variant. The lower-case letters complete a leader
@@ -802,6 +848,36 @@ async function clearComposerLine(sessionName) {
802
848
  function isAllowedSpecialKey(key, vocabulary = terminal_keys_1.NAVIGATION_KEY_VALUES) {
803
849
  return vocabulary.includes(key) && isSendableSpecialKey(key);
804
850
  }
851
+ /**
852
+ * How long after a key lands the TUI is still allowed to be repainting
853
+ * (Issue #2297).
854
+ *
855
+ * `invalidateCache()` fires the instant `tmux send-keys` returns, which is
856
+ * BEFORE the CLI has drawn the consequence of the key. The next capture — the
857
+ * chat surface's own `onKeysSent` refresh, or any of the pollers that share this
858
+ * cache (the sidebar status probe, the global session poller) — therefore has a
859
+ * good chance of storing the PRE-repaint frame, and {@link CACHE_TTL_MS} then
860
+ * serves that stale frame for five seconds. That is the "the highlight does not
861
+ * move" report in Issue #2297: the send worked, the cache was invalidated, and
862
+ * the surface still drew the old dialog.
863
+ *
864
+ * 250 ms is comfortably past an ink/bubbletea repaint (`SPECIAL_KEY_DELAY_MS`,
865
+ * the gap this transport already leaves BETWEEN keys of one chord, is 100 ms)
866
+ * and comfortably inside the 1-second budget the Issue sets for seeing the
867
+ * highlight move.
868
+ */
869
+ exports.REPAINT_INVALIDATE_DELAY_MS = 250;
870
+ /**
871
+ * Drop the cached frame again once the TUI has had time to repaint.
872
+ *
873
+ * Fire-and-forget on purpose: the route must not wait 250 ms to answer, and the
874
+ * work is one `Map.delete`. The timer is `unref()`ed where the runtime supports
875
+ * it so a pending invalidation can never hold a process (or a test runner) open.
876
+ */
877
+ function scheduleRepaintInvalidation(sessionName) {
878
+ const timer = setTimeout(() => (0, tmux_capture_cache_1.invalidateCache)(sessionName), exports.REPAINT_INVALIDATE_DELAY_MS);
879
+ timer.unref?.();
880
+ }
805
881
  /**
806
882
  * Send special keys to a tmux session and invalidate the capture cache.
807
883
  * Wrapper combining sendSpecialKeys() + invalidateCache() for DRY (DR1-003).
@@ -812,4 +888,5 @@ function isAllowedSpecialKey(key, vocabulary = terminal_keys_1.NAVIGATION_KEY_VA
812
888
  async function sendSpecialKeysAndInvalidate(sessionName, keys) {
813
889
  await sendSpecialKeys(sessionName, keys);
814
890
  (0, tmux_capture_cache_1.invalidateCache)(sessionName);
891
+ scheduleRepaintInvalidation(sessionName);
815
892
  }
@@ -20,12 +20,15 @@ exports.isNewerVersion = isNewerVersion;
20
20
  exports.getClientVersion = getClientVersion;
21
21
  exports.getServerVersion = getServerVersion;
22
22
  exports.getCurrentVersion = getCurrentVersion;
23
+ exports.getServedBundleVersion = getServedBundleVersion;
24
+ exports.resolveBundleDrift = resolveBundleDrift;
23
25
  exports.validateReleaseUrl = validateReleaseUrl;
24
26
  exports.sanitizeReleaseName = sanitizeReleaseName;
25
27
  exports.checkForUpdate = checkForUpdate;
26
28
  exports.resetCacheForTesting = resetCacheForTesting;
27
29
  const fs_1 = require("fs");
28
30
  const path_1 = require("path");
31
+ const types_1 = require("../lib/realtime/types");
29
32
  // =============================================================================
30
33
  // Constants
31
34
  // =============================================================================
@@ -60,6 +63,17 @@ const FETCH_TIMEOUT_MS = 5000;
60
63
  * project directory) leaking a foreign version.
61
64
  */
62
65
  const PACKAGE_NAME = 'commandmate';
66
+ /**
67
+ * The manifest `next build` writes beside the client bundle, relative to the
68
+ * package root. [Issue #2271]
69
+ *
70
+ * It snapshots the *resolved* next.config — the `env` block included — so
71
+ * `config.env.NEXT_PUBLIC_APP_VERSION` is literally the string that build
72
+ * inlined into every browser bundle it emitted. That makes it the only file on
73
+ * disk that can answer "which version is the bundle we are serving?" without
74
+ * asking the bundle itself.
75
+ */
76
+ const NEXT_BUILD_MANIFEST_PATH = ['.next', 'required-server-files.json'];
63
77
  const cache = globalThis.__versionCheckCache ??
64
78
  (globalThis.__versionCheckCache = {
65
79
  result: null,
@@ -162,6 +176,99 @@ function getServerVersion() {
162
176
  function getCurrentVersion() {
163
177
  return getServerVersion();
164
178
  }
179
+ // =============================================================================
180
+ // Served bundle identity (Issue #2271)
181
+ // =============================================================================
182
+ /**
183
+ * Memoised answer of {@link getServedBundleVersion}, resolved on first use and
184
+ * then frozen for the life of the process. [Issue #2271]
185
+ *
186
+ * Frozen on purpose. The question is "which build is this process serving?",
187
+ * and a running Next production server answers that once — at startup, from the
188
+ * `.next` it opened. Re-reading the manifest on every call would let a
189
+ * `next build` performed *underneath* the running server rename the served
190
+ * build without the server having reloaded a single byte of it, which is the
191
+ * false positive this Issue exists to remove, in a new disguise.
192
+ */
193
+ let servedBundleVersion = null;
194
+ /**
195
+ * Read the version `next build` inlined into the client bundle, from the build
196
+ * manifest it left on disk. [Issue #2271]
197
+ *
198
+ * @returns The baked version, or null when the manifest is absent, unreadable,
199
+ * malformed, or predates the `env` block.
200
+ */
201
+ function readServedBundleVersionFromBuild() {
202
+ try {
203
+ const raw = (0, fs_1.readFileSync)((0, path_1.join)(process.cwd(), ...NEXT_BUILD_MANIFEST_PATH), 'utf-8');
204
+ const parsed = JSON.parse(raw);
205
+ const baked = parsed.config?.env?.NEXT_PUBLIC_APP_VERSION;
206
+ if (typeof baked === 'string' && baked.length > 0)
207
+ return baked;
208
+ return null;
209
+ }
210
+ catch {
211
+ return null;
212
+ }
213
+ }
214
+ /** First-use resolution behind {@link getServedBundleVersion}'s memo. */
215
+ function resolveServedBundleVersion() {
216
+ // `next dev` compiles on demand and never writes the build manifest, but a
217
+ // stale one left by an earlier `npm run build` is still sitting in `.next` —
218
+ // and it names a version the dev bundle was never built from. Under dev the
219
+ // live next.config populates `process.env` for the server too, so the baked
220
+ // value already *is* the honest answer and the manifest must not be consulted.
221
+ if (process.env.NODE_ENV === 'production') {
222
+ const built = readServedBundleVersionFromBuild();
223
+ if (built)
224
+ return built;
225
+ }
226
+ return getClientVersion();
227
+ }
228
+ /**
229
+ * The version of the **client bundle this server is serving**. [Issue #2271]
230
+ *
231
+ * Deliberately *not* {@link getServerVersion}. That one reads package.json at
232
+ * runtime, which is the right answer for "is there a newer release on GitHub?"
233
+ * and the wrong one for "should this tab reload?": the release procedure bumps
234
+ * package.json on `develop` and never rebuilds the primary checkout (doing so
235
+ * would swap `.next` out from under the running server — see the release
236
+ * skill's Phase 2-3), so `package.json > bundle` is the steady state after
237
+ * every release. Comparing against it therefore told **every** tab, forever,
238
+ * that it was out of date.
239
+ *
240
+ * The honest comparand is the build the bundle came from, so this reads the
241
+ * `next build` manifest and falls back — never to package.json — to the baked
242
+ * `NEXT_PUBLIC_APP_VERSION`, and finally to `'0.0.0'`, which
243
+ * {@link isVersionMismatch} treats as "unknown" and never reports as drift.
244
+ *
245
+ * @returns Served bundle version string (e.g., "0.2.3"), or "0.0.0" as fallback
246
+ */
247
+ function getServedBundleVersion() {
248
+ servedBundleVersion ??= resolveServedBundleVersion();
249
+ return servedBundleVersion;
250
+ }
251
+ /**
252
+ * Decide whether a tab running `clientBundleVersion` is on a stale build.
253
+ * [Issue #2271]
254
+ *
255
+ * The single seam the WebSocket version handshake calls, so "what counts as
256
+ * drift" has exactly one definition and one place to test it. Both sides are
257
+ * build identities: the client sends the `NEXT_PUBLIC_APP_VERSION` its bundle
258
+ * was compiled with, and this compares it against the version of the bundle
259
+ * being served — so a bare `package.json` bump moves neither side, and only a
260
+ * rebuild does.
261
+ *
262
+ * @param clientBundleVersion - The version the tab's bundle was built from
263
+ * @returns The drifted pair, or null when the two builds agree or either side
264
+ * is an unknown/fallback version
265
+ */
266
+ function resolveBundleDrift(clientBundleVersion) {
267
+ const serverVersion = getServedBundleVersion();
268
+ if (!(0, types_1.isVersionMismatch)(serverVersion, clientBundleVersion))
269
+ return null;
270
+ return { serverVersion, clientVersion: clientBundleVersion };
271
+ }
165
272
  /**
166
273
  * Validate that a URL is a legitimate GitHub Releases URL.
167
274
  * [SEC-SF-001] OWASP A03:2021 - Prevents injection via DNS pollution/MITM.
@@ -259,6 +366,9 @@ function resetCacheForTesting() {
259
366
  cache.result = null;
260
367
  cache.fetchedAt = 0;
261
368
  cache.rateLimitResetAt = null;
369
+ // Issue #2271: the served-bundle memo is frozen for the life of a process, so
370
+ // a suite that moves process.cwd() between cases must be able to thaw it.
371
+ servedBundleVersion = null;
262
372
  }
263
373
  // =============================================================================
264
374
  // Internal Functions
@@ -426,28 +426,34 @@ function handleMessage(ws, message) {
426
426
  }
427
427
  }
428
428
  /**
429
- * Handle a client-version hello (#1338/#1356).
429
+ * Handle a client-version hello (#1338/#1356/#2271).
430
430
  *
431
- * The client announces its baked bundle version on every (re)connect. If the
432
- * server's actually-running version (runtime package.json, resolved by
433
- * getServerVersion) has drifted from it, reply with a version_mismatch event so
434
- * the tab can surface a reload nudge. Stays silent when the versions match or
435
- * either side is an unknown/fallback version (受入条件: 誤検知しない).
431
+ * The client announces the version its bundle was built from on every
432
+ * (re)connect. `resolveBundleDrift` compares that against the version of the
433
+ * bundle **this server is serving** and answers null unless the two builds
434
+ * really differ; on drift, reply with a version_mismatch event so the tab can
435
+ * surface a reload nudge.
436
+ *
437
+ * Issue #2271: this used to ask `getServerVersion()`, i.e. the installed
438
+ * package.json. Releases bump that file without rebuilding the running server's
439
+ * `.next` — by design — so the comparison was permanently unequal and every tab
440
+ * carried an undismissable banner. The resolver, not this handler, is where
441
+ * "what counts as drift" is defined; keep it that way.
436
442
  */
437
443
  function handleClientVersion(ws, message) {
438
444
  const clientVersion = typeof message.version === 'string' ? message.version : '';
439
445
  if (!clientVersion)
440
446
  return;
441
- const serverVersion = (0, version_checker_1.getServerVersion)();
442
- if (!(0, types_2.isVersionMismatch)(serverVersion, clientVersion))
447
+ const drift = (0, version_checker_1.resolveBundleDrift)(clientVersion);
448
+ if (!drift)
443
449
  return;
444
450
  if (ws.readyState !== ws_1.WebSocket.OPEN)
445
451
  return;
446
452
  try {
447
453
  ws.send(JSON.stringify({
448
454
  type: types_2.VERSION_MISMATCH_EVENT_TYPE,
449
- serverVersion,
450
- clientVersion,
455
+ serverVersion: drift.serverVersion,
456
+ clientVersion: drift.clientVersion,
451
457
  }));
452
458
  }
453
459
  catch (error) {