aicodeman 1.34.0 → 1.40.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 (299) hide show
  1. package/README.md +11 -0
  2. package/README.zh-CN.md +8 -0
  3. package/dist/attachment-registry.d.ts +6 -0
  4. package/dist/attachment-registry.d.ts.map +1 -1
  5. package/dist/attachment-registry.js +9 -3
  6. package/dist/attachment-registry.js.map +1 -1
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +2 -2
  9. package/dist/cli.js.map +1 -1
  10. package/dist/config/cli-registry/patterns.d.ts +6 -0
  11. package/dist/config/cli-registry/patterns.d.ts.map +1 -1
  12. package/dist/config/cli-registry/patterns.js +13 -0
  13. package/dist/config/cli-registry/patterns.js.map +1 -1
  14. package/dist/config/cli-registry/schema.d.ts +13 -0
  15. package/dist/config/cli-registry/schema.d.ts.map +1 -1
  16. package/dist/config/cli-registry/schema.js +60 -2
  17. package/dist/config/cli-registry/schema.js.map +1 -1
  18. package/dist/config/cli-registry/stock.d.ts.map +1 -1
  19. package/dist/config/cli-registry/stock.js +175 -7
  20. package/dist/config/cli-registry/stock.js.map +1 -1
  21. package/dist/config/cli-registry/types.d.ts +93 -6
  22. package/dist/config/cli-registry/types.d.ts.map +1 -1
  23. package/dist/config/dependency-registry.d.ts +7 -0
  24. package/dist/config/dependency-registry.d.ts.map +1 -1
  25. package/dist/config/dependency-registry.js +15 -0
  26. package/dist/config/dependency-registry.js.map +1 -1
  27. package/dist/config/path-probe.d.ts +37 -0
  28. package/dist/config/path-probe.d.ts.map +1 -0
  29. package/dist/config/path-probe.js +43 -0
  30. package/dist/config/path-probe.js.map +1 -0
  31. package/dist/deepseek-route-config.d.ts +110 -0
  32. package/dist/deepseek-route-config.d.ts.map +1 -0
  33. package/dist/deepseek-route-config.js +477 -0
  34. package/dist/deepseek-route-config.js.map +1 -0
  35. package/dist/git-workspace-status.d.ts +246 -0
  36. package/dist/git-workspace-status.d.ts.map +1 -0
  37. package/dist/git-workspace-status.js +626 -0
  38. package/dist/git-workspace-status.js.map +1 -0
  39. package/dist/hooks-config.d.ts.map +1 -1
  40. package/dist/hooks-config.js +83 -13
  41. package/dist/hooks-config.js.map +1 -1
  42. package/dist/model-config-resolvers.d.ts +29 -0
  43. package/dist/model-config-resolvers.d.ts.map +1 -0
  44. package/dist/model-config-resolvers.js +34 -0
  45. package/dist/model-config-resolvers.js.map +1 -0
  46. package/dist/session-display-model.d.ts +110 -0
  47. package/dist/session-display-model.d.ts.map +1 -0
  48. package/dist/session-display-model.js +154 -0
  49. package/dist/session-display-model.js.map +1 -0
  50. package/dist/session.d.ts +145 -8
  51. package/dist/session.d.ts.map +1 -1
  52. package/dist/session.js +280 -35
  53. package/dist/session.js.map +1 -1
  54. package/dist/types/api.d.ts +7 -0
  55. package/dist/types/api.d.ts.map +1 -1
  56. package/dist/types/api.js.map +1 -1
  57. package/dist/types/session.d.ts +28 -1
  58. package/dist/types/session.d.ts.map +1 -1
  59. package/dist/types/session.js.map +1 -1
  60. package/dist/types/tools.d.ts +1 -1
  61. package/dist/types/tools.d.ts.map +1 -1
  62. package/dist/utils/bounded-path-probe.d.ts +99 -0
  63. package/dist/utils/bounded-path-probe.d.ts.map +1 -0
  64. package/dist/utils/bounded-path-probe.js +228 -0
  65. package/dist/utils/bounded-path-probe.js.map +1 -0
  66. package/dist/utils/cli-executable-resolver.d.ts +2 -0
  67. package/dist/utils/cli-executable-resolver.d.ts.map +1 -1
  68. package/dist/utils/cli-executable-resolver.js +2 -1
  69. package/dist/utils/cli-executable-resolver.js.map +1 -1
  70. package/dist/utils/deepseek-cli-resolver.d.ts +8 -0
  71. package/dist/utils/deepseek-cli-resolver.d.ts.map +1 -1
  72. package/dist/utils/deepseek-cli-resolver.js +18 -2
  73. package/dist/utils/deepseek-cli-resolver.js.map +1 -1
  74. package/dist/utils/dependency-checker.d.ts +2 -0
  75. package/dist/utils/dependency-checker.d.ts.map +1 -1
  76. package/dist/utils/dependency-checker.js +37 -9
  77. package/dist/utils/dependency-checker.js.map +1 -1
  78. package/dist/utils/index.d.ts +2 -0
  79. package/dist/utils/index.d.ts.map +1 -1
  80. package/dist/utils/index.js +1 -0
  81. package/dist/utils/index.js.map +1 -1
  82. package/dist/web/case-path.d.ts +58 -0
  83. package/dist/web/case-path.d.ts.map +1 -0
  84. package/dist/web/case-path.js +182 -0
  85. package/dist/web/case-path.js.map +1 -0
  86. package/dist/web/launch-defaults.d.ts +22 -0
  87. package/dist/web/launch-defaults.d.ts.map +1 -0
  88. package/dist/web/launch-defaults.js +46 -0
  89. package/dist/web/launch-defaults.js.map +1 -0
  90. package/dist/web/public/admin-ui.js.gz +0 -0
  91. package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
  92. package/dist/web/public/app.abadc970.js +43 -0
  93. package/dist/web/public/app.abadc970.js.br +0 -0
  94. package/dist/web/public/app.abadc970.js.gz +0 -0
  95. package/dist/web/public/approvals-ui.js.gz +0 -0
  96. package/dist/web/public/{constants.d95fade9.js → constants.c0f8f9de.js} +1009 -127
  97. package/dist/web/public/constants.c0f8f9de.js.br +0 -0
  98. package/dist/web/public/constants.c0f8f9de.js.gz +0 -0
  99. package/dist/web/public/cron-ui.js.gz +0 -0
  100. package/dist/web/public/entrance-animations.js +1 -0
  101. package/dist/web/public/entrance-animations.js.br +0 -0
  102. package/dist/web/public/entrance-animations.js.gz +0 -0
  103. package/dist/web/public/git-status-ui.js +719 -0
  104. package/dist/web/public/git-status-ui.js.br +0 -0
  105. package/dist/web/public/git-status-ui.js.gz +0 -0
  106. package/dist/web/public/home-sessions.js +12 -9
  107. package/dist/web/public/home-sessions.js.br +0 -0
  108. package/dist/web/public/home-sessions.js.gz +0 -0
  109. package/dist/web/public/host-wake-ui.js.gz +0 -0
  110. package/dist/web/public/i18n.a31747a9.js +2 -0
  111. package/dist/web/public/i18n.a31747a9.js.br +0 -0
  112. package/dist/web/public/i18n.a31747a9.js.gz +0 -0
  113. package/dist/web/public/{image-input.a216cf9e.js → image-input.898a538b.js} +18 -8
  114. package/dist/web/public/image-input.898a538b.js.br +0 -0
  115. package/dist/web/public/image-input.898a538b.js.gz +0 -0
  116. package/dist/web/public/index.html +205 -42
  117. package/dist/web/public/index.html.br +0 -0
  118. package/dist/web/public/index.html.gz +0 -0
  119. package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
  120. package/dist/web/public/keyboard-accessory.c1e7c7b7.js.gz +0 -0
  121. package/dist/web/public/{mobile-handlers.23a85db1.js → mobile-handlers.0ef9c311.js} +20 -0
  122. package/dist/web/public/mobile-handlers.0ef9c311.js.br +0 -0
  123. package/dist/web/public/mobile-handlers.0ef9c311.js.gz +0 -0
  124. package/dist/web/public/mobile-ime-preview.2dbaf262.js.gz +0 -0
  125. package/dist/web/public/mobile-overview.js.gz +0 -0
  126. package/dist/web/public/mobile.111b187d.css +1 -0
  127. package/dist/web/public/mobile.111b187d.css.br +0 -0
  128. package/dist/web/public/mobile.111b187d.css.gz +0 -0
  129. package/dist/web/public/notification-manager.50bb87d8.js.gz +0 -0
  130. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  131. package/dist/web/public/{panels-ui.6a5898d9.js → panels-ui.4735dfc2.js} +4 -4
  132. package/dist/web/public/panels-ui.4735dfc2.js.br +0 -0
  133. package/dist/web/public/{panels-ui.6a5898d9.js.gz → panels-ui.4735dfc2.js.gz} +0 -0
  134. package/dist/web/public/ralph-panel.b350e2ef.js.gz +0 -0
  135. package/dist/web/public/ralph-wizard.b6c0dd19.js.gz +0 -0
  136. package/dist/web/public/readmymind-ui.js.gz +0 -0
  137. package/dist/web/public/reboot-restore-ui.js.gz +0 -0
  138. package/dist/web/public/respawn-ui.ff0dae4c.js.gz +0 -0
  139. package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
  140. package/dist/web/public/session-lineage.js +229 -86
  141. package/dist/web/public/session-lineage.js.br +0 -0
  142. package/dist/web/public/session-lineage.js.gz +0 -0
  143. package/dist/web/public/session-ui.f731602c.js +100 -0
  144. package/dist/web/public/session-ui.f731602c.js.br +0 -0
  145. package/dist/web/public/session-ui.f731602c.js.gz +0 -0
  146. package/dist/web/public/settings-ui.a97ab16f.js +97 -0
  147. package/dist/web/public/settings-ui.a97ab16f.js.br +0 -0
  148. package/dist/web/public/settings-ui.a97ab16f.js.gz +0 -0
  149. package/dist/web/public/spreadsheet-preview-worker.js +290 -0
  150. package/dist/web/public/spreadsheet-preview-worker.js.br +0 -0
  151. package/dist/web/public/spreadsheet-preview-worker.js.gz +0 -0
  152. package/dist/web/public/spreadsheet-preview.af82fa2f.js +555 -0
  153. package/dist/web/public/spreadsheet-preview.af82fa2f.js.br +0 -0
  154. package/dist/web/public/spreadsheet-preview.af82fa2f.js.gz +0 -0
  155. package/dist/web/public/spreadsheet-xlsx-core.js +1006 -0
  156. package/dist/web/public/spreadsheet-xlsx-core.js.br +0 -0
  157. package/dist/web/public/spreadsheet-xlsx-core.js.gz +0 -0
  158. package/dist/web/public/styles.8ee12666.css +1 -0
  159. package/dist/web/public/styles.8ee12666.css.br +0 -0
  160. package/dist/web/public/styles.8ee12666.css.gz +0 -0
  161. package/dist/web/public/subagent-windows.e6ca799f.js.gz +0 -0
  162. package/dist/web/public/sw.js +2 -2
  163. package/dist/web/public/sw.js.br +0 -0
  164. package/dist/web/public/sw.js.gz +0 -0
  165. package/dist/web/public/tab-layout-browser.065fcba4.js +1 -0
  166. package/dist/web/public/tab-layout-browser.065fcba4.js.br +0 -0
  167. package/dist/web/public/tab-layout-browser.065fcba4.js.gz +0 -0
  168. package/dist/web/public/{tab-rail-resize.dcdc5772.js → tab-rail-resize.a5867793.js} +1 -1
  169. package/dist/web/public/tab-rail-resize.a5867793.js.br +0 -0
  170. package/dist/web/public/tab-rail-resize.a5867793.js.gz +0 -0
  171. package/dist/web/public/terminal-keycode229-recovery.af09f99a.js +1 -0
  172. package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.br +0 -0
  173. package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.gz +0 -0
  174. package/dist/web/public/terminal-split.js +146 -649
  175. package/dist/web/public/terminal-split.js.br +0 -0
  176. package/dist/web/public/terminal-split.js.gz +0 -0
  177. package/dist/web/public/terminal-tile.js +1611 -0
  178. package/dist/web/public/terminal-tile.js.br +0 -0
  179. package/dist/web/public/terminal-tile.js.gz +0 -0
  180. package/dist/web/public/terminal-ui.5059b30e.js +2 -0
  181. package/dist/web/public/terminal-ui.5059b30e.js.br +0 -0
  182. package/dist/web/public/terminal-ui.5059b30e.js.gz +0 -0
  183. package/dist/web/public/tile-grid.js +2684 -0
  184. package/dist/web/public/tile-grid.js.br +0 -0
  185. package/dist/web/public/tile-grid.js.gz +0 -0
  186. package/dist/web/public/ultracode-panel.js.gz +0 -0
  187. package/dist/web/public/ultracode-windows.js.gz +0 -0
  188. package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
  189. package/dist/web/public/vendor/exceljs.min.js +44 -0
  190. package/dist/web/public/vendor/exceljs.min.js.br +0 -0
  191. package/dist/web/public/vendor/exceljs.min.js.gz +0 -0
  192. package/dist/web/public/vendor/fflate.min.js +1 -0
  193. package/dist/web/public/vendor/fflate.min.js.br +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.bbb5f84c.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.c4b51eb6.js → voice-input.2342c37b.js} +64 -10
  205. package/dist/web/public/voice-input.2342c37b.js.br +0 -0
  206. package/dist/web/public/voice-input.2342c37b.js.gz +0 -0
  207. package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
  208. package/dist/web/public/webview-tabs.js +9 -1
  209. package/dist/web/public/webview-tabs.js.br +0 -0
  210. package/dist/web/public/webview-tabs.js.gz +0 -0
  211. package/dist/web/routes/case-routes.d.ts.map +1 -1
  212. package/dist/web/routes/case-routes.js +136 -18
  213. package/dist/web/routes/case-routes.js.map +1 -1
  214. package/dist/web/routes/cli-registry-routes.d.ts.map +1 -1
  215. package/dist/web/routes/cli-registry-routes.js +3 -1
  216. package/dist/web/routes/cli-registry-routes.js.map +1 -1
  217. package/dist/web/routes/doctor-routes.d.ts +23 -0
  218. package/dist/web/routes/doctor-routes.d.ts.map +1 -0
  219. package/dist/web/routes/doctor-routes.js +83 -0
  220. package/dist/web/routes/doctor-routes.js.map +1 -0
  221. package/dist/web/routes/file-routes.d.ts +7 -0
  222. package/dist/web/routes/file-routes.d.ts.map +1 -1
  223. package/dist/web/routes/file-routes.js +34 -4
  224. package/dist/web/routes/file-routes.js.map +1 -1
  225. package/dist/web/routes/git-status-routes.d.ts +16 -0
  226. package/dist/web/routes/git-status-routes.d.ts.map +1 -0
  227. package/dist/web/routes/git-status-routes.js +98 -0
  228. package/dist/web/routes/git-status-routes.js.map +1 -0
  229. package/dist/web/routes/index.d.ts +2 -0
  230. package/dist/web/routes/index.d.ts.map +1 -1
  231. package/dist/web/routes/index.js +2 -0
  232. package/dist/web/routes/index.js.map +1 -1
  233. package/dist/web/routes/session-routes.d.ts +18 -0
  234. package/dist/web/routes/session-routes.d.ts.map +1 -1
  235. package/dist/web/routes/session-routes.js +106 -42
  236. package/dist/web/routes/session-routes.js.map +1 -1
  237. package/dist/web/routes/status-telemetry-routes.d.ts +3 -0
  238. package/dist/web/routes/status-telemetry-routes.d.ts.map +1 -1
  239. package/dist/web/routes/status-telemetry-routes.js +12 -0
  240. package/dist/web/routes/status-telemetry-routes.js.map +1 -1
  241. package/dist/web/routes/system-routes.d.ts.map +1 -1
  242. package/dist/web/routes/system-routes.js +13 -0
  243. package/dist/web/routes/system-routes.js.map +1 -1
  244. package/dist/web/schemas.d.ts +28 -0
  245. package/dist/web/schemas.d.ts.map +1 -1
  246. package/dist/web/schemas.js +41 -0
  247. package/dist/web/schemas.js.map +1 -1
  248. package/dist/web/server.d.ts +5 -0
  249. package/dist/web/server.d.ts.map +1 -1
  250. package/dist/web/server.js +35 -12
  251. package/dist/web/server.js.map +1 -1
  252. package/dist/web/session-listener-wiring.d.ts +1 -0
  253. package/dist/web/session-listener-wiring.d.ts.map +1 -1
  254. package/dist/web/session-listener-wiring.js +11 -0
  255. package/dist/web/session-listener-wiring.js.map +1 -1
  256. package/package.json +3 -1
  257. package/scripts/postinstall.js +16 -0
  258. package/skills/codeman/reference/verbs.md +3 -0
  259. package/dist/web/public/app.cf0db8ce.js +0 -43
  260. package/dist/web/public/app.cf0db8ce.js.br +0 -0
  261. package/dist/web/public/app.cf0db8ce.js.gz +0 -0
  262. package/dist/web/public/constants.d95fade9.js.br +0 -0
  263. package/dist/web/public/constants.d95fade9.js.gz +0 -0
  264. package/dist/web/public/i18n.398b8331.js +0 -1
  265. package/dist/web/public/i18n.398b8331.js.br +0 -0
  266. package/dist/web/public/i18n.398b8331.js.gz +0 -0
  267. package/dist/web/public/image-input.a216cf9e.js.br +0 -0
  268. package/dist/web/public/image-input.a216cf9e.js.gz +0 -0
  269. package/dist/web/public/mobile-handlers.23a85db1.js.br +0 -0
  270. package/dist/web/public/mobile-handlers.23a85db1.js.gz +0 -0
  271. package/dist/web/public/mobile.1aa4952d.css +0 -1
  272. package/dist/web/public/mobile.1aa4952d.css.br +0 -0
  273. package/dist/web/public/mobile.1aa4952d.css.gz +0 -0
  274. package/dist/web/public/panels-ui.6a5898d9.js.br +0 -0
  275. package/dist/web/public/session-ui.bf66c13b.js +0 -89
  276. package/dist/web/public/session-ui.bf66c13b.js.br +0 -0
  277. package/dist/web/public/session-ui.bf66c13b.js.gz +0 -0
  278. package/dist/web/public/settings-ui.331d3b1d.js +0 -97
  279. package/dist/web/public/settings-ui.331d3b1d.js.br +0 -0
  280. package/dist/web/public/settings-ui.331d3b1d.js.gz +0 -0
  281. package/dist/web/public/styles.8c485d26.css +0 -1
  282. package/dist/web/public/styles.8c485d26.css.br +0 -0
  283. package/dist/web/public/styles.8c485d26.css.gz +0 -0
  284. package/dist/web/public/tab-layout-browser.4e0ed50c.js +0 -1
  285. package/dist/web/public/tab-layout-browser.4e0ed50c.js.br +0 -0
  286. package/dist/web/public/tab-layout-browser.4e0ed50c.js.gz +0 -0
  287. package/dist/web/public/tab-rail-resize.dcdc5772.js.br +0 -0
  288. package/dist/web/public/tab-rail-resize.dcdc5772.js.gz +0 -0
  289. package/dist/web/public/terminal-keycode229-recovery.fb91b25b.js +0 -1
  290. package/dist/web/public/terminal-keycode229-recovery.fb91b25b.js.br +0 -0
  291. package/dist/web/public/terminal-keycode229-recovery.fb91b25b.js.gz +0 -0
  292. package/dist/web/public/terminal-ui.a4535311.js +0 -2
  293. package/dist/web/public/terminal-ui.a4535311.js.br +0 -0
  294. package/dist/web/public/terminal-ui.a4535311.js.gz +0 -0
  295. package/dist/web/public/upload.html +0 -155
  296. package/dist/web/public/upload.html.br +0 -0
  297. package/dist/web/public/upload.html.gz +0 -0
  298. package/dist/web/public/voice-input.c4b51eb6.js.br +0 -0
  299. package/dist/web/public/voice-input.c4b51eb6.js.gz +0 -0
@@ -8,6 +8,24 @@ import { type SessionMode, type CodexConfig, type GeminiConfig, type Antigravity
8
8
  import { RemoteWakeRegistry } from '../../remote-wake.js';
9
9
  import { clampEnvOverridesForOwner } from '../../session-env-clamp.js';
10
10
  import type { SessionPort, EventPort, ConfigPort, InfraPort, AuthPort, TabLayoutPort } from '../ports/index.js';
11
+ /**
12
+ * The replay half of the strip parity triangle: what `_handleTerminalOutput` (session.ts)
13
+ * removes from the live stream, removed again from a stored buffer before it is replayed,
14
+ * because a buffer recorded before the live-side strip existed (or by an older server)
15
+ * still carries the sequences, and one replayed enable is enough to re-park xterm.
16
+ *
17
+ * - `strip-full` (claude/codex/gemini): alt-screen toggles, `3J` and mouse DECSETs.
18
+ * xterm obeys the toggles by switching to its scrollback-less alt buffer and wiping
19
+ * saved lines, so history disappeared on tab switch.
20
+ * - `strip-mux-and-mouse` (opencode, tmux-backed): alt-screen toggles and mouse DECSETs.
21
+ * A replayed tracking enable parks xterm in report mode, where a drag goes to the CLI
22
+ * instead of selecting text (and Ctrl+C without a selection is opencode's app_exit).
23
+ * `3J` stays: a TUI is not a `clear` consumer.
24
+ * - every other mode, tmux-backed: tmux's own client smcup only (#205).
25
+ *
26
+ * Exported so the parity with the live strip is a test (claude-scrollback-strip.test.ts).
27
+ */
28
+ export declare function stripReplayBuffer(buffer: string, mode: SessionMode, usesMux: boolean): string;
11
29
  /**
12
30
  * Strip redundant Ink spinner/status-bar redraw frames from the terminal buffer.
13
31
  * Ink (Claude Code's TUI) uses absolute cursor positioning (CSI n d = VPA) to animate
@@ -1 +1 @@
1
- {"version":3,"file":"session-routes.d.ts","sourceRoot":"","sources":["../../../src/web/routes/session-routes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAqB,MAAM,SAAS,CAAC;AAS7D,OAAO,EAOL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,SAAS,EAEf,MAAM,gBAAgB,CAAC;AAoDxB,OAAO,EACL,kBAAkB,EAKnB,MAAM,sBAAsB,CAAC;AAwB9B,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAoCvE,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AA4EhH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA0C1D;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAmCvE;AAWD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAiBhF;AAGD,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAoED;;;;;;;GAOG;AACH,wBAAsB,+BAA+B,CACnD,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,YAAY,CAAC,EAAE,YAAY,EAC3B,iBAAiB,CAAC,EAAE,iBAAiB,EACrC,QAAQ,CAAC,EAAE,QAAQ,EACnB,UAAU,CAAC,EAAE,UAAU,EACvB,cAAc,CAAC,EAAE,cAAc,GAC9B,OAAO,CAAC;IACT,WAAW,EAAE,WAAW,GAAG,SAAS,CAAC;IACrC,YAAY,EAAE,YAAY,GAAG,SAAS,CAAC;IACvC,iBAAiB,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACjD,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC/B,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IACnC,cAAc,EAAE,cAAc,GAAG,SAAS,CAAC;CAC5C,CAAC,CAiBD;AAED,sEAAsE;AACtE,eAAO,MAAM,0BAA0B,kCAA4B,CAAC;AA8LpE,2FAA2F;AAC3F,wBAAgB,uBAAuB,IAAI,IAAI,CAI9C;AAED,+EAA+E;AAC/E,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AA2ED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,WAAW,EACjB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,SAAS,GAAG,SAAS,GAC/B,SAAS,GAAG,SAAS,CAYvB;AAsBD,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,aAAa;AAChF,oFAAoF;AACpF,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,kBAAkB,CAAA;CAAO,GAChD,kBAAkB,CA03IpB"}
1
+ {"version":3,"file":"session-routes.d.ts","sourceRoot":"","sources":["../../../src/web/routes/session-routes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAqB,MAAM,SAAS,CAAC;AAS7D,OAAO,EAOL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,SAAS,EAEf,MAAM,gBAAgB,CAAC;AAqDxB,OAAO,EACL,kBAAkB,EAKnB,MAAM,sBAAsB,CAAC;AAwB9B,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAqCvE,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AA6EhH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAY7F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA0C1D;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAmCvE;AAWD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAiBhF;AAGD,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAoED;;;;;;;GAOG;AACH,wBAAsB,+BAA+B,CACnD,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,YAAY,CAAC,EAAE,YAAY,EAC3B,iBAAiB,CAAC,EAAE,iBAAiB,EACrC,QAAQ,CAAC,EAAE,QAAQ,EACnB,UAAU,CAAC,EAAE,UAAU,EACvB,cAAc,CAAC,EAAE,cAAc,GAC9B,OAAO,CAAC;IACT,WAAW,EAAE,WAAW,GAAG,SAAS,CAAC;IACrC,YAAY,EAAE,YAAY,GAAG,SAAS,CAAC;IACvC,iBAAiB,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACjD,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC/B,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IACnC,cAAc,EAAE,cAAc,GAAG,SAAS,CAAC;CAC5C,CAAC,CAiBD;AAED,sEAAsE;AACtE,eAAO,MAAM,0BAA0B,kCAA4B,CAAC;AA8LpE,2FAA2F;AAC3F,wBAAgB,uBAAuB,IAAI,IAAI,CAI9C;AAED,+EAA+E;AAC/E,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AA2ED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,WAAW,EACjB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,SAAS,GAAG,SAAS,GAC/B,SAAS,GAAG,SAAS,CAYvB;AAoCD,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,aAAa;AAChF,oFAAoF;AACpF,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,kBAAkB,CAAA;CAAO,GAChD,kBAAkB,CAu5IpB"}
@@ -11,7 +11,7 @@ import fs from 'node:fs/promises';
11
11
  import { randomBytes, randomUUID } from 'node:crypto';
12
12
  import { performance } from 'node:perf_hooks';
13
13
  import { ApiErrorCode, createErrorResponse, getErrorMessage, } from '../../types.js';
14
- import { Session, cliTakesSessionModel, isAltScreenStripMode, isExternalCliMode, isMuxAltScreenOnlyStripMode, } from '../../session.js';
14
+ import { Session, cliTakesSessionModel, isAltScreenStripMode, isExternalCliMode, isMuxAltScreenOnlyStripMode, isMuxMouseStripMode, } from '../../session.js';
15
15
  import { SseEvent } from '../sse-events.js';
16
16
  import { webviewCapabilities } from '../../webview-capabilities.js';
17
17
  import { CreateSessionSchema, SessionNameSchema, SessionColorSchema, RunPromptSchema, SessionInputWithLimitSchema, ResizeSchema, AutoClearSchema, AutoCompactSchema, AutoResumeSchema, PinSessionSchema, ImageWatcherSchema, FlickerFilterSchema, QuickRunSchema, QuickStartSchema, InteractiveStartSchema, SessionOrderUpdateSchema, SessionWaitQuerySchema, SessionWaitOutputQuerySchema, CustomModelSelectionSchema, } from '../schemas.js';
@@ -30,6 +30,7 @@ import { canUsernameRunPrivilegedCommands, resolveClaudeModeForUsername } from '
30
30
  import { clampEnvOverridesForOwner } from '../../session-env-clamp.js';
31
31
  import { enabledClis, getCli } from '../../config/cli-registry/registry.js';
32
32
  import { resolveCliLaunchError } from '../../utils/cli-launcher.js';
33
+ import { applyLaunchDefaults } from '../launch-defaults.js';
33
34
  import { legacyConfigForMode } from '../../session-cli-registry-bridge.js';
34
35
  import { isMultiUserMode } from '../../config/multiuser.js';
35
36
  import { AUTH_COOKIE_NAME } from '../middleware/auth.js';
@@ -47,6 +48,7 @@ import { dataPath, getDataDir } from '../../config/instance.js';
47
48
  import { checkRemoteTmuxAvailable, readRemoteCases, readRemoteHosts, rehydrateRemoteHostFields, toAttachedSessionRemote, toSessionRemote, } from '../../remote-hosts.js';
48
49
  import { checkDockerAvailable, checkDockerConfigDrift, probeAdoptableContainer, checkDockerTmuxAvailable, ensureAgentBaseImage, DEFAULT_AGENT_IMAGE, persistDockerCaseClaudeSessionId, readDockerCases, readDockerHosts, toSessionDocker, } from '../../docker-hosts.js';
49
50
  import { LRUMap } from '../../utils/lru-map.js';
51
+ import { describeUnknownPath, probePathKind } from '../../utils/index.js';
50
52
  import { findLatestOmpSessionId } from '../../utils/omp-session-resolver.js';
51
53
  import { scanOmpSessionsHistory } from '../../omp-transcript.js';
52
54
  import { scanCodexSessionsHistory, codexThreadBySessionId } from '../../codex-transcript.js';
@@ -87,6 +89,37 @@ const ERASE_SCROLLBACK_PATTERN = /\x1b\[3J/g;
87
89
  // strip existed can still carry them; strip on replay for parity.
88
90
  // eslint-disable-next-line no-control-regex
89
91
  const MOUSE_TRACKING_PATTERN = /\x1b\[\?(?:1000|1001|1002|1003|1005|1006|1007)[hl]/g;
92
+ /**
93
+ * The replay half of the strip parity triangle: what `_handleTerminalOutput` (session.ts)
94
+ * removes from the live stream, removed again from a stored buffer before it is replayed,
95
+ * because a buffer recorded before the live-side strip existed (or by an older server)
96
+ * still carries the sequences, and one replayed enable is enough to re-park xterm.
97
+ *
98
+ * - `strip-full` (claude/codex/gemini): alt-screen toggles, `3J` and mouse DECSETs.
99
+ * xterm obeys the toggles by switching to its scrollback-less alt buffer and wiping
100
+ * saved lines, so history disappeared on tab switch.
101
+ * - `strip-mux-and-mouse` (opencode, tmux-backed): alt-screen toggles and mouse DECSETs.
102
+ * A replayed tracking enable parks xterm in report mode, where a drag goes to the CLI
103
+ * instead of selecting text (and Ctrl+C without a selection is opencode's app_exit).
104
+ * `3J` stays: a TUI is not a `clear` consumer.
105
+ * - every other mode, tmux-backed: tmux's own client smcup only (#205).
106
+ *
107
+ * Exported so the parity with the live strip is a test (claude-scrollback-strip.test.ts).
108
+ */
109
+ export function stripReplayBuffer(buffer, mode, usesMux) {
110
+ if (isAltScreenStripMode(mode)) {
111
+ return buffer
112
+ .replace(ALT_SCREEN_TOGGLE_PATTERN, '')
113
+ .replace(ERASE_SCROLLBACK_PATTERN, '')
114
+ .replace(MOUSE_TRACKING_PATTERN, '');
115
+ }
116
+ if (isMuxMouseStripMode(mode, usesMux)) {
117
+ return buffer.replace(ALT_SCREEN_TOGGLE_PATTERN, '').replace(MOUSE_TRACKING_PATTERN, '');
118
+ }
119
+ if (isMuxAltScreenOnlyStripMode(mode, usesMux))
120
+ return buffer.replace(ALT_SCREEN_TOGGLE_PATTERN, '');
121
+ return buffer;
122
+ }
90
123
  /**
91
124
  * Strip redundant Ink spinner/status-bar redraw frames from the terminal buffer.
92
125
  * Ink (Claude Code's TUI) uses absolute cursor positioning (CSI n d = VPA) to animate
@@ -592,6 +625,20 @@ export function resolveOmpConfigForCreate(mode, workingDir, ompConfig) {
592
625
  }
593
626
  return resolvedId ? { ...ompConfig, resumeSessionId: resolvedId } : ompConfig;
594
627
  }
628
+ /**
629
+ * The tmux history lines a full capture may read (`capture-pane -S -<n>`): the
630
+ * optional `lines` query parameter, an integer of at least 1, never more than
631
+ * the configured history limit; absent or malformed, the limit itself, as
632
+ * before. A grid tile sends its own scrollback size: its xterm keeps no more
633
+ * than that, while a capture of the whole history (tens of thousands of lines,
634
+ * cut to `tail` only afterwards) is synchronous work on this event loop.
635
+ */
636
+ function captureHistoryLines(raw, historyLimit) {
637
+ if (typeof raw !== 'string' || !/^\d{1,9}$/.test(raw))
638
+ return historyLimit;
639
+ const lines = Number(raw);
640
+ return lines >= 1 ? Math.min(lines, historyLimit) : historyLimit;
641
+ }
595
642
  /**
596
643
  * `RemoteHost` → the wake registry's host shape. They differ in one field name only
597
644
  * (`id` in host config vs `hostId` on a session's `remote`), but the rename is load-
@@ -760,17 +807,20 @@ options = {}) {
760
807
  if (!isWorkingDirAllowed(getAuthUser(req), workingDir)) {
761
808
  return createErrorResponse(ApiErrorCode.FORBIDDEN, 'workingDir is outside your workspace');
762
809
  }
763
- // Validate workingDir exists and is a directory
810
+ // Validate workingDir exists and is a directory. Bounded: a workingDir on a
811
+ // network mount that stopped answering must not freeze the event loop, and
812
+ // "did not answer" is reported as such, never as "does not exist".
764
813
  if (body.workingDir) {
765
- try {
766
- const stat = statSync(workingDir);
767
- if (!stat.isDirectory()) {
768
- return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'workingDir is not a directory');
769
- }
814
+ const kind = await probePathKind(workingDir, { pastCap: true });
815
+ if (kind === 'unknown') {
816
+ return createErrorResponse(ApiErrorCode.OPERATION_FAILED, describeUnknownPath('workingDir', workingDir, { pastCap: true }));
770
817
  }
771
- catch {
818
+ if (kind === 'absent') {
772
819
  return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'workingDir does not exist');
773
820
  }
821
+ if (kind !== 'directory') {
822
+ return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'workingDir is not a directory');
823
+ }
774
824
  }
775
825
  // envOverrides flow through Session → tmux setenv (ephemeral, per-session).
776
826
  //
@@ -876,6 +926,10 @@ options = {}) {
876
926
  const globalNice = await ctx.getGlobalNiceConfig();
877
927
  const modelConfig = await ctx.getModelConfig();
878
928
  const mode = body.mode || 'claude';
929
+ // Synced App Settings launch defaults (capabilities.launchDefaults, codex's model and
930
+ // effort today) fill the CLI's own config object where the caller left it unset.
931
+ // Local launches only: a remote attach runs whatever the remote pane already runs.
932
+ const launchBody = remote ? body : await applyLaunchDefaults(mode, body);
879
933
  // Where a model override comes from is a capability, and the three answers are
880
934
  // genuinely different mechanisms:
881
935
  // 'flag' — the CLI takes --model, so read the value the caller sent
@@ -889,7 +943,7 @@ options = {}) {
889
943
  // (docs/deepseek-integration.md). Both get nothing.
890
944
  const modelSource = getCli(mode)?.capabilities.model;
891
945
  const model = modelSource?.source === 'flag'
892
- ? legacyConfigForMode(mode, body)?.[modelSource.param ?? 'model']
946
+ ? legacyConfigForMode(mode, launchBody)?.[modelSource.param ?? 'model']
893
947
  : modelSource?.source === 'claude-settings-file'
894
948
  ? body.model || modelConfig?.defaultModel || undefined
895
949
  : undefined;
@@ -897,7 +951,7 @@ options = {}) {
897
951
  // Section 6.3: force non-granted users to a classifier-guarded mode.
898
952
  const effectiveClaudeMode = await resolveClaudeModeForUsername(claudeModeConfig.claudeMode, owner);
899
953
  // Section 6.3: clamp Codex/Gemini/Antigravity bypass switches for a non-granted owner (no-op single-user/granted).
900
- const { codexConfig: gatedCodexConfig, geminiConfig: gatedGeminiConfig, antigravityConfig: gatedAntigravityConfig, piConfig: gatedPiConfig, grokConfig: gatedGrokConfig, deepSeekConfig: gatedDeepSeekConfig, } = await _clampExternalCliBypassForOwner(owner, body.codexConfig, body.geminiConfig, body.antigravityConfig, body.piConfig, body.grokConfig, body.deepSeekConfig);
954
+ const { codexConfig: gatedCodexConfig, geminiConfig: gatedGeminiConfig, antigravityConfig: gatedAntigravityConfig, piConfig: gatedPiConfig, grokConfig: gatedGrokConfig, deepSeekConfig: gatedDeepSeekConfig, } = await _clampExternalCliBypassForOwner(owner, launchBody.codexConfig, launchBody.geminiConfig, launchBody.antigravityConfig, launchBody.piConfig, launchBody.grokConfig, launchBody.deepSeekConfig);
901
955
  const terminalHistoryConfig = await ctx.getTerminalHistoryConfig();
902
956
  const session = new Session({
903
957
  workingDir,
@@ -909,14 +963,14 @@ options = {}) {
909
963
  model,
910
964
  claudeMode: effectiveClaudeMode,
911
965
  allowedTools: claudeModeConfig.allowedTools,
912
- openCodeConfig: mode === 'opencode' ? body.openCodeConfig : undefined,
966
+ openCodeConfig: mode === 'opencode' ? launchBody.openCodeConfig : undefined,
913
967
  codexConfig: mode === 'codex' ? gatedCodexConfig : undefined,
914
968
  geminiConfig: mode === 'gemini' ? gatedGeminiConfig : undefined,
915
969
  antigravityConfig: mode === 'antigravity' ? gatedAntigravityConfig : undefined,
916
970
  piConfig: mode === 'pi' ? gatedPiConfig : undefined,
917
971
  grokConfig: mode === 'grok' ? gatedGrokConfig : undefined,
918
972
  deepSeekConfig: mode === 'deepseek' ? gatedDeepSeekConfig : undefined,
919
- ompConfig: resolveOmpConfigForCreate(mode, workingDir, body.ompConfig),
973
+ ompConfig: resolveOmpConfigForCreate(mode, workingDir, launchBody.ompConfig),
920
974
  resumeSessionId: validatedResumeId,
921
975
  envOverrides: await clampEnvOverridesForOwner(owner, body.envOverrides),
922
976
  effort: body.effort,
@@ -2590,8 +2644,14 @@ options = {}) {
2590
2644
  // single reason: `capturedGeometry` comes BACK on it, and the response has
2591
2645
  // to tell the client what size the frame it is about to render was built
2592
2646
  // for. See PaneCaptureOptions.capturedGeometry.
2647
+ // `lines` bounds only the history a FULL capture reads; the visible-frame
2648
+ // path reads no history and is untouched by it.
2593
2649
  const captureOpts = isFullReload
2594
- ? { fullHistory: true, historyLimitLines: tmuxHistoryLimit, maxCaptureBytes: terminalBufferMaxBytes }
2650
+ ? {
2651
+ fullHistory: true,
2652
+ historyLimitLines: captureHistoryLines(query.lines, tmuxHistoryLimit),
2653
+ maxCaptureBytes: terminalBufferMaxBytes,
2654
+ }
2595
2655
  : {};
2596
2656
  const liveMuxBuffer = muxName && typeof ctx.mux.captureActivePaneBuffer === 'function'
2597
2657
  ? ctx.mux.captureActivePaneBuffer(muxName, captureOpts)
@@ -2663,22 +2723,9 @@ options = {}) {
2663
2723
  let strippedBuffer = isFullCapture || getCli(session.mode)?.capabilities.stripInkBloat === false
2664
2724
  ? rawBuffer
2665
2725
  : stripInkRedrawBloat(rawBuffer);
2666
- // Strip alt-screen toggles and scrollback-erase from Codex/Claude byte
2667
- // streams. xterm.js obeys them by switching to its scrollback-less alt
2668
- // buffer and wiping saved lines, so conversation history disappears on tab
2669
- // switch. Same gate as the live-stream strip in session.ts.
2670
- if (isAltScreenStripMode(session.mode)) {
2671
- strippedBuffer = strippedBuffer
2672
- .replace(ALT_SCREEN_TOGGLE_PATTERN, '')
2673
- .replace(ERASE_SCROLLBACK_PATTERN, '')
2674
- .replace(MOUSE_TRACKING_PATTERN, '');
2675
- }
2676
- else if (isMuxAltScreenOnlyStripMode(session.mode, session.usesMux)) {
2677
- // tmux-backed shell/opencode/antigravity: drop tmux's own client smcup only.
2678
- // A byte buffer recorded before the live-side strip existed can still carry
2679
- // it, and one replayed `\x1b[?1049h` re-parks xterm in the alt buffer (#205).
2680
- strippedBuffer = strippedBuffer.replace(ALT_SCREEN_TOGGLE_PATTERN, '');
2681
- }
2726
+ // Same strip as the live stream (session.ts), so a buffer recorded before the
2727
+ // live-side strip existed cannot re-park xterm on replay. See stripReplayBuffer.
2728
+ strippedBuffer = stripReplayBuffer(strippedBuffer, session.mode, session.usesMux);
2682
2729
  if (tailBytes > 0 && strippedBuffer.length > tailBytes) {
2683
2730
  // Fast path: tail from the end, skip expensive banner search on full 2MB buffer.
2684
2731
  // Banner is near the top and gets discarded by tail anyway.
@@ -3175,9 +3222,17 @@ options = {}) {
3175
3222
  if (!remote && !isWorkingDirAllowed(getAuthUser(req), resolvedCasePath)) {
3176
3223
  return createErrorResponse(ApiErrorCode.FORBIDDEN, 'case path is outside your workspace');
3177
3224
  }
3225
+ // Bounded probe of a local case folder: a linked case can sit on a network mount
3226
+ // that stopped answering, and a synchronous check there froze the whole server.
3227
+ // Only a DEFINITE absence may scaffold a new case; "did not answer" must not
3228
+ // create one over the top of where the real case is mounted.
3229
+ const localCaseState = remote || docker ? undefined : await probePathKind(resolvedCasePath, { pastCap: true });
3230
+ if (localCaseState === 'unknown') {
3231
+ return createErrorResponse(ApiErrorCode.OPERATION_FAILED, describeUnknownPath('Case folder', resolvedCasePath, { pastCap: true }));
3232
+ }
3178
3233
  // Create case folder and CLAUDE.md if it doesn't exist (only for non-linked, non-remote,
3179
3234
  // non-docker cases — docker workspaces are scaffolded in their own block below)
3180
- if (!remote && !docker && !existsSync(resolvedCasePath)) {
3235
+ if (localCaseState === 'absent') {
3181
3236
  try {
3182
3237
  mkdirSync(resolvedCasePath, { recursive: true });
3183
3238
  mkdirSync(join(resolvedCasePath, 'src'), { recursive: true });
@@ -3283,28 +3338,37 @@ options = {}) {
3283
3338
  // Apply global Nice priority config and model config from settings
3284
3339
  const niceConfig = await ctx.getGlobalNiceConfig();
3285
3340
  const qsModelConfig = await ctx.getModelConfig();
3341
+ // Synced App Settings launch defaults, as on the create path: local launches only, so
3342
+ // never a remote or Docker case, and never a custom model endpoint launch.
3343
+ const qsRequestConfigs = {
3344
+ openCodeConfig,
3345
+ codexConfig,
3346
+ geminiConfig,
3347
+ antigravityConfig,
3348
+ piConfig,
3349
+ grokConfig,
3350
+ deepSeekConfig,
3351
+ ompConfig,
3352
+ };
3353
+ const qsLaunchConfigs = remote || docker ? qsRequestConfigs : await applyLaunchDefaults(mode, qsRequestConfigs, !!customModel);
3354
+ // ⚠️ The model is read from a bag WITHOUT ompConfig, as it always was here: quick-start
3355
+ // has never taken omp's session model from ompConfig (the create path does). Kept as
3356
+ // found rather than changed in passing.
3357
+ const { ompConfig: qsLaunchOmpConfig, ...qsModelConfigs } = qsLaunchConfigs;
3286
3358
  // See the create path for why this is a capability rather than a mode ladder.
3287
3359
  const qsModelSource = getCli(mode)?.capabilities.model;
3288
3360
  const qsModel = qsModelSource?.source === 'flag'
3289
- ? legacyConfigForMode(mode, {
3290
- openCodeConfig,
3291
- codexConfig,
3292
- geminiConfig,
3293
- antigravityConfig,
3294
- piConfig,
3295
- grokConfig,
3296
- deepSeekConfig,
3297
- })?.[qsModelSource.param ?? 'model']
3361
+ ? legacyConfigForMode(mode, qsModelConfigs)?.[qsModelSource.param ?? 'model']
3298
3362
  : qsModelSource?.source === 'claude-settings-file'
3299
3363
  ? qsModelConfig?.defaultModel || undefined
3300
3364
  : undefined;
3301
3365
  const qsClaudeModeConfig = await ctx.getClaudeModeConfig();
3302
3366
  const qsEffectiveClaudeMode = await resolveClaudeModeForUsername(qsClaudeModeConfig.claudeMode, owner);
3303
3367
  // Section 6.3: clamp Codex/Gemini/Antigravity bypass switches for a non-granted owner (no-op single-user/granted).
3304
- const { codexConfig: qsGatedCodexConfig, geminiConfig: qsGatedGeminiConfig, antigravityConfig: qsGatedAntigravityConfig, piConfig: qsGatedPiConfig, grokConfig: qsGatedGrokConfig, deepSeekConfig: qsGatedDeepSeekConfig, } = await _clampExternalCliBypassForOwner(owner, codexConfig, geminiConfig, antigravityConfig, piConfig, grokConfig, deepSeekConfig);
3368
+ const { codexConfig: qsGatedCodexConfig, geminiConfig: qsGatedGeminiConfig, antigravityConfig: qsGatedAntigravityConfig, piConfig: qsGatedPiConfig, grokConfig: qsGatedGrokConfig, deepSeekConfig: qsGatedDeepSeekConfig, } = await _clampExternalCliBypassForOwner(owner, qsLaunchConfigs.codexConfig, qsLaunchConfigs.geminiConfig, qsLaunchConfigs.antigravityConfig, qsLaunchConfigs.piConfig, qsLaunchConfigs.grokConfig, qsLaunchConfigs.deepSeekConfig);
3305
3369
  const qsTerminalHistoryConfig = await ctx.getTerminalHistoryConfig();
3306
3370
  const qsGatedEnvOverrides = await clampEnvOverridesForOwner(owner, envOverrides);
3307
- const qsResolvedOmpConfig = resolveOmpConfigForCreate(mode, resolvedCasePath, ompConfig);
3371
+ const qsResolvedOmpConfig = resolveOmpConfigForCreate(mode, resolvedCasePath, qsLaunchOmpConfig);
3308
3372
  // Custom Model Endpoint Profiles, applied AT CREATE TIME (docs/custom-model-endpoints-plan.md)
3309
3373
  // rather than via the dedicated restart-in-place route (POST /api/sessions/:id/custom-
3310
3374
  // model, still what an ALREADY-RUNNING session uses to switch later): computing the
@@ -3430,7 +3494,7 @@ options = {}) {
3430
3494
  claudeMode: qsEffectiveClaudeMode,
3431
3495
  allowedTools: qsClaudeModeConfig.allowedTools,
3432
3496
  owner,
3433
- openCodeConfig: mode === 'opencode' ? openCodeConfig : undefined,
3497
+ openCodeConfig: mode === 'opencode' ? qsLaunchConfigs.openCodeConfig : undefined,
3434
3498
  codexConfig: mode === 'codex' ? qsGatedCodexConfig : undefined,
3435
3499
  geminiConfig: mode === 'gemini' ? qsGatedGeminiConfig : undefined,
3436
3500
  antigravityConfig: mode === 'antigravity' ? qsGatedAntigravityConfig : undefined,