aicodeman 1.43.0 → 1.45.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 (353) hide show
  1. package/README.md +9 -4
  2. package/dist/case-rename.d.ts +65 -0
  3. package/dist/case-rename.d.ts.map +1 -0
  4. package/dist/case-rename.js +198 -0
  5. package/dist/case-rename.js.map +1 -0
  6. package/dist/cli-agent.d.ts +63 -4
  7. package/dist/cli-agent.d.ts.map +1 -1
  8. package/dist/cli-agent.js +233 -19
  9. package/dist/cli-agent.js.map +1 -1
  10. package/dist/config/auth-config.d.ts +16 -1
  11. package/dist/config/auth-config.d.ts.map +1 -1
  12. package/dist/config/auth-config.js +16 -1
  13. package/dist/config/auth-config.js.map +1 -1
  14. package/dist/config/cli-registry/stock.d.ts.map +1 -1
  15. package/dist/config/cli-registry/stock.js +8 -3
  16. package/dist/config/cli-registry/stock.js.map +1 -1
  17. package/dist/config/cli-registry/types.d.ts +2 -2
  18. package/dist/config/map-limits.d.ts +13 -1
  19. package/dist/config/map-limits.d.ts.map +1 -1
  20. package/dist/config/map-limits.js +28 -1
  21. package/dist/config/map-limits.js.map +1 -1
  22. package/dist/config-backup.d.ts +279 -0
  23. package/dist/config-backup.d.ts.map +1 -0
  24. package/dist/config-backup.js +794 -0
  25. package/dist/config-backup.js.map +1 -0
  26. package/dist/cron/cron-service.d.ts +5 -5
  27. package/dist/cron/cron-service.js +6 -6
  28. package/dist/cron/cron-service.js.map +1 -1
  29. package/dist/custom-model-hosts.d.ts +16 -0
  30. package/dist/custom-model-hosts.d.ts.map +1 -1
  31. package/dist/custom-model-hosts.js.map +1 -1
  32. package/dist/hooks-config.d.ts +15 -0
  33. package/dist/hooks-config.d.ts.map +1 -1
  34. package/dist/hooks-config.js +35 -0
  35. package/dist/hooks-config.js.map +1 -1
  36. package/dist/host-sensors.d.ts +115 -0
  37. package/dist/host-sensors.d.ts.map +1 -0
  38. package/dist/host-sensors.js +457 -0
  39. package/dist/host-sensors.js.map +1 -0
  40. package/dist/intent-store.d.ts +2 -0
  41. package/dist/intent-store.d.ts.map +1 -1
  42. package/dist/intent-store.js +9 -0
  43. package/dist/intent-store.js.map +1 -1
  44. package/dist/mux-interface.d.ts +21 -4
  45. package/dist/mux-interface.d.ts.map +1 -1
  46. package/dist/prompt-cache-keepwarm.d.ts +193 -0
  47. package/dist/prompt-cache-keepwarm.d.ts.map +1 -0
  48. package/dist/prompt-cache-keepwarm.js +359 -0
  49. package/dist/prompt-cache-keepwarm.js.map +1 -0
  50. package/dist/remote-hosts.d.ts +7 -0
  51. package/dist/remote-hosts.d.ts.map +1 -1
  52. package/dist/remote-hosts.js +17 -3
  53. package/dist/remote-hosts.js.map +1 -1
  54. package/dist/remote-pane-history.d.ts.map +1 -1
  55. package/dist/remote-pane-history.js +2 -2
  56. package/dist/remote-pane-history.js.map +1 -1
  57. package/dist/respawn-controller.d.ts.map +1 -1
  58. package/dist/respawn-controller.js +6 -5
  59. package/dist/respawn-controller.js.map +1 -1
  60. package/dist/session-auto-ops.d.ts.map +1 -1
  61. package/dist/session-auto-ops.js +6 -1
  62. package/dist/session-auto-ops.js.map +1 -1
  63. package/dist/session-cli-registry-bridge.d.ts +13 -0
  64. package/dist/session-cli-registry-bridge.d.ts.map +1 -1
  65. package/dist/session-cli-registry-bridge.js +20 -3
  66. package/dist/session-cli-registry-bridge.js.map +1 -1
  67. package/dist/session-submit-verifier.d.ts +19 -0
  68. package/dist/session-submit-verifier.d.ts.map +1 -1
  69. package/dist/session-submit-verifier.js +88 -0
  70. package/dist/session-submit-verifier.js.map +1 -1
  71. package/dist/session.d.ts +61 -5
  72. package/dist/session.d.ts.map +1 -1
  73. package/dist/session.js +125 -7
  74. package/dist/session.js.map +1 -1
  75. package/dist/state-store.d.ts +10 -0
  76. package/dist/state-store.d.ts.map +1 -1
  77. package/dist/state-store.js +35 -0
  78. package/dist/state-store.js.map +1 -1
  79. package/dist/tab-layout-service.d.ts +33 -0
  80. package/dist/tab-layout-service.d.ts.map +1 -1
  81. package/dist/tab-layout-service.js +75 -3
  82. package/dist/tab-layout-service.js.map +1 -1
  83. package/dist/tmux-manager.d.ts +57 -11
  84. package/dist/tmux-manager.d.ts.map +1 -1
  85. package/dist/tmux-manager.js +190 -42
  86. package/dist/tmux-manager.js.map +1 -1
  87. package/dist/tmux-prefix-table.d.ts +86 -0
  88. package/dist/tmux-prefix-table.d.ts.map +1 -0
  89. package/dist/tmux-prefix-table.js +172 -0
  90. package/dist/tmux-prefix-table.js.map +1 -0
  91. package/dist/tui/tui-app.d.ts +17 -2
  92. package/dist/tui/tui-app.d.ts.map +1 -1
  93. package/dist/tui/tui-app.js +70 -20
  94. package/dist/tui/tui-app.js.map +1 -1
  95. package/dist/tui/tui-client.d.ts +93 -5
  96. package/dist/tui/tui-client.d.ts.map +1 -1
  97. package/dist/tui/tui-client.js +198 -28
  98. package/dist/tui/tui-client.js.map +1 -1
  99. package/dist/types/app-state.d.ts +6 -0
  100. package/dist/types/app-state.d.ts.map +1 -1
  101. package/dist/types/app-state.js.map +1 -1
  102. package/dist/types/session.d.ts +40 -1
  103. package/dist/types/session.d.ts.map +1 -1
  104. package/dist/types/session.js.map +1 -1
  105. package/dist/usage-telemetry.d.ts +15 -0
  106. package/dist/usage-telemetry.d.ts.map +1 -1
  107. package/dist/usage-telemetry.js +45 -2
  108. package/dist/usage-telemetry.js.map +1 -1
  109. package/dist/utils/copilot-plan-usage.d.ts +46 -0
  110. package/dist/utils/copilot-plan-usage.d.ts.map +1 -0
  111. package/dist/utils/copilot-plan-usage.js +95 -0
  112. package/dist/utils/copilot-plan-usage.js.map +1 -0
  113. package/dist/utils/index.d.ts +2 -0
  114. package/dist/utils/index.d.ts.map +1 -1
  115. package/dist/utils/index.js +2 -0
  116. package/dist/utils/index.js.map +1 -1
  117. package/dist/utils/single-line.d.ts +22 -0
  118. package/dist/utils/single-line.d.ts.map +1 -0
  119. package/dist/utils/single-line.js +30 -0
  120. package/dist/utils/single-line.js.map +1 -0
  121. package/dist/web/agent-inbox-persistence.d.ts +52 -0
  122. package/dist/web/agent-inbox-persistence.d.ts.map +1 -0
  123. package/dist/web/agent-inbox-persistence.js +139 -0
  124. package/dist/web/agent-inbox-persistence.js.map +1 -0
  125. package/dist/web/agent-inbox.d.ts +140 -0
  126. package/dist/web/agent-inbox.d.ts.map +1 -0
  127. package/dist/web/agent-inbox.js +258 -0
  128. package/dist/web/agent-inbox.js.map +1 -0
  129. package/dist/web/approval-inbox.d.ts +6 -0
  130. package/dist/web/approval-inbox.d.ts.map +1 -1
  131. package/dist/web/approval-inbox.js +2 -2
  132. package/dist/web/approval-inbox.js.map +1 -1
  133. package/dist/web/middleware/auth.d.ts +2 -0
  134. package/dist/web/middleware/auth.d.ts.map +1 -1
  135. package/dist/web/middleware/auth.js +145 -52
  136. package/dist/web/middleware/auth.js.map +1 -1
  137. package/dist/web/plan-usage-latest.d.ts +2 -1
  138. package/dist/web/plan-usage-latest.d.ts.map +1 -1
  139. package/dist/web/plan-usage-latest.js +12 -2
  140. package/dist/web/plan-usage-latest.js.map +1 -1
  141. package/dist/web/ports/index.d.ts +1 -0
  142. package/dist/web/ports/index.d.ts.map +1 -1
  143. package/dist/web/ports/keep-warm-port.d.ts +9 -0
  144. package/dist/web/ports/keep-warm-port.d.ts.map +1 -0
  145. package/dist/web/ports/keep-warm-port.js +6 -0
  146. package/dist/web/ports/keep-warm-port.js.map +1 -0
  147. package/dist/web/ports/session-port.d.ts +3 -1
  148. package/dist/web/ports/session-port.d.ts.map +1 -1
  149. package/dist/web/public/admin-ui.js.gz +0 -0
  150. package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
  151. package/dist/web/public/app.42d0abae.js +43 -0
  152. package/dist/web/public/app.42d0abae.js.br +0 -0
  153. package/dist/web/public/app.42d0abae.js.gz +0 -0
  154. package/dist/web/public/approvals-ui.js.gz +0 -0
  155. package/dist/web/public/{constants.e5e588db.js → constants.0b3cdde9.js} +60 -1
  156. package/dist/web/public/constants.0b3cdde9.js.br +0 -0
  157. package/dist/web/public/constants.0b3cdde9.js.gz +0 -0
  158. package/dist/web/public/cron-ui.js.gz +0 -0
  159. package/dist/web/public/entrance-animations.js.gz +0 -0
  160. package/dist/web/public/git-status-ui.js.gz +0 -0
  161. package/dist/web/public/header-divider.eb2d2463.js +1 -0
  162. package/dist/web/public/header-divider.eb2d2463.js.br +0 -0
  163. package/dist/web/public/header-divider.eb2d2463.js.gz +0 -0
  164. package/dist/web/public/home-sessions.js.gz +0 -0
  165. package/dist/web/public/host-wake-ui.js.gz +0 -0
  166. package/dist/web/public/i18n.1e68220d.js +2 -0
  167. package/dist/web/public/i18n.1e68220d.js.br +0 -0
  168. package/dist/web/public/i18n.1e68220d.js.gz +0 -0
  169. package/dist/web/public/image-input.941386e7.js.gz +0 -0
  170. package/dist/web/public/index.html +162 -14
  171. package/dist/web/public/index.html.br +0 -0
  172. package/dist/web/public/index.html.gz +0 -0
  173. package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
  174. package/dist/web/public/{keyboard-accessory.c283e827.js → keyboard-accessory.4e8b20ac.js} +23 -5
  175. package/dist/web/public/keyboard-accessory.4e8b20ac.js.br +0 -0
  176. package/dist/web/public/keyboard-accessory.4e8b20ac.js.gz +0 -0
  177. package/dist/web/public/{mobile-handlers.0ef9c311.js → mobile-handlers.1c0cbcd8.js} +50 -16
  178. package/dist/web/public/mobile-handlers.1c0cbcd8.js.br +0 -0
  179. package/dist/web/public/mobile-handlers.1c0cbcd8.js.gz +0 -0
  180. package/dist/web/public/mobile-ime-preview.2dbaf262.js.gz +0 -0
  181. package/dist/web/public/mobile-overview.js.gz +0 -0
  182. package/dist/web/public/mobile.12fb18de.css +1 -0
  183. package/dist/web/public/mobile.12fb18de.css.br +0 -0
  184. package/dist/web/public/mobile.12fb18de.css.gz +0 -0
  185. package/dist/web/public/notification-manager.feb82c04.js.gz +0 -0
  186. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  187. package/dist/web/public/{panels-ui.b7bfb9da.js → panels-ui.78c3defb.js} +19 -13
  188. package/dist/web/public/panels-ui.78c3defb.js.br +0 -0
  189. package/dist/web/public/panels-ui.78c3defb.js.gz +0 -0
  190. package/dist/web/public/ralph-panel.b350e2ef.js.gz +0 -0
  191. package/dist/web/public/ralph-wizard.b6c0dd19.js.gz +0 -0
  192. package/dist/web/public/readmymind-ui.js.gz +0 -0
  193. package/dist/web/public/reboot-restore-ui.js.gz +0 -0
  194. package/dist/web/public/respawn-ui.d7adcf6a.js.gz +0 -0
  195. package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
  196. package/dist/web/public/session-lineage.js.gz +0 -0
  197. package/dist/web/public/{session-ui.be076c88.js → session-ui.ea6b1994.js} +33 -27
  198. package/dist/web/public/session-ui.ea6b1994.js.br +0 -0
  199. package/dist/web/public/session-ui.ea6b1994.js.gz +0 -0
  200. package/dist/web/public/settings-ui.085dd202.js +106 -0
  201. package/dist/web/public/settings-ui.085dd202.js.br +0 -0
  202. package/dist/web/public/settings-ui.085dd202.js.gz +0 -0
  203. package/dist/web/public/spreadsheet-preview-worker.js.gz +0 -0
  204. package/dist/web/public/spreadsheet-preview.75c751de.js.gz +0 -0
  205. package/dist/web/public/spreadsheet-xlsx-core.js.gz +0 -0
  206. package/dist/web/public/styles.3b59b41d.css +1 -0
  207. package/dist/web/public/styles.3b59b41d.css.br +0 -0
  208. package/dist/web/public/styles.3b59b41d.css.gz +0 -0
  209. package/dist/web/public/subagent-windows.07277a58.js.gz +0 -0
  210. package/dist/web/public/sw.js +2 -2
  211. package/dist/web/public/sw.js.br +0 -0
  212. package/dist/web/public/sw.js.gz +0 -0
  213. package/dist/web/public/tab-layout-browser.2d6189f7.js.gz +0 -0
  214. package/dist/web/public/tab-rail-resize.7157e0bd.js.gz +0 -0
  215. package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.gz +0 -0
  216. package/dist/web/public/terminal-split.js.gz +0 -0
  217. package/dist/web/public/terminal-tile.js +49 -23
  218. package/dist/web/public/terminal-tile.js.br +0 -0
  219. package/dist/web/public/terminal-tile.js.gz +0 -0
  220. package/dist/web/public/terminal-ui.fb2a27f5.js +2 -0
  221. package/dist/web/public/terminal-ui.fb2a27f5.js.br +0 -0
  222. package/dist/web/public/terminal-ui.fb2a27f5.js.gz +0 -0
  223. package/dist/web/public/tile-grid.js.gz +0 -0
  224. package/dist/web/public/ultracode-panel.js.gz +0 -0
  225. package/dist/web/public/ultracode-windows.js.gz +0 -0
  226. package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
  227. package/dist/web/public/vendor/exceljs.min.js.gz +0 -0
  228. package/dist/web/public/vendor/fflate.min.js.gz +0 -0
  229. package/dist/web/public/vendor/marked.min.js.gz +0 -0
  230. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  231. package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
  232. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  233. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  234. package/dist/web/public/vendor/xterm-predictive-echo.ae5e3d5d.js.gz +0 -0
  235. package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.gz +0 -0
  236. package/dist/web/public/vendor/xterm.css.gz +0 -0
  237. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  238. package/dist/web/public/voice-input.2342c37b.js.gz +0 -0
  239. package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
  240. package/dist/web/public/webview-tabs.js.gz +0 -0
  241. package/dist/web/public/whats-new.json +9 -9
  242. package/dist/web/route-helpers.d.ts +57 -6
  243. package/dist/web/route-helpers.d.ts.map +1 -1
  244. package/dist/web/route-helpers.js +72 -4
  245. package/dist/web/route-helpers.js.map +1 -1
  246. package/dist/web/routes/admin-routes.d.ts +2 -1
  247. package/dist/web/routes/admin-routes.d.ts.map +1 -1
  248. package/dist/web/routes/admin-routes.js +3 -0
  249. package/dist/web/routes/admin-routes.js.map +1 -1
  250. package/dist/web/routes/case-routes.d.ts +2 -2
  251. package/dist/web/routes/case-routes.d.ts.map +1 -1
  252. package/dist/web/routes/case-routes.js +263 -4
  253. package/dist/web/routes/case-routes.js.map +1 -1
  254. package/dist/web/routes/config-backup-routes.d.ts +54 -0
  255. package/dist/web/routes/config-backup-routes.d.ts.map +1 -0
  256. package/dist/web/routes/config-backup-routes.js +268 -0
  257. package/dist/web/routes/config-backup-routes.js.map +1 -0
  258. package/dist/web/routes/custom-model-routes.d.ts +17 -1
  259. package/dist/web/routes/custom-model-routes.d.ts.map +1 -1
  260. package/dist/web/routes/custom-model-routes.js +118 -13
  261. package/dist/web/routes/custom-model-routes.js.map +1 -1
  262. package/dist/web/routes/hook-event-routes.d.ts.map +1 -1
  263. package/dist/web/routes/hook-event-routes.js +26 -5
  264. package/dist/web/routes/hook-event-routes.js.map +1 -1
  265. package/dist/web/routes/inbox-routes.d.ts +43 -0
  266. package/dist/web/routes/inbox-routes.d.ts.map +1 -0
  267. package/dist/web/routes/inbox-routes.js +148 -0
  268. package/dist/web/routes/inbox-routes.js.map +1 -0
  269. package/dist/web/routes/index.d.ts +2 -0
  270. package/dist/web/routes/index.d.ts.map +1 -1
  271. package/dist/web/routes/index.js +2 -0
  272. package/dist/web/routes/index.js.map +1 -1
  273. package/dist/web/routes/ralph-routes.js +2 -2
  274. package/dist/web/routes/ralph-routes.js.map +1 -1
  275. package/dist/web/routes/reboot-restore-routes.d.ts.map +1 -1
  276. package/dist/web/routes/reboot-restore-routes.js +2 -0
  277. package/dist/web/routes/reboot-restore-routes.js.map +1 -1
  278. package/dist/web/routes/session-routes.d.ts +2 -2
  279. package/dist/web/routes/session-routes.d.ts.map +1 -1
  280. package/dist/web/routes/session-routes.js +110 -61
  281. package/dist/web/routes/session-routes.js.map +1 -1
  282. package/dist/web/routes/status-telemetry-routes.d.ts +2 -2
  283. package/dist/web/routes/status-telemetry-routes.d.ts.map +1 -1
  284. package/dist/web/routes/status-telemetry-routes.js +8 -4
  285. package/dist/web/routes/status-telemetry-routes.js.map +1 -1
  286. package/dist/web/routes/system-routes.d.ts +2 -2
  287. package/dist/web/routes/system-routes.d.ts.map +1 -1
  288. package/dist/web/routes/system-routes.js +30 -2
  289. package/dist/web/routes/system-routes.js.map +1 -1
  290. package/dist/web/routes/webview-routes.d.ts.map +1 -1
  291. package/dist/web/routes/webview-routes.js +1 -0
  292. package/dist/web/routes/webview-routes.js.map +1 -1
  293. package/dist/web/schemas.d.ts +45 -0
  294. package/dist/web/schemas.d.ts.map +1 -1
  295. package/dist/web/schemas.js +79 -2
  296. package/dist/web/schemas.js.map +1 -1
  297. package/dist/web/sensitive-path.d.ts.map +1 -1
  298. package/dist/web/sensitive-path.js +2 -0
  299. package/dist/web/sensitive-path.js.map +1 -1
  300. package/dist/web/server.d.ts +14 -2
  301. package/dist/web/server.d.ts.map +1 -1
  302. package/dist/web/server.js +176 -7
  303. package/dist/web/server.js.map +1 -1
  304. package/dist/web/session-listener-wiring.d.ts +6 -0
  305. package/dist/web/session-listener-wiring.d.ts.map +1 -1
  306. package/dist/web/session-listener-wiring.js +10 -3
  307. package/dist/web/session-listener-wiring.js.map +1 -1
  308. package/dist/web/session-wait-registry.d.ts +48 -4
  309. package/dist/web/session-wait-registry.d.ts.map +1 -1
  310. package/dist/web/session-wait-registry.js +144 -6
  311. package/dist/web/session-wait-registry.js.map +1 -1
  312. package/dist/web/sse-events.d.ts +9 -3
  313. package/dist/web/sse-events.d.ts.map +1 -1
  314. package/dist/web/sse-events.js +9 -3
  315. package/dist/web/sse-events.js.map +1 -1
  316. package/dist/web/webview-proxy.d.ts +8 -3
  317. package/dist/web/webview-proxy.d.ts.map +1 -1
  318. package/dist/web/webview-proxy.js +23 -5
  319. package/dist/web/webview-proxy.js.map +1 -1
  320. package/package.json +1 -1
  321. package/skills/codeman/SKILL.md +27 -13
  322. package/skills/codeman/preamble.sh +15 -5
  323. package/skills/codeman/reference/endpoints.md +32 -10
  324. package/skills/codeman/reference/recipes.md +1 -1
  325. package/skills/codeman/reference/verbs.md +68 -13
  326. package/dist/web/public/app.ae50029a.js +0 -43
  327. package/dist/web/public/app.ae50029a.js.br +0 -0
  328. package/dist/web/public/app.ae50029a.js.gz +0 -0
  329. package/dist/web/public/constants.e5e588db.js.br +0 -0
  330. package/dist/web/public/constants.e5e588db.js.gz +0 -0
  331. package/dist/web/public/i18n.8f291f06.js +0 -2
  332. package/dist/web/public/i18n.8f291f06.js.br +0 -0
  333. package/dist/web/public/i18n.8f291f06.js.gz +0 -0
  334. package/dist/web/public/keyboard-accessory.c283e827.js.br +0 -0
  335. package/dist/web/public/keyboard-accessory.c283e827.js.gz +0 -0
  336. package/dist/web/public/mobile-handlers.0ef9c311.js.br +0 -0
  337. package/dist/web/public/mobile-handlers.0ef9c311.js.gz +0 -0
  338. package/dist/web/public/mobile.13514863.css +0 -1
  339. package/dist/web/public/mobile.13514863.css.br +0 -0
  340. package/dist/web/public/mobile.13514863.css.gz +0 -0
  341. package/dist/web/public/panels-ui.b7bfb9da.js.br +0 -0
  342. package/dist/web/public/panels-ui.b7bfb9da.js.gz +0 -0
  343. package/dist/web/public/session-ui.be076c88.js.br +0 -0
  344. package/dist/web/public/session-ui.be076c88.js.gz +0 -0
  345. package/dist/web/public/settings-ui.fc4cc50a.js +0 -97
  346. package/dist/web/public/settings-ui.fc4cc50a.js.br +0 -0
  347. package/dist/web/public/settings-ui.fc4cc50a.js.gz +0 -0
  348. package/dist/web/public/styles.dcfa907f.css +0 -1
  349. package/dist/web/public/styles.dcfa907f.css.br +0 -0
  350. package/dist/web/public/styles.dcfa907f.css.gz +0 -0
  351. package/dist/web/public/terminal-ui.ae01a7d1.js +0 -2
  352. package/dist/web/public/terminal-ui.ae01a7d1.js.br +0 -0
  353. package/dist/web/public/terminal-ui.ae01a7d1.js.gz +0 -0
@@ -16,8 +16,8 @@
16
16
  <link rel="manifest" href="manifest.json">
17
17
  <title>Codeman</title>
18
18
  <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0%25' y1='0%25' x2='100%25' y2='100%25'%3E%3Cstop offset='0%25' stop-color='%2360a5fa'/%3E%3Cstop offset='100%25' stop-color='%233b82f6'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='32' height='32' rx='6' fill='%230a0a0a'/%3E%3Cpath d='M18 4L8 18h6l-2 10 10-14h-6z' fill='url(%23g)'/%3E%3C/svg%3E">
19
- <link rel="stylesheet" href="styles.dcfa907f.css">
20
- <link rel="stylesheet" href="mobile.13514863.css" media="(max-width: 1023px)">
19
+ <link rel="stylesheet" href="styles.3b59b41d.css">
20
+ <link rel="stylesheet" href="mobile.12fb18de.css" media="(max-width: 1023px)">
21
21
  <!-- xterm.css loaded async — terminal won't display until xterm.js runs anyway -->
22
22
  <link rel="preload" href="vendor/xterm.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
23
23
  <noscript><link rel="stylesheet" href="vendor/xterm.css"></noscript>
@@ -27,8 +27,8 @@
27
27
  <!-- Symbols font before the terminal first paints — a late-loading icon font
28
28
  leaves tofu in xterm's glyph atlas until something forces a re-render. -->
29
29
  <link rel="preload" href="fonts/symbols-nerd-font-mono.woff2" as="font" type="font/woff2" crossorigin>
30
- <link rel="preload" href="constants.e5e588db.js" as="script">
31
- <link rel="preload" href="app.ae50029a.js" as="script">
30
+ <link rel="preload" href="constants.0b3cdde9.js" as="script">
31
+ <link rel="preload" href="app.42d0abae.js" as="script">
32
32
  <!-- Self-hosted xterm.js — eliminates CDN DNS/TLS latency (~100ms).
33
33
  'defer' preserves execution order (xterm loads before fit addon). -->
34
34
  <script defer src="vendor/xterm.min.js"></script>
@@ -178,6 +178,30 @@
178
178
  </div>
179
179
  <span class="stat-value" id="statMem">--</span>
180
180
  </div>
181
+ <div class="stat-item stat-item--host" id="statGpuItem" hidden>
182
+ <span class="stat-ring" id="statGpuRing" aria-hidden="true"></span>
183
+ <span class="stat-label">GPU</span>
184
+ <div class="stat-bar">
185
+ <div class="stat-bar-fill stat-bar-cpu" id="statGpuBar"></div>
186
+ </div>
187
+ <span class="stat-value" id="statGpu">--%</span>
188
+ </div>
189
+ <div class="stat-item stat-item--host" id="statVramItem" hidden>
190
+ <span class="stat-ring" id="statVramRing" aria-hidden="true"></span>
191
+ <span class="stat-label">VRAM</span>
192
+ <div class="stat-bar">
193
+ <div class="stat-bar-fill stat-bar-cpu" id="statVramBar"></div>
194
+ </div>
195
+ <span class="stat-value" id="statVram">--%</span>
196
+ </div>
197
+ <div class="stat-item stat-item--host stat-item--ringless" id="statGpuMhzItem" hidden>
198
+ <span class="stat-label">GPU</span>
199
+ <span class="stat-value" id="statGpuMhz">-- MHz</span>
200
+ </div>
201
+ <div class="stat-item stat-item--host stat-item--ringless" id="statCpuMhzItem" hidden>
202
+ <span class="stat-label">CPU</span>
203
+ <span class="stat-value" id="statCpuMhz">-- MHz</span>
204
+ </div>
181
205
  </div>
182
206
  <button class="btn-icon-header btn-redraw-terminal btn-redraw-terminal--hidden" onclick="app.restoreTerminalSize()" title="Redraw terminal to fit current screen (Ctrl+Shift+R)" aria-label="Redraw terminal"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="1 4 1 10 7 10"/><polyline points="23 20 23 14 17 14"/><path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15"/></svg></button>
183
207
  <button class="btn-icon-header btn-response-viewer-header btn-response-viewer-header--hidden" onclick="app.toggleResponseViewer()" title="View last response" aria-label="View last response"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></button>
@@ -197,7 +221,7 @@
197
221
  <button class="btn-icon-header btn-split btn-split--hidden" onclick="app.openSplitPicker(event)" title="Split: open a second session beside this one" aria-label="Split: open a second session beside this one" aria-pressed="false"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2" y="3" width="20" height="18" rx="2"/><line x1="12" y1="3" x2="12" y2="21"/></svg></button>
198
222
  <button class="btn-icon-header btn-tile-grid btn-tile-grid--hidden" onclick="app.toggleTileGrid()" oncontextmenu="app.openTileCountMenu(event)" aria-describedby="tileGridHint" aria-label="Tiles: show several sessions side by side (right-click for how many)" aria-pressed="false"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="3" width="8" height="8" rx="1"/><rect x="13" y="3" width="8" height="8" rx="1"/><rect x="3" y="13" width="8" height="8" rx="1"/><rect x="13" y="13" width="8" height="8" rx="1"/></svg></button>
199
223
  <button class="btn-icon-header btn-ultracode-agents btn-ultracode-agents--hidden" onclick="app.toggleUltracodeAgentsPanel()" title="Ultracode / Workflow agents" aria-label="Open ultracode workflow agents"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><circle cx="18" cy="12" r="2.5"/><path d="M8.2 7.2 15.6 11M8.2 16.8 15.6 13"/></svg></button>
200
- <div class="header-plan-usage header-plan-usage--hidden" id="planUsageChip" title="Claude and Codex plan usage limits">—</div>
224
+ <div class="header-plan-usage header-plan-usage--hidden" id="planUsageChip" title="Claude, Codex and Copilot plan usage limits">—</div>
201
225
  <button class="btn-icon-header btn-notifications" onclick="app.toggleNotifications()" title="Notifications" aria-label="Toggle notifications" style="display:none;">
202
226
  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
203
227
  <span class="notification-badge" id="notifBadge" style="display:none;">0</span>
@@ -614,6 +638,8 @@
614
638
  <div class="file-preview-header">
615
639
  <span class="file-preview-title" id="filePreviewTitle">file.ts</span>
616
640
  <div class="file-preview-actions">
641
+ <button class="btn-icon-sm" id="filePreviewBackBtn" onclick="app.stepFilePreviewHistory(-1)" title="Back (Alt+←)" aria-label="Back to the previous file" hidden disabled>&larr;</button>
642
+ <button class="btn-icon-sm" id="filePreviewForwardBtn" onclick="app.stepFilePreviewHistory(1)" title="Forward (Alt+→)" aria-label="Forward to the next file" hidden disabled>&rarr;</button>
617
643
  <button class="btn-icon-sm" id="filePreviewPrevBtn" onclick="app.stepFolderPreview(-1)" title="Previous file in folder (←)" aria-label="Previous file in folder" hidden>&lsaquo;</button>
618
644
  <button class="btn-icon-sm" id="filePreviewNextBtn" onclick="app.stepFolderPreview(1)" title="Next file in folder (→)" aria-label="Next file in folder" hidden>&rsaquo;</button>
619
645
  <button class="btn-icon-sm" id="filePreviewFolderBtn" onclick="app.openFolderOfPreview()" title="Show folder" aria-label="Show folder" hidden><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg></button>
@@ -624,6 +650,7 @@
624
650
  <button class="btn-icon-sm file-preview-edit-btn" id="filePreviewEditBtn" onclick="app.enterFilePreviewEdit()" title="Edit file" aria-label="Edit file" hidden><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5z"/></svg></button>
625
651
  <button class="btn-icon-sm" onclick="app.copyFilePreviewContent()" title="Copy content">&#x2398;</button>
626
652
  <button class="btn-icon-sm" id="filePreviewDetachBtn" onclick="app.detachFilePreview()" title="Open in new tab" aria-label="Open in new tab" hidden><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg></button>
653
+ <button class="btn-icon-sm" id="filePreviewExpandBtn" onclick="app.toggleFilePreviewExpanded()" title="Expand" aria-label="Expand" aria-pressed="false"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg></button>
627
654
  <button class="btn-icon-sm" onclick="app.closeFilePreview()" title="Close">&times;</button>
628
655
  </div>
629
656
  </div>
@@ -635,6 +662,7 @@
635
662
  <button class="file-preview-editbar-btn file-preview-editbar-btn--save" id="filePreviewSaveBtn" onclick="app.saveFilePreviewEdit()" disabled>Save</button>
636
663
  </div>
637
664
  <div class="file-preview-footer" id="filePreviewFooter"></div>
665
+ <div class="file-preview-resize" id="filePreviewResize" title="Drag to resize" aria-hidden="true"></div>
638
666
  </div>
639
667
  </div>
640
668
 
@@ -774,6 +802,11 @@
774
802
  <span>1M Opus Context</span>
775
803
  </label>
776
804
  <span class="form-hint">Use 1M token context window for new sessions</span>
805
+ <label class="case-default-group-label" for="caseDefaultGroup">Default session group</label>
806
+ <select id="caseDefaultGroup" class="case-default-group-select" onchange="app.onCaseDefaultGroupChanged(this)">
807
+ <option value="">Ungrouped</option>
808
+ </select>
809
+ <span class="form-hint">New sessions for this case land in this group</span>
777
810
  </div>
778
811
  </div>
779
812
  <!-- Mobile-only case button + gear -->
@@ -818,6 +851,11 @@
818
851
  <span>1M Opus Context</span>
819
852
  </label>
820
853
  <span class="form-hint">Use 1M token context window</span>
854
+ <label class="case-default-group-label" for="caseDefaultGroupMobile">Default session group</label>
855
+ <select id="caseDefaultGroupMobile" class="case-default-group-select" onchange="app.onCaseDefaultGroupChanged(this)">
856
+ <option value="">Ungrouped</option>
857
+ </select>
858
+ <span class="form-hint">New sessions for this case land in this group</span>
821
859
  </div>
822
860
  </div>
823
861
 
@@ -922,6 +960,7 @@
922
960
  <div><kbd>Ctrl</kbd>+<kbd>?</kbd></div><div>Show Shortcuts</div>
923
961
  <div><kbd>Alt/Option</kbd>+<kbd>?</kbd></div><div>Show Shortcuts</div>
924
962
  <div><kbd>Escape</kbd></div><div>Close Panels</div>
963
+ <div><kbd>Alt/Option</kbd>+<kbd>ArrowLeft</kbd> / <kbd>Alt/Option</kbd>+<kbd>ArrowRight</kbd></div><div>File Viewer Back / Forward</div>
925
964
  </div>
926
965
  </section>
927
966
  </div>
@@ -1334,7 +1373,18 @@
1334
1373
  <div class="set-row-text">
1335
1374
  <span class="set-row-label">Status</span>
1336
1375
  <span class="set-row-desc" id="promptCacheStatus" data-i18n-skip>Not reported yet.</span>
1376
+ <span class="set-row-desc" id="keepWarmStatus" data-i18n-skip hidden></span>
1377
+ </div>
1378
+ </div>
1379
+ <!-- Per-session opt-in for the keep-alive nudge (prompt-cache-keepwarm.ts);
1380
+ the default for sessions that have not chosen lives in App Settings →
1381
+ Automation. Its status shares the Status row above: session-ui.js updateKeepWarmStatus. -->
1382
+ <div class="set-row">
1383
+ <div class="set-row-text">
1384
+ <span class="set-row-label">Keep the cache warm while idle</span>
1385
+ <span class="set-row-desc">Sends a one-line keep-alive just before the cache expires, so your next prompt still reads from cache. Runs only while idle, up to the limit in App Settings &rarr; System &rarr; Automation; switch on before launch to also stop Claude Code's own idle compaction.</span>
1337
1386
  </div>
1387
+ <label class="switch switch-sm"><input type="checkbox" id="modalKeepWarmEnabled" onchange="app.autoSaveKeepWarm()"><span class="slider"></span></label>
1338
1388
  </div>
1339
1389
  </div>
1340
1390
  </div>
@@ -2071,6 +2121,8 @@
2071
2121
  <div class="set-chips" data-search="header buttons plan usage font stats lifecycle response file viewer attachments monitor session away cron redraw split tiles">
2072
2122
  <label class="set-chip" data-preview="header" data-preview-order="1" data-preview-text="A+"><input type="checkbox" id="appSettingsShowFontControls"><svg class="set-chip-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 20 10 5l6 15"/><path d="M6.5 15h7"/><path d="M18 12h4M20 10v4"/></svg><span>Font Size</span></label>
2073
2123
  <label class="set-chip" data-preview="header" data-preview-order="2" data-preview-text="CPU 12%"><input type="checkbox" id="appSettingsShowSystemStats" checked><svg class="set-chip-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 12h4l2.5-7 4 14L16 12h5"/></svg><span>System Stats</span></label>
2124
+ <label class="set-chip" data-preview="header" data-preview-order="2" data-preview-text="GPU 8%"><input type="checkbox" id="appSettingsShowGpuStats"><svg class="set-chip-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="7" width="18" height="10" rx="2"/><path d="M7 21v-4M12 21v-4M17 21v-4M7 7V3M17 7V3"/></svg><span>GPU Stats</span></label>
2125
+ <label class="set-chip" data-preview="header" data-preview-order="2" data-preview-text="3400 MHz"><input type="checkbox" id="appSettingsShowCpuMhz"><svg class="set-chip-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg><span>CPU MHz</span></label>
2074
2126
  <label class="set-chip" data-preview="header" data-preview-order="3"><input type="checkbox" id="appSettingsShowRedrawButton"><svg class="set-chip-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="1 4 1 10 7 10"/><polyline points="23 20 23 14 17 14"/><path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15"/></svg><span>Redraw Terminal</span></label>
2075
2127
  <label class="set-chip" data-preview="header" data-preview-order="4"><input type="checkbox" id="appSettingsShowResponseViewer"><svg class="set-chip-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg><span>Response Viewer</span></label>
2076
2128
  <label class="set-chip" data-preview="header" data-preview-order="5"><input type="checkbox" id="appSettingsShowAwayDigestButton"><svg class="set-chip-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 6h13"/><path d="M8 12h13"/><path d="M8 18h13"/><path d="M3 6h.01"/><path d="M3 12h.01"/><path d="M3 18h.01"/></svg><span>Away Digest</span></label>
@@ -2119,6 +2171,13 @@
2119
2171
  <label class="set-chip" data-preview="header" data-preview-order="12"><input type="checkbox" id="appSettingsShowUltracodeAgents"><svg class="set-chip-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><circle cx="18" cy="12" r="2.5"/><path d="M8.2 7.2 15.6 11M8.2 16.8 15.6 13"/></svg><span>Ultracode Agents</span></label>
2120
2172
  <label class="set-chip" data-preview="float" data-preview-order="1"><input type="checkbox" id="appSettingsUltracodeFloatingWindows"><svg class="set-chip-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M3 9h18"/><circle cx="6" cy="6.5" r="0.6"/></svg><span>Ultracode Windows</span></label>
2121
2173
  </div>
2174
+ <div class="set-row" data-search="agent inbox messages persist restart disk codeman agent post">
2175
+ <div class="set-row-text">
2176
+ <span class="set-row-label">Keep agent inbox across restarts</span>
2177
+ <span class="set-row-desc">Saves pending <code>codeman agent post</code> messages to <code>agent-inbox.json</code> in the data dir (readable by you only), so they survive a server restart. Off by default; turning it off deletes the file. Messages expire after 12 hours either way.</span>
2178
+ </div>
2179
+ <label class="switch switch-sm"><input type="checkbox" id="appSettingsAgentInboxPersist"><span class="slider"></span></label>
2180
+ </div>
2122
2181
  </div>
2123
2182
  </div>
2124
2183
 
@@ -3242,6 +3301,48 @@
3242
3301
  </div>
3243
3302
  </div>
3244
3303
 
3304
+ <div class="set-group" id="configBackupGroup">
3305
+ <div class="set-group-head"><h4>Config backups</h4><span class="set-scope">server</span></div>
3306
+ <div class="set-group-body">
3307
+ <div class="set-row" data-search="config backup snapshot settings clis restore retention keep">
3308
+ <div class="set-row-text">
3309
+ <span class="set-row-label">Back up my configuration</span>
3310
+ <span class="set-row-desc">Keeps timestamped copies of your settings, CLI overrides, custom endpoints, webhook, linked cases and (in multi-user mode) accounts. A copy is made at startup and whenever one of them changes. Some of these files hold credentials, so each copy is private to this user (mode 0700/0600).</span>
3311
+ </div>
3312
+ <label class="switch switch-sm"><input type="checkbox" id="appSettingsConfigBackup"><span class="slider"></span></label>
3313
+ </div>
3314
+ <div class="set-row has-field" data-search="config backup folder location path directory">
3315
+ <div class="set-row-text">
3316
+ <span class="set-row-label">Backup folder</span>
3317
+ <span class="set-row-desc">An absolute path (a leading <code>~</code> is expanded). Leave empty for the default shown. Only folders Codeman created there are ever pruned.</span>
3318
+ </div>
3319
+ <input type="text" id="appSettingsConfigBackupDir" class="set-input" placeholder="default: ~/.codeman/backups/config" data-i18n-skip>
3320
+ </div>
3321
+ <div class="set-row has-field" data-search="config backup retention keep count snapshots">
3322
+ <div class="set-row-text">
3323
+ <span class="set-row-label">Keep this many backups</span>
3324
+ <span class="set-row-desc">2 to 500 (with 1, every change would delete the state before it). The newest backup is always kept.</span>
3325
+ </div>
3326
+ <input type="number" id="appSettingsConfigBackupKeepCount" oninput="this.dataset.touched=1" class="set-input" min="2" max="500" step="1" placeholder="20">
3327
+ </div>
3328
+ <div class="set-row has-field" data-search="config backup retention keep days age">
3329
+ <div class="set-row-text">
3330
+ <span class="set-row-label">Delete backups older than (days)</span>
3331
+ <span class="set-row-desc">A backup is removed once a newer one has existed this many days. 0 keeps backups until the count above pushes them out.</span>
3332
+ </div>
3333
+ <input type="number" id="appSettingsConfigBackupKeepDays" oninput="this.dataset.touched=1" class="set-input" min="0" max="3650" step="1" placeholder="30">
3334
+ </div>
3335
+ <div class="set-row" data-search="config backup now restore list">
3336
+ <div class="set-row-text">
3337
+ <span class="set-row-label">Backups</span>
3338
+ <span class="set-row-desc">Folder and retention changes apply after you save. Restoring puts a backup's files back and makes a copy of the current ones first. Compare shows what changed between two backups, or between a backup and the running config; credential values are never shown.</span>
3339
+ </div>
3340
+ <button class="btn-toolbar btn-sm btn-primary" id="configBackupNowBtn" onclick="app.backupConfigNow()">Back up now</button>
3341
+ </div>
3342
+ <div id="configBackupList" class="set-note" data-i18n-skip>Loading…</div>
3343
+ </div>
3344
+ </div>
3345
+
3245
3346
  <div class="set-group">
3246
3347
  <div class="set-group-head"><h4>Automation</h4><span class="set-scope">synced</span></div>
3247
3348
  <div class="set-group-body">
@@ -3252,6 +3353,23 @@
3252
3353
  </div>
3253
3354
  <label class="switch switch-sm"><input type="checkbox" id="appSettingsImageWatcherEnabled"><span class="slider"></span></label>
3254
3355
  </div>
3356
+ <div class="set-row" data-search="prompt cache keep warm keep-alive nudge idle expire">
3357
+ <div class="set-row-text">
3358
+ <span class="set-row-label">Keep prompt caches warm</span>
3359
+ <span class="set-row-desc">Default for Claude sessions that have not chosen on their Respawn tab (a session an agent started needs its own switch): shortly before an idle session's prompt cache would expire, send a one-line keep-alive turn so the next prompt still reads the conversation from cache instead of re-processing it.</span>
3360
+ </div>
3361
+ <label class="switch switch-sm"><input type="checkbox" id="appSettingsPromptCacheKeepWarm"><span class="slider"></span></label>
3362
+ </div>
3363
+ <div class="set-row" data-search="prompt cache keep warm hours limit cap window">
3364
+ <div class="set-row-text">
3365
+ <span class="set-row-label">Keep warm for at most</span>
3366
+ <span class="set-row-desc">Hours after your last prompt in a session during which keep-alives are sent; past that the cache is left to expire. A keep-alive costs a small fraction of the re-write it prevents, so a few hours of them pay off, an overnight gap does not.</span>
3367
+ </div>
3368
+ <div class="set-row-actions">
3369
+ <input type="number" id="appSettingsPromptCacheKeepWarmMaxHours" class="set-num" min="0.5" max="24" step="0.5" value="2">
3370
+ <span class="set-unit">hours</span>
3371
+ </div>
3372
+ </div>
3255
3373
  </div>
3256
3374
  </div>
3257
3375
 
@@ -3707,6 +3825,35 @@
3707
3825
  </div>
3708
3826
  </div>
3709
3827
 
3828
+ <!-- Rename a case (and its folder): opened by the Manage tab's pencil button, see renameCase() in session-ui.js.
3829
+ Placed after the case modal so it stacks above it. -->
3830
+ <div class="modal" id="renameCaseModal">
3831
+ <div class="modal-backdrop" onclick="app.closeRenameCase()"></div>
3832
+ <div class="modal-content modal-sm">
3833
+ <div class="modal-header">
3834
+ <h3>Rename case</h3>
3835
+ <button class="modal-close" onclick="app.closeRenameCase()" aria-label="Cancel">&times;</button>
3836
+ </div>
3837
+ <div class="modal-body">
3838
+ <div class="form-row">
3839
+ <label for="renameCaseInput" id="renameCaseLabel">New name</label>
3840
+ <input type="text" id="renameCaseInput" class="set-input" maxlength="100" autocomplete="off" spellcheck="false"
3841
+ placeholder="letters, numbers, - and _" onkeydown="if (event.key === 'Enter') app.submitRenameCase()">
3842
+ </div>
3843
+ <div class="form-row hidden" id="renameCaseFolderRow">
3844
+ <label class="checkbox-row"><input type="checkbox" id="renameCaseFolder"> Also rename the folder on disk</label>
3845
+ <span class="form-hint" id="renameCaseFolderHint" data-i18n-skip></span>
3846
+ </div>
3847
+ <p class="form-hint" id="renameCaseNote">A case under the cases folder is renamed together with its folder.</p>
3848
+ <p class="form-hint hidden" id="renameCaseError" role="alert" style="color: var(--danger, #e5534b);"></p>
3849
+ </div>
3850
+ <div class="modal-footer">
3851
+ <button class="btn-toolbar" onclick="app.closeRenameCase()">Cancel</button>
3852
+ <button class="btn-toolbar btn-primary" id="renameCaseSubmit" onclick="app.submitRenameCase()">Rename</button>
3853
+ </div>
3854
+ </div>
3855
+ </div>
3856
+
3710
3857
  <!-- Mobile Case Picker (Bottom Sheet) -->
3711
3858
  <div class="modal mobile-case-picker" id="mobileCasePickerModal">
3712
3859
  <div class="modal-backdrop" onclick="app.closeMobileCasePicker()"></div>
@@ -4243,12 +4390,12 @@
4243
4390
  <div class="approvals-list"></div>
4244
4391
  </div>
4245
4392
 
4246
- <script defer src="constants.e5e588db.js"></script>
4247
- <script defer src="i18n.8f291f06.js"></script>
4248
- <script defer src="mobile-handlers.0ef9c311.js"></script>
4393
+ <script defer src="constants.0b3cdde9.js"></script>
4394
+ <script defer src="i18n.1e68220d.js"></script>
4395
+ <script defer src="mobile-handlers.1c0cbcd8.js"></script>
4249
4396
  <script defer src="voice-input.2342c37b.js"></script>
4250
4397
  <script defer src="notification-manager.feb82c04.js"></script>
4251
- <script defer src="keyboard-accessory.c283e827.js"></script>
4398
+ <script defer src="keyboard-accessory.4e8b20ac.js"></script>
4252
4399
  <script defer src="input-cjk.8bc46081.js"></script>
4253
4400
  <!-- Shows iOS Safari IME composition text inside the terminal. Must precede terminal-ui.js. -->
4254
4401
  <script defer src="mobile-ime-preview.2dbaf262.js"></script>
@@ -4258,9 +4405,10 @@
4258
4405
  <script defer src="sanitize-html.e7147e76.js"></script>
4259
4406
  <!-- Owner tab layout projection (grouped vertical rail); pure, read by app.js. -->
4260
4407
  <script defer src="tab-layout-browser.2d6189f7.js"></script>
4261
- <script defer src="app.ae50029a.js"></script>
4408
+ <script defer src="app.42d0abae.js"></script>
4262
4409
  <script defer src="tab-rail-resize.7157e0bd.js"></script>
4263
- <script defer src="terminal-ui.ae01a7d1.js"></script>
4410
+ <script defer src="header-divider.eb2d2463.js"></script>
4411
+ <script defer src="terminal-ui.fb2a27f5.js"></script>
4264
4412
  <script defer src="terminal-tile.js"></script>
4265
4413
  <script defer src="terminal-split.js"></script>
4266
4414
  <script defer src="tile-grid.js"></script>
@@ -4268,14 +4416,14 @@
4268
4416
  <script defer src="ralph-panel.b350e2ef.js"></script>
4269
4417
  <script defer src="orchestrator-panel.js"></script>
4270
4418
  <script defer src="cron-ui.js"></script>
4271
- <script defer src="settings-ui.fc4cc50a.js"></script>
4272
- <script defer src="panels-ui.b7bfb9da.js"></script>
4419
+ <script defer src="settings-ui.085dd202.js"></script>
4420
+ <script defer src="panels-ui.78c3defb.js"></script>
4273
4421
  <script defer src="readmymind-ui.js"></script>
4274
4422
  <script defer src="ultracode-panel.js"></script>
4275
4423
  <script defer src="approvals-ui.js"></script>
4276
4424
  <script defer src="reboot-restore-ui.js"></script>
4277
4425
  <script defer src="admin-ui.js"></script>
4278
- <script defer src="session-ui.be076c88.js"></script>
4426
+ <script defer src="session-ui.ea6b1994.js"></script>
4279
4427
  <script defer src="host-wake-ui.js"></script>
4280
4428
  <script defer src="webview-tabs.js"></script>
4281
4429
  <script defer src="mobile-overview.js"></script>
Binary file
Binary file
@@ -647,6 +647,9 @@ const COMPOSER_INPUT_FRAME_LIMIT = 64 * 1024;
647
647
  const COMPOSER_PASTE_START = '\x1b[200~';
648
648
  const COMPOSER_PASTE_END = '\x1b[201~';
649
649
 
650
+ // Accessory keys that act on the terminal and leave the keyboard up.
651
+ const ACCESSORY_REFOCUS_ACTIONS = new Set(['scroll-up', 'scroll-down', 'arrow-left', 'arrow-right', 'tab', 'shift-tab', 'shift-left', 'shift-right', 'ctrl', 'ctrl-o', 'opt-enter', 'esc', 'effort-max', 'clear-input']);
652
+
650
653
  /**
651
654
  * KeyboardAccessoryBar - Quick action buttons shown above keyboard when typing.
652
655
  */
@@ -802,6 +805,21 @@ const KeyboardAccessoryBar = {
802
805
  this.syncCodexKeys();
803
806
  this._syncComposerDraftIndicator();
804
807
 
808
+ // A key that keeps the keyboard up must not take focus on press at all.
809
+ // Letting the tap blur the terminal and refocusing it in the click handler
810
+ // (kept below as the fallback) made every such key start a keyboard
811
+ // dismissal: a blur/focus pair per tap. Same pattern as the Attach input
812
+ // (image-input.js). A first tap on clear/compact only arms the confirm.
813
+ this.element.addEventListener('mousedown', (e) => {
814
+ const btn = e.target.closest('.accessory-btn');
815
+ if (!btn) return;
816
+ const action = btn.dataset.action;
817
+ if (ACCESSORY_REFOCUS_ACTIONS.has(action) ||
818
+ ((action === 'clear' || action === 'compact') && this._confirmAction !== action)) {
819
+ e.preventDefault();
820
+ }
821
+ });
822
+
805
823
  // Add click handlers — preventDefault stops event from reaching terminal
806
824
  this.element.addEventListener('click', (e) => {
807
825
  const btn = e.target.closest('.accessory-btn');
@@ -813,8 +831,7 @@ const KeyboardAccessoryBar = {
813
831
  this.handleAction(action, btn);
814
832
 
815
833
  // Refocus terminal so keyboard stays open (tap blurs terminal → keyboard dismisses → toolbar shifts)
816
- const refocusActions = new Set(['scroll-up', 'scroll-down', 'arrow-left', 'arrow-right', 'tab', 'shift-tab', 'shift-left', 'shift-right', 'ctrl', 'ctrl-o', 'opt-enter', 'esc', 'effort-max', 'clear-input']);
817
- if (refocusActions.has(action) ||
834
+ if (ACCESSORY_REFOCUS_ACTIONS.has(action) ||
818
835
  ((action === 'clear' || action === 'compact') && this._confirmAction)) {
819
836
  if (typeof app !== 'undefined' && app.terminal) {
820
837
  app.terminal.focus();
@@ -1415,9 +1432,10 @@ const KeyboardAccessoryBar = {
1415
1432
  overlay.querySelector('.prompt-composer-terminal').addEventListener('click', () => {
1416
1433
  // Hand the text BACK to the terminal prompt so both surfaces hold the same
1417
1434
  // prompt, the mirror of the adoption composePrompt() does on open. Only a
1418
- // single-line draft can make the trip: the prompt transport is single-line
1419
- // and strips embedded newlines, so a multi-line draft would arrive mangled
1420
- // and instead stays parked as a draft (the dot on the Compose key shows it).
1435
+ // single-line draft can make the trip: the terminal prompt is one line and
1436
+ // its text reaches the PTY as typed input, where an embedded newline is a
1437
+ // key, so a multi-line draft would arrive mangled and instead stays parked
1438
+ // as a draft (the dot on the Compose key shows it).
1421
1439
  const text = textarea.value;
1422
1440
  if (!text || text.includes('\n')) {
1423
1441
  close({ focusTerminal: true });
@@ -9,7 +9,7 @@
9
9
  * toolbar/accessory bar repositioning, terminal resize on keyboard open/close,
10
10
  * and input scroll-into-view. Uses 100px threshold for iOS address bar drift.
11
11
  * - SwipeHandler — Horizontal swipe detection on the terminal area for session switching.
12
- * 80px minimum distance, 300ms maximum time, 100px max vertical drift.
12
+ * 80px minimum distance, 500ms maximum time, 50px max vertical drift.
13
13
  *
14
14
  * All three have init()/cleanup() lifecycle methods. They are re-initialized after SSE
15
15
  * reconnect (in handleInit) to prevent stale closures.
@@ -758,14 +758,24 @@ const SwipeHandler = {
758
758
  startY: 0,
759
759
  startTime: 0,
760
760
  minSwipeDistance: 80, // Minimum pixels for a valid swipe
761
- maxSwipeTime: 300, // Maximum ms for a swipe gesture
762
- maxVerticalDrift: 100, // Max vertical movement allowed
761
+ // 300ms rejected an unhurried but deliberate swipe outright, which read as an
762
+ // unresponsive gesture rather than as "too slow".
763
+ maxSwipeTime: 500, // Maximum ms for a swipe gesture
764
+ maxVerticalDrift: 50, // Max vertical movement allowed, at any point of the gesture
763
765
 
764
766
  _touchStartHandler: null,
767
+ _touchMoveHandler: null,
765
768
  _touchEndHandler: null,
766
769
  _element: null,
767
770
  _ignoreGesture: false,
768
771
 
772
+ /**
773
+ * Surfaces inside `.main` that own their own gestures or controls: a swipe
774
+ * there must not switch sessions. The phone overview and welcome screen are
775
+ * deliberately NOT listed: swiping from home into a session is a feature.
776
+ */
777
+ IGNORE_SELECTOR: '.tile-grid, .term-select-bar, #cjkInput, .history-trunc-bar',
778
+
769
779
  /** Initialize swipe handling */
770
780
  init() {
771
781
  // Only on touch devices
@@ -776,8 +786,10 @@ const SwipeHandler = {
776
786
 
777
787
  this._element = terminal;
778
788
  this._touchStartHandler = (e) => this.onTouchStart(e);
789
+ this._touchMoveHandler = (e) => this.onTouchMove(e);
779
790
  this._touchEndHandler = (e) => this.onTouchEnd(e);
780
791
  terminal.addEventListener('touchstart', this._touchStartHandler, { passive: true });
792
+ terminal.addEventListener('touchmove', this._touchMoveHandler, { passive: true });
781
793
  terminal.addEventListener('touchend', this._touchEndHandler, { passive: true });
782
794
  },
783
795
 
@@ -785,9 +797,11 @@ const SwipeHandler = {
785
797
  cleanup() {
786
798
  if (this._element && this._touchStartHandler) {
787
799
  this._element.removeEventListener('touchstart', this._touchStartHandler);
800
+ this._element.removeEventListener('touchmove', this._touchMoveHandler);
788
801
  this._element.removeEventListener('touchend', this._touchEndHandler);
789
802
  }
790
803
  this._touchStartHandler = null;
804
+ this._touchMoveHandler = null;
791
805
  this._touchEndHandler = null;
792
806
  this._element = null;
793
807
  },
@@ -797,20 +811,43 @@ const SwipeHandler = {
797
811
  // here. Swiping across the open session drawer — the natural "dismiss it"
798
812
  // gesture — would otherwise fire nextSession() and drop the user into a
799
813
  // session they never tapped.
814
+ // The terminal's touch handler publishes the axis it locks for a gesture
815
+ // that starts on it; a touch that starts elsewhere in `.main` (the home
816
+ // screen) must not inherit the last one, or a terminal scroll a moment
817
+ // earlier vetoes a swipe from home. Reset before any early return.
818
+ if (typeof app !== 'undefined') app._terminalGestureAxis = null;
800
819
  this._ignoreGesture = !!e.target?.closest?.('.session-sidebar');
801
820
  if (this._ignoreGesture) return;
802
- if (!e.touches || e.touches.length !== 1) return;
821
+ // A second finger makes this a different gesture (pinch, two-finger scroll):
822
+ // never measure a later lift against the first finger's start. Stays set
823
+ // until the next touchstart, so the first finger's lift cannot clear it.
824
+ if (!e.touches || e.touches.length !== 1) {
825
+ this._ignoreGesture = true;
826
+ return;
827
+ }
828
+ this._ignoreGesture = !!e.target?.closest?.(this.IGNORE_SELECTOR);
803
829
  this.startX = e.touches[0].clientX;
804
830
  this.startY = e.touches[0].clientY;
805
831
  this.startTime = Date.now();
806
832
  },
807
833
 
834
+ onTouchMove(e) {
835
+ if (this._ignoreGesture || !e.touches || e.touches.length !== 1) return;
836
+ if (Math.abs(e.touches[0].clientY - this.startY) > this.maxVerticalDrift) this._ignoreGesture = true;
837
+ },
838
+
808
839
  onTouchEnd(e) {
809
- if (this._ignoreGesture) {
810
- this._ignoreGesture = false;
811
- return;
812
- }
840
+ if (this._ignoreGesture) return;
813
841
  if (!e.changedTouches || e.changedTouches.length !== 1) return;
842
+ if (typeof app === 'undefined') return;
843
+ // The terminal's own touch handler (terminal-ui.js) runs first, on the same
844
+ // gesture: a drag it locked as a scroll or a pan is not a session swipe,
845
+ // and neither is a lift it consumed (its long-press selection gesture
846
+ // preventDefaults the touchend, even on blank space where no selection
847
+ // survives the lift). A swipe must not extend or drop a touch selection.
848
+ if (e.defaultPrevented) return;
849
+ if (app._terminalGestureAxis === 'y' || app._terminalGestureAxis === 'x') return;
850
+ if (app._touchSelecting || app._touchSelectionActive) return;
814
851
 
815
852
  const endX = e.changedTouches[0].clientX;
816
853
  const endY = e.changedTouches[0].clientY;
@@ -824,13 +861,10 @@ const SwipeHandler = {
824
861
  if (deltaY > this.maxVerticalDrift) return; // Too much vertical movement
825
862
  if (Math.abs(deltaX) < this.minSwipeDistance) return; // Too short
826
863
 
827
- // Valid swipe detected
828
- if (deltaX > 0) {
829
- // Swipe right -> previous session
830
- if (typeof app !== 'undefined') app.prevSession();
831
- } else {
832
- // Swipe left -> next session
833
- if (typeof app !== 'undefined') app.nextSession();
834
- }
864
+ // Valid swipe detected. Swipe right -> previous session, left -> next.
865
+ // In the order the strip draws, which a grouped layout ('case', 'state', a
866
+ // sorted rail) makes differ from the canonical session order.
867
+ if (deltaX > 0) app.prevSession({ visual: true });
868
+ else app.nextSession({ visual: true });
835
869
  },
836
870
  };