aicodeman 1.43.0 → 1.44.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 (304) hide show
  1. package/README.md +3 -2
  2. package/dist/cli-agent.d.ts +3 -3
  3. package/dist/cli-agent.d.ts.map +1 -1
  4. package/dist/cli-agent.js +8 -6
  5. package/dist/cli-agent.js.map +1 -1
  6. package/dist/config/cli-registry/stock.d.ts.map +1 -1
  7. package/dist/config/cli-registry/stock.js +8 -3
  8. package/dist/config/cli-registry/stock.js.map +1 -1
  9. package/dist/config/cli-registry/types.d.ts +2 -2
  10. package/dist/config/map-limits.d.ts +13 -1
  11. package/dist/config/map-limits.d.ts.map +1 -1
  12. package/dist/config/map-limits.js +28 -1
  13. package/dist/config/map-limits.js.map +1 -1
  14. package/dist/config-backup.d.ts +279 -0
  15. package/dist/config-backup.d.ts.map +1 -0
  16. package/dist/config-backup.js +794 -0
  17. package/dist/config-backup.js.map +1 -0
  18. package/dist/cron/cron-service.d.ts +5 -5
  19. package/dist/cron/cron-service.js +6 -6
  20. package/dist/cron/cron-service.js.map +1 -1
  21. package/dist/custom-model-hosts.d.ts +16 -0
  22. package/dist/custom-model-hosts.d.ts.map +1 -1
  23. package/dist/custom-model-hosts.js.map +1 -1
  24. package/dist/hooks-config.d.ts +15 -0
  25. package/dist/hooks-config.d.ts.map +1 -1
  26. package/dist/hooks-config.js +35 -0
  27. package/dist/hooks-config.js.map +1 -1
  28. package/dist/intent-store.d.ts +2 -0
  29. package/dist/intent-store.d.ts.map +1 -1
  30. package/dist/intent-store.js +9 -0
  31. package/dist/intent-store.js.map +1 -1
  32. package/dist/mux-interface.d.ts +21 -4
  33. package/dist/mux-interface.d.ts.map +1 -1
  34. package/dist/prompt-cache-keepwarm.d.ts +193 -0
  35. package/dist/prompt-cache-keepwarm.d.ts.map +1 -0
  36. package/dist/prompt-cache-keepwarm.js +359 -0
  37. package/dist/prompt-cache-keepwarm.js.map +1 -0
  38. package/dist/respawn-controller.d.ts.map +1 -1
  39. package/dist/respawn-controller.js +6 -5
  40. package/dist/respawn-controller.js.map +1 -1
  41. package/dist/session-auto-ops.d.ts.map +1 -1
  42. package/dist/session-auto-ops.js +6 -1
  43. package/dist/session-auto-ops.js.map +1 -1
  44. package/dist/session-cli-registry-bridge.d.ts +13 -0
  45. package/dist/session-cli-registry-bridge.d.ts.map +1 -1
  46. package/dist/session-cli-registry-bridge.js +20 -3
  47. package/dist/session-cli-registry-bridge.js.map +1 -1
  48. package/dist/session-submit-verifier.d.ts +19 -0
  49. package/dist/session-submit-verifier.d.ts.map +1 -1
  50. package/dist/session-submit-verifier.js +88 -0
  51. package/dist/session-submit-verifier.js.map +1 -1
  52. package/dist/session.d.ts +61 -5
  53. package/dist/session.d.ts.map +1 -1
  54. package/dist/session.js +112 -7
  55. package/dist/session.js.map +1 -1
  56. package/dist/state-store.d.ts +10 -0
  57. package/dist/state-store.d.ts.map +1 -1
  58. package/dist/state-store.js +35 -0
  59. package/dist/state-store.js.map +1 -1
  60. package/dist/tab-layout-service.d.ts +33 -0
  61. package/dist/tab-layout-service.d.ts.map +1 -1
  62. package/dist/tab-layout-service.js +75 -3
  63. package/dist/tab-layout-service.js.map +1 -1
  64. package/dist/tmux-manager.d.ts +50 -8
  65. package/dist/tmux-manager.d.ts.map +1 -1
  66. package/dist/tmux-manager.js +146 -30
  67. package/dist/tmux-manager.js.map +1 -1
  68. package/dist/tmux-prefix-table.d.ts +54 -0
  69. package/dist/tmux-prefix-table.d.ts.map +1 -0
  70. package/dist/tmux-prefix-table.js +137 -0
  71. package/dist/tmux-prefix-table.js.map +1 -0
  72. package/dist/tui/tui-app.d.ts +9 -1
  73. package/dist/tui/tui-app.d.ts.map +1 -1
  74. package/dist/tui/tui-app.js +21 -8
  75. package/dist/tui/tui-app.js.map +1 -1
  76. package/dist/tui/tui-client.d.ts +3 -2
  77. package/dist/tui/tui-client.d.ts.map +1 -1
  78. package/dist/tui/tui-client.js +3 -2
  79. package/dist/tui/tui-client.js.map +1 -1
  80. package/dist/types/app-state.d.ts +6 -0
  81. package/dist/types/app-state.d.ts.map +1 -1
  82. package/dist/types/app-state.js.map +1 -1
  83. package/dist/types/session.d.ts +40 -1
  84. package/dist/types/session.d.ts.map +1 -1
  85. package/dist/types/session.js.map +1 -1
  86. package/dist/usage-telemetry.d.ts +15 -0
  87. package/dist/usage-telemetry.d.ts.map +1 -1
  88. package/dist/usage-telemetry.js +45 -2
  89. package/dist/usage-telemetry.js.map +1 -1
  90. package/dist/utils/copilot-plan-usage.d.ts +46 -0
  91. package/dist/utils/copilot-plan-usage.d.ts.map +1 -0
  92. package/dist/utils/copilot-plan-usage.js +95 -0
  93. package/dist/utils/copilot-plan-usage.js.map +1 -0
  94. package/dist/utils/index.d.ts +2 -0
  95. package/dist/utils/index.d.ts.map +1 -1
  96. package/dist/utils/index.js +2 -0
  97. package/dist/utils/index.js.map +1 -1
  98. package/dist/utils/single-line.d.ts +22 -0
  99. package/dist/utils/single-line.d.ts.map +1 -0
  100. package/dist/utils/single-line.js +30 -0
  101. package/dist/utils/single-line.js.map +1 -0
  102. package/dist/web/approval-inbox.d.ts +6 -0
  103. package/dist/web/approval-inbox.d.ts.map +1 -1
  104. package/dist/web/approval-inbox.js +2 -2
  105. package/dist/web/approval-inbox.js.map +1 -1
  106. package/dist/web/plan-usage-latest.d.ts +2 -1
  107. package/dist/web/plan-usage-latest.d.ts.map +1 -1
  108. package/dist/web/plan-usage-latest.js +12 -2
  109. package/dist/web/plan-usage-latest.js.map +1 -1
  110. package/dist/web/ports/index.d.ts +1 -0
  111. package/dist/web/ports/index.d.ts.map +1 -1
  112. package/dist/web/ports/keep-warm-port.d.ts +9 -0
  113. package/dist/web/ports/keep-warm-port.d.ts.map +1 -0
  114. package/dist/web/ports/keep-warm-port.js +6 -0
  115. package/dist/web/ports/keep-warm-port.js.map +1 -0
  116. package/dist/web/ports/session-port.d.ts +3 -1
  117. package/dist/web/ports/session-port.d.ts.map +1 -1
  118. package/dist/web/public/admin-ui.js.gz +0 -0
  119. package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
  120. package/dist/web/public/app.9314ee60.js +43 -0
  121. package/dist/web/public/app.9314ee60.js.br +0 -0
  122. package/dist/web/public/app.9314ee60.js.gz +0 -0
  123. package/dist/web/public/approvals-ui.js.gz +0 -0
  124. package/dist/web/public/{constants.e5e588db.js → constants.4866ecc3.js} +49 -1
  125. package/dist/web/public/constants.4866ecc3.js.br +0 -0
  126. package/dist/web/public/constants.4866ecc3.js.gz +0 -0
  127. package/dist/web/public/cron-ui.js.gz +0 -0
  128. package/dist/web/public/entrance-animations.js.gz +0 -0
  129. package/dist/web/public/git-status-ui.js.gz +0 -0
  130. package/dist/web/public/home-sessions.js.gz +0 -0
  131. package/dist/web/public/host-wake-ui.js.gz +0 -0
  132. package/dist/web/public/i18n.22ca902b.js +2 -0
  133. package/dist/web/public/i18n.22ca902b.js.br +0 -0
  134. package/dist/web/public/i18n.22ca902b.js.gz +0 -0
  135. package/dist/web/public/image-input.941386e7.js.gz +0 -0
  136. package/dist/web/public/index.html +99 -14
  137. package/dist/web/public/index.html.br +0 -0
  138. package/dist/web/public/index.html.gz +0 -0
  139. package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
  140. package/dist/web/public/{keyboard-accessory.c283e827.js → keyboard-accessory.4e8b20ac.js} +23 -5
  141. package/dist/web/public/keyboard-accessory.4e8b20ac.js.br +0 -0
  142. package/dist/web/public/keyboard-accessory.4e8b20ac.js.gz +0 -0
  143. package/dist/web/public/{mobile-handlers.0ef9c311.js → mobile-handlers.44adaa07.js} +48 -16
  144. package/dist/web/public/mobile-handlers.44adaa07.js.br +0 -0
  145. package/dist/web/public/mobile-handlers.44adaa07.js.gz +0 -0
  146. package/dist/web/public/mobile-ime-preview.2dbaf262.js.gz +0 -0
  147. package/dist/web/public/mobile-overview.js.gz +0 -0
  148. package/dist/web/public/mobile.12fb18de.css +1 -0
  149. package/dist/web/public/mobile.12fb18de.css.br +0 -0
  150. package/dist/web/public/mobile.12fb18de.css.gz +0 -0
  151. package/dist/web/public/notification-manager.feb82c04.js.gz +0 -0
  152. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  153. package/dist/web/public/{panels-ui.b7bfb9da.js → panels-ui.cbb24ba1.js} +65 -65
  154. package/dist/web/public/panels-ui.cbb24ba1.js.br +0 -0
  155. package/dist/web/public/panels-ui.cbb24ba1.js.gz +0 -0
  156. package/dist/web/public/ralph-panel.b350e2ef.js.gz +0 -0
  157. package/dist/web/public/ralph-wizard.b6c0dd19.js.gz +0 -0
  158. package/dist/web/public/readmymind-ui.js.gz +0 -0
  159. package/dist/web/public/reboot-restore-ui.js.gz +0 -0
  160. package/dist/web/public/respawn-ui.d7adcf6a.js.gz +0 -0
  161. package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
  162. package/dist/web/public/session-lineage.js.gz +0 -0
  163. package/dist/web/public/{session-ui.be076c88.js → session-ui.9c1f009b.js} +7 -3
  164. package/dist/web/public/session-ui.9c1f009b.js.br +0 -0
  165. package/dist/web/public/session-ui.9c1f009b.js.gz +0 -0
  166. package/dist/web/public/settings-ui.fea9ddae.js +106 -0
  167. package/dist/web/public/settings-ui.fea9ddae.js.br +0 -0
  168. package/dist/web/public/settings-ui.fea9ddae.js.gz +0 -0
  169. package/dist/web/public/spreadsheet-preview-worker.js.gz +0 -0
  170. package/dist/web/public/spreadsheet-preview.75c751de.js.gz +0 -0
  171. package/dist/web/public/spreadsheet-xlsx-core.js.gz +0 -0
  172. package/dist/web/public/styles.e096fcd6.css +1 -0
  173. package/dist/web/public/styles.e096fcd6.css.br +0 -0
  174. package/dist/web/public/styles.e096fcd6.css.gz +0 -0
  175. package/dist/web/public/subagent-windows.07277a58.js.gz +0 -0
  176. package/dist/web/public/sw.js +2 -2
  177. package/dist/web/public/sw.js.br +0 -0
  178. package/dist/web/public/sw.js.gz +0 -0
  179. package/dist/web/public/tab-layout-browser.2d6189f7.js.gz +0 -0
  180. package/dist/web/public/tab-rail-resize.7157e0bd.js.gz +0 -0
  181. package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.gz +0 -0
  182. package/dist/web/public/terminal-split.js.gz +0 -0
  183. package/dist/web/public/terminal-tile.js +41 -22
  184. package/dist/web/public/terminal-tile.js.br +0 -0
  185. package/dist/web/public/terminal-tile.js.gz +0 -0
  186. package/dist/web/public/terminal-ui.68dbd352.js +2 -0
  187. package/dist/web/public/terminal-ui.68dbd352.js.br +0 -0
  188. package/dist/web/public/terminal-ui.68dbd352.js.gz +0 -0
  189. package/dist/web/public/tile-grid.js.gz +0 -0
  190. package/dist/web/public/ultracode-panel.js.gz +0 -0
  191. package/dist/web/public/ultracode-windows.js.gz +0 -0
  192. package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
  193. package/dist/web/public/vendor/exceljs.min.js.gz +0 -0
  194. package/dist/web/public/vendor/fflate.min.js.gz +0 -0
  195. package/dist/web/public/vendor/marked.min.js.gz +0 -0
  196. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  197. package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
  198. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  199. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  200. package/dist/web/public/vendor/xterm-predictive-echo.ae5e3d5d.js.gz +0 -0
  201. package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.gz +0 -0
  202. package/dist/web/public/vendor/xterm.css.gz +0 -0
  203. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  204. package/dist/web/public/voice-input.2342c37b.js.gz +0 -0
  205. package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
  206. package/dist/web/public/webview-tabs.js.gz +0 -0
  207. package/dist/web/public/whats-new.json +9 -9
  208. package/dist/web/routes/admin-routes.d.ts +2 -1
  209. package/dist/web/routes/admin-routes.d.ts.map +1 -1
  210. package/dist/web/routes/admin-routes.js +3 -0
  211. package/dist/web/routes/admin-routes.js.map +1 -1
  212. package/dist/web/routes/case-routes.d.ts +2 -2
  213. package/dist/web/routes/case-routes.d.ts.map +1 -1
  214. package/dist/web/routes/case-routes.js +81 -3
  215. package/dist/web/routes/case-routes.js.map +1 -1
  216. package/dist/web/routes/config-backup-routes.d.ts +54 -0
  217. package/dist/web/routes/config-backup-routes.d.ts.map +1 -0
  218. package/dist/web/routes/config-backup-routes.js +268 -0
  219. package/dist/web/routes/config-backup-routes.js.map +1 -0
  220. package/dist/web/routes/custom-model-routes.d.ts +17 -1
  221. package/dist/web/routes/custom-model-routes.d.ts.map +1 -1
  222. package/dist/web/routes/custom-model-routes.js +118 -13
  223. package/dist/web/routes/custom-model-routes.js.map +1 -1
  224. package/dist/web/routes/hook-event-routes.d.ts.map +1 -1
  225. package/dist/web/routes/hook-event-routes.js +26 -5
  226. package/dist/web/routes/hook-event-routes.js.map +1 -1
  227. package/dist/web/routes/index.d.ts +1 -0
  228. package/dist/web/routes/index.d.ts.map +1 -1
  229. package/dist/web/routes/index.js +1 -0
  230. package/dist/web/routes/index.js.map +1 -1
  231. package/dist/web/routes/ralph-routes.js +2 -2
  232. package/dist/web/routes/ralph-routes.js.map +1 -1
  233. package/dist/web/routes/reboot-restore-routes.d.ts.map +1 -1
  234. package/dist/web/routes/reboot-restore-routes.js +2 -0
  235. package/dist/web/routes/reboot-restore-routes.js.map +1 -1
  236. package/dist/web/routes/session-routes.d.ts +2 -2
  237. package/dist/web/routes/session-routes.d.ts.map +1 -1
  238. package/dist/web/routes/session-routes.js +86 -15
  239. package/dist/web/routes/session-routes.js.map +1 -1
  240. package/dist/web/routes/status-telemetry-routes.d.ts +2 -2
  241. package/dist/web/routes/status-telemetry-routes.d.ts.map +1 -1
  242. package/dist/web/routes/status-telemetry-routes.js +8 -4
  243. package/dist/web/routes/status-telemetry-routes.js.map +1 -1
  244. package/dist/web/routes/system-routes.d.ts +2 -2
  245. package/dist/web/routes/system-routes.d.ts.map +1 -1
  246. package/dist/web/routes/system-routes.js +7 -0
  247. package/dist/web/routes/system-routes.js.map +1 -1
  248. package/dist/web/routes/webview-routes.d.ts.map +1 -1
  249. package/dist/web/routes/webview-routes.js +1 -0
  250. package/dist/web/routes/webview-routes.js.map +1 -1
  251. package/dist/web/schemas.d.ts +19 -0
  252. package/dist/web/schemas.d.ts.map +1 -1
  253. package/dist/web/schemas.js +31 -2
  254. package/dist/web/schemas.js.map +1 -1
  255. package/dist/web/server.d.ts +12 -2
  256. package/dist/web/server.d.ts.map +1 -1
  257. package/dist/web/server.js +116 -5
  258. package/dist/web/server.js.map +1 -1
  259. package/dist/web/session-listener-wiring.d.ts +6 -0
  260. package/dist/web/session-listener-wiring.d.ts.map +1 -1
  261. package/dist/web/session-listener-wiring.js +10 -3
  262. package/dist/web/session-listener-wiring.js.map +1 -1
  263. package/dist/web/sse-events.d.ts +5 -2
  264. package/dist/web/sse-events.d.ts.map +1 -1
  265. package/dist/web/sse-events.js +5 -2
  266. package/dist/web/sse-events.js.map +1 -1
  267. package/dist/web/webview-proxy.d.ts +8 -3
  268. package/dist/web/webview-proxy.d.ts.map +1 -1
  269. package/dist/web/webview-proxy.js +23 -5
  270. package/dist/web/webview-proxy.js.map +1 -1
  271. package/package.json +1 -1
  272. package/skills/codeman/SKILL.md +20 -9
  273. package/skills/codeman/preamble.sh +12 -2
  274. package/skills/codeman/reference/endpoints.md +8 -7
  275. package/skills/codeman/reference/recipes.md +1 -1
  276. package/skills/codeman/reference/verbs.md +21 -13
  277. package/dist/web/public/app.ae50029a.js +0 -43
  278. package/dist/web/public/app.ae50029a.js.br +0 -0
  279. package/dist/web/public/app.ae50029a.js.gz +0 -0
  280. package/dist/web/public/constants.e5e588db.js.br +0 -0
  281. package/dist/web/public/constants.e5e588db.js.gz +0 -0
  282. package/dist/web/public/i18n.8f291f06.js +0 -2
  283. package/dist/web/public/i18n.8f291f06.js.br +0 -0
  284. package/dist/web/public/i18n.8f291f06.js.gz +0 -0
  285. package/dist/web/public/keyboard-accessory.c283e827.js.br +0 -0
  286. package/dist/web/public/keyboard-accessory.c283e827.js.gz +0 -0
  287. package/dist/web/public/mobile-handlers.0ef9c311.js.br +0 -0
  288. package/dist/web/public/mobile-handlers.0ef9c311.js.gz +0 -0
  289. package/dist/web/public/mobile.13514863.css +0 -1
  290. package/dist/web/public/mobile.13514863.css.br +0 -0
  291. package/dist/web/public/mobile.13514863.css.gz +0 -0
  292. package/dist/web/public/panels-ui.b7bfb9da.js.br +0 -0
  293. package/dist/web/public/panels-ui.b7bfb9da.js.gz +0 -0
  294. package/dist/web/public/session-ui.be076c88.js.br +0 -0
  295. package/dist/web/public/session-ui.be076c88.js.gz +0 -0
  296. package/dist/web/public/settings-ui.fc4cc50a.js +0 -97
  297. package/dist/web/public/settings-ui.fc4cc50a.js.br +0 -0
  298. package/dist/web/public/settings-ui.fc4cc50a.js.gz +0 -0
  299. package/dist/web/public/styles.dcfa907f.css +0 -1
  300. package/dist/web/public/styles.dcfa907f.css.br +0 -0
  301. package/dist/web/public/styles.dcfa907f.css.gz +0 -0
  302. package/dist/web/public/terminal-ui.ae01a7d1.js +0 -2
  303. package/dist/web/public/terminal-ui.ae01a7d1.js.br +0 -0
  304. package/dist/web/public/terminal-ui.ae01a7d1.js.gz +0 -0
@@ -3,7 +3,7 @@
3
3
  * Covers session CRUD, input/output, terminal buffer, quick-start, quick-run,
4
4
  * auto-clear, auto-compact, image watcher, flicker filter, and logout.
5
5
  */
6
- import { join, dirname, extname, basename } from 'node:path';
6
+ import { join, dirname, extname, basename, resolve as resolvePath } from 'node:path';
7
7
  import { homedir } from 'node:os';
8
8
  import { existsSync, statSync, mkdirSync, writeFileSync } from 'node:fs';
9
9
  import { execFile } from 'node:child_process';
@@ -17,7 +17,7 @@ import { Session, cliTakesSessionModel, isAltScreenStripMode, isExternalCliMode,
17
17
  import { SseEvent } from '../sse-events.js';
18
18
  import { webviewCapabilities } from '../../webview-capabilities.js';
19
19
  import { htmlViewCapabilities } from '../../html-view-capabilities.js';
20
- import { CreateSessionSchema, SessionNameSchema, SessionColorSchema, RunPromptSchema, SessionInputWithLimitSchema, ResizeSchema, AutoClearSchema, AutoCompactSchema, AutoResumeSchema, PinSessionSchema, ImageWatcherSchema, FlickerFilterSchema, QuickRunSchema, QuickStartSchema, InteractiveStartSchema, SessionOrderUpdateSchema, SessionWaitQuerySchema, SessionWaitOutputQuerySchema, CustomModelSelectionSchema, } from '../schemas.js';
20
+ import { CreateSessionSchema, SessionNameSchema, SessionColorSchema, RunPromptSchema, SessionInputWithLimitSchema, ResizeSchema, AutoClearSchema, AutoCompactSchema, AutoResumeSchema, KeepWarmSchema, PinSessionSchema, ImageWatcherSchema, FlickerFilterSchema, QuickRunSchema, QuickStartSchema, InteractiveStartSchema, SessionOrderUpdateSchema, SessionWaitQuerySchema, SessionWaitOutputQuerySchema, CustomModelSelectionSchema, } from '../schemas.js';
21
21
  import { readCustomModelHosts } from '../../custom-model-hosts.js';
22
22
  import { applyCustomModelInjection, removeConfigDir } from '../../custom-model-injection-apply.js';
23
23
  import { getLlamaSwapStatus, triggerLlamaSwapLoad, exceedsSafeContextFloor, CLAUDE_MIN_SAFE_CONTEXT_TOKENS, } from './custom-model-routes.js';
@@ -27,7 +27,7 @@ import { TabLayoutValidationError } from '../../tab-layout.js';
27
27
  import { sessionWaits, resolveWaitSignals, sessionHookOptions, signalForStatus, WaitCapacityError, } from '../session-wait-registry.js';
28
28
  import { RemoteWakeRegistry, REMOTE_WAKE_REQUEST_READY_TIMEOUT_MS, createDefaultRemoteWakeDeps, isProbeable, } from '../../remote-wake.js';
29
29
  import { clampWaitMs, MAX_BUFFER_SCAN_BYTES } from '../../config/agent-wait.js';
30
- import { autoConfigureRalph, canAccessOwned, CASES_DIR, findPersistedSessionOrFail, findSessionOrFail, getAuthUser, isAdmin, isPlainPromptInput, isWorkingDirAllowed, ownerFor, parseBody, persistAndBroadcastSession, resolveAgentCaseOrigin, resolveCasesDir, resolveParentSessionId, sessionCapacityMessage, SETTINGS_PATH, validatePathWithinBase, } from '../route-helpers.js';
30
+ import { autoConfigureRalph, canAccessOwned, CASES_DIR, findPersistedSessionOrFail, findSessionOrFail, getAuthUser, isAdmin, isPlainPromptInput, isWorkingDirAllowed, ownerFor, parseBody, persistAndBroadcastSession, readJsonConfig, resolveAgentCaseOrigin, resolveCasesDir, resolveParentSessionId, sessionCapacityMessage, SETTINGS_PATH, validatePathWithinBase, } from '../route-helpers.js';
31
31
  import { buildAgentCaseMarker, writeAgentCaseMarker } from '../../agent-case-marker.js';
32
32
  import { canUsernameRunPrivilegedCommands, resolveClaudeModeForUsername } from '../../user-store.js';
33
33
  import { clampEnvOverridesForOwner } from '../../session-env-clamp.js';
@@ -65,6 +65,41 @@ import { UPLOADS_DIR } from '../paste-image-gc.js';
65
65
  // Path to linked-cases registry (same file used by case-routes resolveCasePath)
66
66
  const LINKED_CASES_FILE = dataPath('linked-cases.json');
67
67
  const CODEMAN_CONFIG_DIR = getDataDir();
68
+ const SAFE_CASE_NAME = /^[a-zA-Z0-9_-]+$/;
69
+ /** `<repo>/.claude/worktrees/<name>`: the layout Claude Code's own worktree feature creates. */
70
+ const CLAUDE_WORKTREE_PATH = /^(.*)\/\.claude\/worktrees\/([^/]+)\/?$/;
71
+ /** Did the committed layout put this session in a named group (not Ungrouped)? */
72
+ function landedInGroup(layout, sessionId) {
73
+ return !!layout?.groups.some((group) => group.refs.some((ref) => ref.kind === 'session' && ref.id === sessionId));
74
+ }
75
+ /**
76
+ * The case a POST /api/sessions `workingDir` belongs to, for its default session
77
+ * group: a direct child of the caller's case space, or (admin / single-user, as
78
+ * GET /api/cases lists them) a linked case's exact path, or a Claude worktree
79
+ * (`<case>/.claude/worktrees/<name>`) of either. Lexical only: the browser sends
80
+ * the path the case list gave it, and this must never touch a possibly-dead
81
+ * mount. Anything else is no case, which keeps today's placement.
82
+ */
83
+ async function inferLocalCaseName(req, workingDir) {
84
+ // The Git worktrees modal launches Claude through this route in the worktree, and every other CLI
85
+ // through quick-start with the case name: both are sessions of that case.
86
+ const resolved = resolvePath(workingDir);
87
+ const target = CLAUDE_WORKTREE_PATH.exec(resolved)?.[1] || resolved;
88
+ const user = getAuthUser(req);
89
+ if (dirname(target) === resolvePath(resolveCasesDir(user))) {
90
+ const name = basename(target);
91
+ if (SAFE_CASE_NAME.test(name))
92
+ return name;
93
+ }
94
+ if (isMultiUserMode() && !isAdmin(req))
95
+ return undefined;
96
+ const linked = await readJsonConfig(LINKED_CASES_FILE, 'linked cases', {});
97
+ for (const [name, path] of Object.entries(linked)) {
98
+ if (SAFE_CASE_NAME.test(name) && typeof path === 'string' && resolvePath(path) === target)
99
+ return name;
100
+ }
101
+ return undefined;
102
+ }
68
103
  // Pre-compiled regex for terminal buffer cleaning (avoids per-request compilation)
69
104
  // eslint-disable-next-line no-control-regex
70
105
  const CLAUDE_BANNER_PATTERN = /\x1b\[1mClaud/;
@@ -1149,9 +1184,13 @@ options = {}) {
1149
1184
  owner,
1150
1185
  parentSessionId: resolveParentSessionId(ctx, req, body.parentSessionId, owner),
1151
1186
  });
1152
- const tabLayout = body.tabGroupId
1153
- ? await ctx.addSession(session, { tabGroupId: body.tabGroupId })
1154
- : await ctx.addSession(session);
1187
+ // Only a named workingDir: without one the session starts in the server's own cwd, which is no case.
1188
+ const placementCase = remote || !body.workingDir ? undefined : await inferLocalCaseName(req, workingDir);
1189
+ const placement = {
1190
+ ...(body.tabGroupId ? { tabGroupId: body.tabGroupId } : {}),
1191
+ ...(placementCase ? { caseName: placementCase } : {}),
1192
+ };
1193
+ const tabLayout = Object.keys(placement).length > 0 ? await ctx.addSession(session, placement) : await ctx.addSession(session);
1155
1194
  ctx.store.incrementSessionsCreated();
1156
1195
  ctx.persistSessionState(session);
1157
1196
  await ctx.setupSessionListeners(session);
@@ -1166,9 +1205,13 @@ options = {}) {
1166
1205
  // Avoids serializing 2-3MB of terminal+text buffers per session creation.
1167
1206
  const lightState = ctx.getSessionStateWithRespawn(session);
1168
1207
  ctx.broadcast(SseEvent.SessionCreated, lightState);
1169
- // A grouped creation also returns the layout that placed it, so the browser
1170
- // draws the tab inside its group at once instead of after a re-read.
1171
- return { session: lightState, ...(body.tabGroupId ? { tabLayout } : {}) };
1208
+ // A grouped creation (asked for, or its case's default group) also returns the
1209
+ // layout that placed it, so the browser draws the tab inside its group at once
1210
+ // instead of after a re-read.
1211
+ return {
1212
+ session: lightState,
1213
+ ...(body.tabGroupId || landedInGroup(tabLayout, session.id) ? { tabLayout } : {}),
1214
+ };
1172
1215
  });
1173
1216
  // ========== Rename Session ==========
1174
1217
  app.put('/api/sessions/:id/name', async (req) => {
@@ -1246,6 +1289,7 @@ options = {}) {
1246
1289
  return createErrorResponse(ApiErrorCode.NOT_FOUND, 'Model endpoint not found');
1247
1290
  }
1248
1291
  const contextLength = endpoint.modelContextLengths?.[body.modelId];
1292
+ const slotCount = endpoint.modelSlotCounts?.[body.modelId];
1249
1293
  // Some CLIs (today: only claude) carry enough of their own fixed system-prompt/tool-
1250
1294
  // schema overhead that a small enough real context guarantees a first-message failure
1251
1295
  // no matter what CLAUDE_CODE_MAX_CONTEXT_TOKENS says — confirmed live at ~36.4K tokens
@@ -1255,12 +1299,13 @@ options = {}) {
1255
1299
  // `confirmed`, which still means both) — NOT by `confirmedSwap`: this warning is
1256
1300
  // about the caller's own session, and the swap warning below is about someone
1257
1301
  // else's, so an answer to one is not consent to the other.
1258
- if (!(body.confirmed || body.confirmedContext) && exceedsSafeContextFloor(entry, contextLength)) {
1302
+ if (!(body.confirmed || body.confirmedContext) && exceedsSafeContextFloor(entry, contextLength, slotCount)) {
1259
1303
  return {
1260
1304
  requiresContextWarning: true,
1261
1305
  modelId: body.modelId,
1262
1306
  contextLength,
1263
1307
  minSafeContextTokens: CLAUDE_MIN_SAFE_CONTEXT_TOKENS,
1308
+ ...(slotCount && slotCount > 1 ? { slotCount } : {}),
1264
1309
  };
1265
1310
  }
1266
1311
  // llama.cpp runs exactly one model at a time; llama-swap unloads and reloads it on
@@ -3089,6 +3134,32 @@ options = {}) {
3089
3134
  },
3090
3135
  };
3091
3136
  });
3137
+ // ========== Prompt-cache keep-warm ==========
3138
+ // Per-session opt-in for the keep-alive nudge (prompt-cache-keepwarm.ts). `enabled: null`
3139
+ // clears the choice so the app-wide default applies again. Refused for a CLI that reports
3140
+ // no cache telemetry on its statusline: without `expires_at` there is nothing to schedule.
3141
+ app.post('/api/sessions/:id/keep-warm', async (req) => {
3142
+ const { id } = req.params;
3143
+ const body = parseBody(KeepWarmSchema, req.body, 'Invalid request body');
3144
+ const session = findSessionOrFail(ctx, id, req);
3145
+ if (!getCli(session.mode)?.capabilities.statusLineTelemetry) {
3146
+ return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'Prompt-cache keep-warm needs the cache telemetry this CLI does not report');
3147
+ }
3148
+ session.setKeepWarmEnabled(body.enabled ?? undefined);
3149
+ // Re-evaluate BEFORE the state broadcast and the response: both carry `keepWarm`, and a
3150
+ // page that received the previous status would overwrite the one the toggle just produced.
3151
+ await ctx.keepWarm.schedule(id);
3152
+ persistAndBroadcastSession(ctx, session);
3153
+ return {
3154
+ success: true,
3155
+ data: {
3156
+ keepWarm: {
3157
+ enabled: session.keepWarmEnabled ?? null,
3158
+ status: session.keepWarm,
3159
+ },
3160
+ },
3161
+ };
3162
+ });
3092
3163
  // ========== Auto-Resume (usage-limit pause) ==========
3093
3164
  app.post('/api/sessions/:id/auto-resume', async (req) => {
3094
3165
  const { id } = req.params;
@@ -3688,6 +3759,7 @@ options = {}) {
3688
3759
  if (!cmEndpoint)
3689
3760
  return createErrorResponse(ApiErrorCode.NOT_FOUND, 'Model endpoint not found');
3690
3761
  const cmContextLength = cmEndpoint.modelContextLengths?.[customModel.modelId];
3762
+ const cmSlotCount = cmEndpoint.modelSlotCounts?.[customModel.modelId];
3691
3763
  // See the dedicated route's own comment for the full reasoning: some CLIs' own fixed
3692
3764
  // overhead can exceed a small enough real context on the very first message,
3693
3765
  // regardless of contextLengthVar. Warn before creating a session that's certain to
@@ -3695,12 +3767,13 @@ options = {}) {
3695
3767
  // See the dedicated route above for why this reads `confirmedContext` and never
3696
3768
  // `confirmedSwap`.
3697
3769
  if (!(customModel.confirmed || customModel.confirmedContext) &&
3698
- exceedsSafeContextFloor(cmEntry, cmContextLength)) {
3770
+ exceedsSafeContextFloor(cmEntry, cmContextLength, cmSlotCount)) {
3699
3771
  return {
3700
3772
  requiresContextWarning: true,
3701
3773
  modelId: customModel.modelId,
3702
3774
  contextLength: cmContextLength,
3703
3775
  minSafeContextTokens: CLAUDE_MIN_SAFE_CONTEXT_TOKENS,
3776
+ ...(cmSlotCount && cmSlotCount > 1 ? { slotCount: cmSlotCount } : {}),
3704
3777
  };
3705
3778
  }
3706
3779
  // See the dedicated route's own comment for the full reasoning: llama.cpp runs one
@@ -3834,7 +3907,7 @@ options = {}) {
3834
3907
  session.ralphTracker.enableAutoEnable(); // Allow re-enabling on restart
3835
3908
  }
3836
3909
  }
3837
- const tabLayout = tabGroupId ? await ctx.addSession(session, { tabGroupId }) : await ctx.addSession(session);
3910
+ const tabLayout = await ctx.addSession(session, { caseName, ...(tabGroupId ? { tabGroupId } : {}) });
3838
3911
  ctx.store.incrementSessionsCreated();
3839
3912
  ctx.persistSessionState(session);
3840
3913
  await ctx.setupSessionListeners(session);
@@ -3920,7 +3993,7 @@ options = {}) {
3920
3993
  caseName,
3921
3994
  ...(worktree ? { worktree, workingDir: workspacePath } : {}),
3922
3995
  ...(customModel ? { modelSwapInProgress: qsCustomModelSwapInProgress } : {}),
3923
- ...(tabGroupId ? { tabLayout } : {}),
3996
+ ...(tabGroupId || landedInGroup(tabLayout, session.id) ? { tabLayout } : {}),
3924
3997
  };
3925
3998
  }
3926
3999
  catch (err) {
@@ -4045,8 +4118,6 @@ options = {}) {
4045
4118
  }
4046
4119
  return sawNonCli;
4047
4120
  }
4048
- /** `<repo>/.claude/worktrees/<name>` — the layout Claude Code's own worktree feature creates. */
4049
- const CLAUDE_WORKTREE_PATH = /^(.*)\/\.claude\/worktrees\/([^/]+)\/?$/;
4050
4121
  /**
4051
4122
  * Recover cwd / branch / worktree from a transcript chunk.
4052
4123
  *