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
@@ -0,0 +1 @@
1
+ html.mobile-init .header-font-controls,html.mobile-init .header-system-stats,html.mobile-init .header-tokens,html.mobile-init .monitor-panel,html.mobile-init .subagents-panel,html.mobile-init .project-insights-panel,html.mobile-init .file-browser-panel{display:none!important}@media(max-width:768px){input,textarea,select{font-size:16px!important}html{touch-action:manipulation}html:not(.host-windows) .session-tab .tab-detach{display:none!important}}@media(max-width:768px)and (min-width:600px){.header{position:fixed;top:0;left:0;right:0;min-height:48px;max-height:48px;padding:.35rem .5rem;padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right));background:#0a0a0a;border-bottom:1px solid rgba(255,255,255,.08);contain:none;overflow:visible;z-index:1200}.ios-device .header{padding-top:calc(.35rem + var(--safe-area-top));min-height:calc(48px + var(--safe-area-top));max-height:calc(48px + var(--safe-area-top))}.app{padding-top:54px}.ios-device .app{padding-top:calc(54px + var(--safe-area-top))}.header-font-controls{gap:.15rem;padding:.15rem .25rem}.header-font-controls .btn-icon-sm{width:18px;height:18px}.header-system-stats{font-size:.6rem;gap:.25rem}.header-right{gap:.35rem}.btn-icon-header:not(.btn-sm){width:44px;height:44px}.session-tabs,.session-tabs.tabs-two-rows{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;scrollbar-width:none;max-height:52px;gap:3px}.session-tabs::-webkit-scrollbar{display:none}.session-tab{padding:.4rem .6rem;font-size:.75rem;min-height:40px}.session-tab .tab-name{max-width:80px}.toolbar{padding:.4rem .5rem;padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right));gap:.4rem}.tab-count-group{display:none}.btn-toolbar{padding:.4rem .8rem;font-size:.8rem;min-height:40px}.case-select-group{max-width:none}.case-combobox{width:160px}.toolbar-select{font-size:.75rem}.monitor-panel,.subagents-panel{width:100%;max-width:100%;left:0;right:0;border-radius:8px 8px 0 0;max-height:40vh}.project-insights-panel{max-width:280px;font-size:.7rem}.modal{z-index:1300}.command-palette-modal{padding:10vh .75rem 0}.command-palette-shell{width:100%;max-height:74vh}.command-palette-input-row{grid-template-columns:20px minmax(0,1fr)}.command-palette-input-row kbd{display:none}.command-palette-item{min-height:56px}.settings-grid{gap:.4rem .75rem}.settings-item{font-size:.7rem}.event-type-grid{grid-template-columns:1fr 40px 40px 40px;gap:5px 6px}.event-label{font-size:.7rem}.subagent-window{width:320px;height:280px;min-width:240px;min-height:160px}.subagent-window-header{padding:.35rem .5rem}.subagent-window-title .id{font-size:.7rem;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.subagent-window-title .status{font-size:.55rem}.subagent-window-body{font-size:.7rem}.respawn-banner{padding:.25rem .5rem;padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right));font-size:.65rem}.respawn-compact-layout{gap:.75rem}.respawn-status-row1{gap:.4rem}.respawn-action-log{max-height:2.6em;font-size:.6rem}.respawn-countdown-timer{font-size:.55rem}.respawn-timer-bar{width:24px}.toolbar-center .btn-toolbar.btn-voice{display:flex!important}.toolbar{padding:0 .5rem;gap:.5rem}.toolbar-left,.toolbar-right,.toolbar-group{gap:.5rem}.btn-toolbar{padding:.4rem .75rem;font-size:.75rem;min-height:unset}}@media(min-width:600px)and (max-width:767px){:where(.header) .session-tabs-host>.session-tabs.tabs-clusters>.tab-cluster{display:contents}:where(.header) .tab-cluster-label{display:none}:where(.header) .session-tabs-host>.session-tabs.tabs-clusters .tab-name-case{display:inline}}@property --tab-strip-fade-start{syntax: "<length>"; inherits: false; initial-value: 0px;}@property --tab-strip-fade-end{syntax: "<length>"; inherits: false; initial-value: 0px;}@keyframes tab-strip-edge-fade{0%{--tab-strip-fade-start: 0px;--tab-strip-fade-end: 28px}10%,90%{--tab-strip-fade-start: 28px;--tab-strip-fade-end: 28px}to{--tab-strip-fade-start: 28px;--tab-strip-fade-end: 0px}}@media(max-width:599px){:root{--header-height: 44px}.header-brand{padding-right:0;margin-right:.1rem;border-right:none}.header-brand .logo{display:inline-flex;align-items:center;justify-content:center;min-width:44px;height:var(--header-height);margin-left:-.3rem;font-size:1.15rem;line-height:1;border-radius:8px;-webkit-tap-highlight-color:transparent}.header-brand .logo:active{background:#60a5fa29}.header-brand .logo .logo-text{display:none}.header-brand .logo .logo-compact{display:inline}.header-font-controls{gap:.1rem;padding:.1rem .2rem}.header-font-controls .btn-icon-sm{width:16px;height:16px}.header-font-controls .font-size-display{font-size:.6rem;min-width:14px}.header-system-stats{font-size:.55rem;gap:.15rem}.header-tokens{font-size:.6rem;padding:.1rem .3rem}.header{position:fixed;top:0;left:0;right:0;min-height:var(--header-height);max-height:var(--header-height);align-items:center;padding:.15rem .3rem;padding-left:calc(.3rem + var(--safe-area-left));padding-right:calc(.3rem + var(--safe-area-right));gap:.15rem;overflow:hidden;background:#0a0a0a;border-bottom:1px solid rgba(255,255,255,.08);contain:none;z-index:1200}.ios-device .header{padding-top:calc(.15rem + var(--safe-area-top));min-height:calc(var(--header-height) + var(--safe-area-top));max-height:calc(var(--header-height) + var(--safe-area-top))}.app{padding-top:calc(var(--header-height) + 6px)}.ios-device .app{padding-top:calc(var(--header-height) + 6px + var(--safe-area-top))}.main{padding-bottom:calc(40px + var(--safe-area-bottom))}.ios-device.safari-browser .main{padding-bottom:calc(40px + var(--safe-area-bottom) + var(--chrome-overlap, 0px))}.header-right{padding-left:.2rem;gap:.1rem;flex-shrink:0;border-left:none}.btn-icon-header{width:26px;height:26px;padding:0}.btn-icon-header svg{width:12px;height:12px}html[data-session-list=sidebar] #sidebarToggleBtn{width:44px;height:44px}html[data-session-list=sidebar] #sidebarToggleBtn svg{width:18px;height:18px}.btn-icon-header.btn-settings,.btn-icon-header.btn-lifecycle-log,.btn-icon-header.btn-away-digest,.btn-icon-header.btn-session-manager,.btn-icon-header.btn-file-viewer,.btn-icon-header.btn-approvals,.btn-icon-header.btn-readmymind,.btn-admin-panel{display:none!important}.btn-voice-mobile,.btn-attach-mobile{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;background:#1a2a3f;border:1px solid rgba(59,130,246,.3);border-radius:4px;color:#93c5fd;cursor:pointer;flex-shrink:0}.btn-voice-mobile,.btn-attach-mobile-wrap{order:5}.btn-attach-mobile-wrap{position:relative;display:inline-flex;flex-shrink:0;overflow:hidden}.btn-attach-mobile-input{position:absolute;inset:0;width:100%;height:100%;opacity:0}.btn-voice-mobile svg,.btn-attach-mobile svg{width:13px;height:13px}.btn-voice-mobile:active,.btn-attach-mobile:active,.btn-attach-mobile-wrap:active .btn-attach-mobile{background:#2a3a5f}.btn-voice-mobile.recording{background:#ef444440;border-color:#ef444499;color:#ef4444;animation:mobile-voice-pulse 1.2s ease-in-out infinite}@keyframes mobile-voice-pulse{0%,to{box-shadow:inset 0 0 0 1px #ef444459;background:#ef444433}50%{box-shadow:inset 0 0 0 2px #ef4444bf;background:#ef444459}}.btn-settings-mobile{display:inline-flex!important;align-items:center;justify-content:center;width:26px;height:26px;background:transparent;border:1px solid rgba(255,255,255,.2);border-radius:4px;color:#9ca3af;font-size:.85rem;cursor:pointer;flex-shrink:0;order:6;position:relative}.btn-settings-mobile svg{width:13px;height:13px}.btn-settings-mobile:active{background:#ffffff1a;color:#fff}.app{overflow:hidden;position:relative}.keyboard-visible .app{position:fixed;inset:0 0 auto;height:var(--app-height, 100dvh)}.session-tabs,.session-tabs.tabs-two-rows{flex:1;flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;scrollbar-width:none;max-height:36px;gap:6px;padding:0}.session-tabs::-webkit-scrollbar{display:none}@supports (animation-timeline: scroll()){.header .session-tabs{-webkit-mask-image:linear-gradient(to right,transparent,#000 var(--tab-strip-fade-start),#000 calc(100% - var(--tab-strip-fade-end)),transparent);mask-image:linear-gradient(to right,transparent,#000 var(--tab-strip-fade-start),#000 calc(100% - var(--tab-strip-fade-end)),transparent);animation:tab-strip-edge-fade linear both;animation-timeline:scroll(self inline)}}.session-tab{flex-shrink:0;min-height:32px;max-height:32px;padding:.35rem .5rem;font-size:.7rem;gap:.25rem;border-radius:4px}:where(.header) .session-tab{border-radius:8px;background:var(--control-bg-hover);border-color:var(--control-border-hover);color:var(--text)}:where(.header) .session-tab .tab-name{font-weight:500}:where(.header) .tab-triage-head{display:none}:where(.header) .session-tabs-host>.session-tabs.tabs-clusters>.tab-cluster{display:contents}:where(.header) .tab-cluster-label{display:none}:where(.header) .session-tabs-host>.session-tabs.tabs-clusters .tab-name-case{display:inline}:where(.header) .session-tab:not(.active) .tab-actions{display:none}:where(.header) .session-tab .tab-number{display:none}.session-tab .tab-status{width:6px;height:6px}.session-tab .tab-status.busy{width:9px;height:9px;box-shadow:0 0 8px 2px color-mix(in srgb,var(--green) 55%,transparent)!important}.session-tab .tab-status.busy:after{display:none}.session-tab.tab-agent-exited:not(.tab-alert-action):not(.tab-alert-idle) .tab-status:not(.error){background:var(--text-muted)!important;box-shadow:none!important;opacity:.5}.session-tab .tab-name{max-width:80px;overflow:hidden;text-overflow:ellipsis}.session-tab.active .tab-name{min-width:44px}.session-tab .tab-close,.session-tab .tab-gear{display:none}.session-tab .tab-detach{display:none!important}.session-tab.active .tab-gear{display:inline-flex;align-items:center;justify-content:center;font-size:.65rem;line-height:1;width:32px;height:32px;margin-left:auto;opacity:.6}.session-tab.active .tab-close{display:inline-flex;align-items:center;justify-content:center;font-size:1.1rem;line-height:1;width:20px;height:18px;margin-left:-2px}.toolbar{position:fixed;bottom:var(--safe-area-bottom);left:0;right:0;height:40px;min-height:40px;max-height:40px;padding:.3rem .4rem;padding-left:calc(.4rem + var(--safe-area-left));padding-right:calc(.4rem + var(--safe-area-right));flex-wrap:nowrap;gap:.3rem;align-items:center;justify-content:space-between;background:#111;border-top:1px solid rgba(255,255,255,.1);z-index:50;transition:transform .15s ease-out;will-change:transform}.ios-device.safari-browser .toolbar{bottom:calc(var(--safe-area-bottom) + var(--chrome-overlap, 0px))}.keyboard-visible.ios-device.safari-browser .toolbar{bottom:var(--safe-area-bottom)}.keyboard-visible.ios-device.safari-browser .keyboard-accessory-bar{bottom:calc(var(--safe-area-bottom) + 40px)}.toolbar-center{display:flex!important;align-items:center}.toolbar-center .btn-toolbar.btn-voice,.toolbar-right,.version-display{display:none!important}.toolbar-left{flex:1 1 0;min-width:0;align-items:center;gap:.3rem}.toolbar-left .toolbar-group{display:flex;flex:1 1 0;min-width:0;align-items:center;gap:.3rem}.toolbar-left .toolbar-group:first-child{flex:1 1 0;min-width:0;justify-content:space-between;gap:.3rem;flex-wrap:nowrap;align-items:center}.tab-count-group{display:none!important}.btn-toolbar{min-height:26px!important;max-height:26px!important;height:26px!important;padding:0 .5rem!important;font-size:.65rem!important;border-radius:4px;line-height:26px;display:inline-flex;align-items:center;justify-content:center;font-weight:500;letter-spacing:.01em;color:#fff}.run-btn-group{display:flex;flex:0 0 auto}.btn-toolbar.btn-run{flex:0 0 auto;padding:0 .6rem!important;font-weight:500;border-radius:4px 0 0 4px!important;border-right:none!important}.btn-toolbar.btn-run svg{width:10px;height:10px;margin-right:3px}.btn-toolbar.btn-run-gear{flex:0 0 auto;padding:0 .35rem!important;min-width:unset!important;border-radius:0 4px 4px 0!important;border-left:1px solid rgba(255,255,255,.15)!important}.btn-toolbar.btn-run-gear svg{width:10px;height:10px}.btn-toolbar.btn-run.mode-claude,.btn-toolbar.btn-run-gear.mode-claude{background:#1e3a5f;border-color:#3b82f64d;color:#93c5fd}.btn-toolbar.btn-run.mode-claude:active,.btn-toolbar.btn-run-gear.mode-claude:active{background:#2563eb;border-color:#3b82f680}.btn-toolbar.btn-run.mode-opencode,.btn-toolbar.btn-run-gear.mode-opencode{background:#0a2e2a;border-color:#10b9814d;color:#6ee7b7}.btn-toolbar.btn-run.mode-opencode:active,.btn-toolbar.btn-run-gear.mode-opencode:active{background:#0d4a40;border-color:#10b98180}.btn-toolbar.btn-run.mode-gemini,.btn-toolbar.btn-run-gear.mode-gemini{background:#10243f!important;border-color:#60a5fa4d!important;color:#dbeafe!important}.btn-toolbar.btn-run.mode-gemini:active,.btn-toolbar.btn-run-gear.mode-gemini:active{background:#174ea6!important;border-color:#60a5fa80!important}.btn-toolbar.btn-run.mode-antigravity,.btn-toolbar.btn-run-gear.mode-antigravity{background:#0b2b33!important;border-color:#22d3ee4d!important;color:#cffafe!important}.btn-toolbar.btn-run.mode-antigravity:active,.btn-toolbar.btn-run-gear.mode-antigravity:active{background:#0e7490!important;border-color:#22d3ee80!important}.btn-toolbar.btn-run.mode-pi,.btn-toolbar.btn-run-gear.mode-pi{background:#33121f!important;border-color:#f472b64d!important;color:#fce7f3!important}.btn-toolbar.btn-run.mode-pi:active,.btn-toolbar.btn-run-gear.mode-pi:active{background:#9d174d!important;border-color:#f472b680!important}.btn-toolbar.btn-run.mode-grok,.btn-toolbar.btn-run-gear.mode-grok{background:#1c1c1f!important;border-color:#d4d4d84d!important;color:#f4f4f5!important}.btn-toolbar.btn-run.mode-grok:active,.btn-toolbar.btn-run-gear.mode-grok:active{background:#3f3f46!important;border-color:#d4d4d880!important}.btn-toolbar.btn-run.mode-deepseek,.btn-toolbar.btn-run-gear.mode-deepseek{background:#16225f!important;border-color:#7c93ff59!important;color:#eef2ff!important}.btn-toolbar.btn-run.mode-deepseek:active,.btn-toolbar.btn-run-gear.mode-deepseek:active{background:#3350e6!important;border-color:#96aaff8c!important}.btn-toolbar.btn-run.mode-omp,.btn-toolbar.btn-run-gear.mode-omp{background:#312e81!important;border-color:#818cf84d!important;color:#e0e7ff!important}.btn-toolbar.btn-run.mode-omp:active,.btn-toolbar.btn-run-gear.mode-omp:active{background:#4f46e5!important;border-color:#818cf880!important}.btn-toolbar.btn-run.mode-copilot,.btn-toolbar.btn-run-gear.mode-copilot{background:#2e1065!important;border-color:#a371f74d!important;color:#ede9fe!important}.btn-toolbar.btn-run.mode-copilot:active,.btn-toolbar.btn-run-gear.mode-copilot:active{background:#6d28d9!important;border-color:#a371f780!important}.run-mode-menu{bottom:100%;left:0;margin-bottom:6px;min-width:160px;max-width:80vw}.run-mode-option{padding:10px 12px;font-size:.8rem;cursor:pointer;-webkit-tap-highlight-color:rgba(255,255,255,.1)}.run-mode-row-btn{width:34px;height:34px;font-size:1rem;-webkit-tap-highlight-color:rgba(255,255,255,.1)}.run-mode-webview-delete{font-size:1.2rem}.run-mode-history{-webkit-overflow-scrolling:touch;touch-action:manipulation}.btn-toolbar.btn-stop{display:flex!important;flex:0 0 auto;padding:0 8px!important;min-width:unset;order:3}.btn-toolbar.btn-stop svg{width:10px;height:10px;margin-right:0}.btn-toolbar.btn-shell{display:none!important}.btn-toolbar.btn-enter{display:flex!important;flex:0 0 auto;align-items:center;justify-content:center;min-width:54px;width:54px;white-space:nowrap;padding:0 8px!important;overflow:hidden;font-size:.65rem;font-weight:600;letter-spacing:.01em;background:#1e3a5fd9!important;border:1px solid rgba(59,130,246,.45)!important;color:#dbeafe!important;order:4}.btn-toolbar.btn-enter:hover,.btn-toolbar.btn-enter:active{background:#254a7af2!important;border-color:#3b82f6b3!important;color:#fff!important}.case-select-group{display:none!important}.toolbar-left .toolbar-group:first-child{width:100%;gap:8px}.btn-toolbar.btn-case-mobile{display:flex!important;flex:1 1 0!important;min-width:0;padding:0 8px!important;order:2;overflow:hidden;justify-content:center;gap:4px}.btn-toolbar.btn-case-mobile #mobileCaseName{max-width:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.btn-case-settings-mobile{display:inline-flex!important;align-items:center;justify-content:center;width:26px;height:26px;background:transparent;border:1px solid rgba(255,255,255,.2);border-radius:4px;color:#9ca3af;cursor:pointer;flex-shrink:0;order:1}.btn-case-settings-mobile:active{background:#ffffff1a;color:#fff}@media(max-width:374px){.toolbar{padding:0 2px}.toolbar-left,.toolbar-left .toolbar-group,.toolbar-left .toolbar-group:first-child{gap:2px}}.btn-case-settings-mobile{display:none!important}.case-settings-popover-mobile{position:fixed;bottom:calc(var(--safe-area-bottom) + 46px);left:8px;right:8px;background:#1e1e1e;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:.6rem .75rem;z-index:1000;box-shadow:0 4px 16px #00000080;display:block}.case-settings-popover-mobile.hidden{display:none!important}.case-settings-popover-mobile .checkbox-inline{display:flex;align-items:center;gap:6px;font-size:.75rem;color:#e5e7eb}.case-settings-popover-mobile .form-hint{display:block;margin-top:.2rem;font-size:.6rem;color:#6b7280}.keyboard-accessory-bar{display:none;position:fixed;bottom:calc(var(--safe-area-bottom) + 40px);left:0;right:0;height:44px;background:#1a1a1a;border-top:1px solid rgba(255,255,255,.1);padding:6px 8px;padding-left:calc(8px + var(--safe-area-left));padding-right:calc(8px + var(--safe-area-right));gap:8px;align-items:center;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;z-index:51;transition:transform .15s ease-out;will-change:transform}.keyboard-accessory-bar.visible{display:flex}.keyboard-accessory-bar::-webkit-scrollbar{display:none}.accessory-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;gap:4px;padding:6px 12px;background:#2a2a2a;border:1px solid rgba(255,255,255,.15);border-radius:6px;color:#e5e5e5;font-size:.65rem;font-weight:500;cursor:pointer;transition:background .15s,border-color .15s}.accessory-btn.confirming{background:#6b4f00;border-color:#b8860b;color:#ffd54f}.accessory-btn.accessory-btn-ctrl.armed{background:#2563eb;border-color:#3b82f6e6;color:#fff;font-weight:700;box-shadow:0 0 0 2px #3b82f673}.accessory-btn:active{background:#3a3a3a}.accessory-btn svg{width:14px;height:14px}.accessory-btn-arrow{padding:6px 10px;background:#2563eb;border-color:#3b82f680;color:#fff}.accessory-btn-arrow:active{background:#1d4ed8}.accessory-btn-dismiss{margin-left:auto;flex:1 1 0;max-width:100px;padding:10px 8px;background:#2563eb;border-color:#3b82f680;color:#fff;font-weight:600}.accessory-btn-dismiss svg{width:22px;height:22px}.accessory-btn-dismiss:active{background:#1d4ed8}.voice-preview{bottom:calc(var(--safe-area-bottom) + 94px);font-size:.8rem;max-width:90%;padding:6px 14px}.toolbar-select{display:none!important}.monitor-panel,.subagents-panel{width:100%;max-width:100%;left:0;right:0;border-radius:8px 8px 0 0;bottom:calc(44px + 2rem + var(--safe-area-bottom));max-height:35vh}.modal{z-index:1300}.modal-content{width:100%;max-width:100%;height:100%;max-height:100%;border-radius:0;margin:0;display:flex;flex-direction:column}.modal-content.modal-sm,.modal-content.readmymind-modal{height:auto;max-height:85vh;border-radius:12px;margin:1rem;width:calc(100% - 2rem)}.readmymind-modal .modal-footer{flex-wrap:wrap}.readmymind-modal .modal-footer .btn-toolbar{flex:1 1 auto;justify-content:center;min-height:38px}.readmymind-alt,.readmymind-steer-input{min-height:38px}.ios-device .modal-content{padding-top:var(--safe-area-top);padding-bottom:var(--safe-area-bottom);padding-left:var(--safe-area-left);padding-right:var(--safe-area-right)}.modal-header{padding:.75rem 1rem}.modal-header h3{font-size:1rem}.modal-body{padding:.75rem 1rem;flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch}.away-digest-modal{width:100%;max-width:100%;height:100%;max-height:100%}.away-digest-ranges{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.4rem}.away-digest-ranges .filter-btn{min-height:38px;padding:.4rem .5rem}.away-digest-custom-range,.away-digest-custom-range.active{grid-template-columns:1fr}.away-digest-summary{grid-template-columns:repeat(2,minmax(0,1fr));gap:.5rem}.away-digest-item{grid-template-columns:1fr;gap:.5rem}.away-digest-action{width:100%;min-height:38px}.modal-footer,.form-actions{padding:.75rem 1rem;padding-bottom:calc(.75rem + var(--safe-area-bottom))}.ios-device .terminal-container{padding-bottom:var(--safe-area-bottom)}.main{flex:1;min-height:0}.cli-info-bar{display:block}.terminal-container{height:100%;min-height:0;position:relative;overflow:visible;touch-action:none}.terminal-container .xterm,.terminal-container .xterm-viewport,.terminal-container .xterm-screen{touch-action:none}.response-viewer{padding-bottom:var(--safe-area-bottom, 0px);max-height:88vh;max-height:92dvh}.response-viewer-body{font-size:14.5px;line-height:1.65;padding:16px 16px 24px;--rv-content-max: 100%}.response-viewer-body .rv-text pre,.response-viewer-body pre{padding:12px 14px;margin-left:-4px;margin-right:-4px;border-radius:6px}.response-viewer-body .rv-text pre code,.response-viewer-body pre code{font-size:11.5px;line-height:1.5}.response-viewer-body .rv-text h1,.response-viewer-body>h1{font-size:1.35em}.response-viewer-body .rv-text h2,.response-viewer-body>h2{font-size:1.2em}.response-viewer-body .rv-text h3,.response-viewer-body>h3{font-size:1.08em}.welcome-content{max-width:calc(100vw - 1.5rem);padding:1rem .75rem}.welcome-title{font-size:1.2rem;margin-bottom:.5rem}.welcome-desc{font-size:.8rem;margin-bottom:.4rem}.welcome-actions{margin-top:1rem}.welcome-primary{width:100%;justify-content:center;min-height:44px;font-size:.9rem}.welcome-chip{height:40px;border-radius:20px}.history-show-more{display:block;margin-bottom:.75rem}.welcome-ralph-link{display:block;margin:.75rem auto 0}.welcome-hint{font-size:.7rem;margin-top:.75rem}.modal-wizard{display:flex;flex-direction:column}.wizard-progress{padding:.5rem}.wizard-step{padding:.3rem}.wizard-step-number{width:24px;height:24px;font-size:.7rem}.wizard-step-label{display:none}.timer-banner{padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right))}.respawn-banner{padding:.3rem .5rem;padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right));font-size:.65rem}.respawn-compact-layout{flex-direction:column;gap:.15rem}.respawn-status-col{flex-shrink:1;min-width:0;gap:.1rem}.respawn-status-row1{flex-wrap:wrap;gap:.25rem;row-gap:.1rem}.respawn-state{font-size:.6rem;padding:.05rem .3rem}.respawn-banner .detection-confidence{font-size:.5rem;padding:.02rem .2rem}.respawn-cycles{font-size:.55rem}.respawn-timer{font-size:.55rem;padding:0 .25rem}.respawn-tokens{font-size:.55rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:120px}.respawn-indicator{font-size:.65rem}.respawn-banner .btn-icon-only{min-width:36px;min-height:36px;font-size:1rem;display:flex;align-items:center;justify-content:center;margin-left:auto;border-radius:6px;flex-shrink:0}.respawn-status-row2{font-size:.55rem;gap:.3rem;min-height:0;flex-wrap:wrap}.respawn-banner .detection-hook,.respawn-banner .detection-ai-check,.respawn-banner .detection-status{font-size:.55rem;padding:.02rem .2rem}.respawn-countdown-timers{gap:.2rem}.respawn-countdown-timer{font-size:.5rem;padding:.02rem .2rem;gap:.15rem}.respawn-countdown-timer .respawn-timer-bar{display:none}.respawn-action-log{border-left:none;border-top:1px solid rgba(34,197,94,.15);padding-left:0;padding-top:.15rem;max-height:1.4em;font-size:.55rem;overflow:hidden}.respawn-header{flex-direction:row;gap:.4rem;align-items:center}.respawn-header .respawn-actions{display:flex;gap:.3rem;flex-shrink:0}.respawn-header .respawn-actions .btn-toolbar{min-height:28px!important;font-size:.7rem!important;padding:.2rem .5rem!important;border-radius:5px}.duration-presets{display:flex;flex-wrap:wrap;gap:.2rem}.duration-preset-btn{min-height:24px;padding:.1rem .4rem;font-size:.6rem;border-radius:4px;text-align:center}.duration-custom{display:flex;gap:.2rem;align-items:center}.duration-custom-input.visible{flex:0 1 auto}.duration-custom-input input{width:64px;min-height:24px;font-size:16px;padding:.1rem .3rem}.preset-selector{display:grid;grid-template-columns:1fr 1fr;gap:.25rem}.preset-selector select{grid-column:1 / -1;min-height:32px;font-size:16px;border-radius:5px;padding:.2rem .4rem}.preset-selector .btn{min-height:32px;font-size:.65rem;border-radius:5px;padding:.2rem .4rem}#sessionOptionsModal textarea{font-size:16px;min-height:32px!important;max-height:56px;height:auto!important;border-radius:6px;padding:.3rem .5rem}#modalRespawnPrompt{min-height:32px!important;max-height:56px}#modalRespawnKickstart{min-height:32px!important;max-height:48px}#sessionOptionsModal .checkbox-inline{min-height:30px;font-size:.75rem;padding:.15rem 0;gap:.4rem}#sessionOptionsModal .checkbox-inline input[type=checkbox]{width:18px;height:18px}#sessionOptionsModal .respawn-loop-title{font-size:.75rem}#sessionOptionsModal .respawn-loop-box .checkbox-inline{font-size:.65rem}#sessionOptionsModal .respawn-options-row{gap:.5rem}#sessionOptionsModal .form-section-header{margin-top:.75rem;padding-top:.5rem;font-size:.65rem}#sessionOptionsModal .form-row{margin-bottom:.5rem}#sessionOptionsModal .form-row label{font-size:.65rem;margin-bottom:.2rem}#sessionOptionsModal .form-hint{font-size:.6rem;margin-top:.2rem}.context-setting{padding:.625rem}.context-setting-header{flex-wrap:wrap;gap:.4rem}.context-setting-header .input-suffix-sm input{width:60px;font-size:16px;min-height:36px}.context-setting input[type=text]{font-size:16px;min-height:36px;padding:.4rem .6rem;border-radius:6px}.color-picker{gap:8px}.color-swatch{width:36px;height:36px;border-radius:6px}.form-row-switch{min-height:40px;gap:.4rem}.context-settings-grid input[type=number]{font-size:16px;min-height:36px}.ralph-limits-grid{grid-template-columns:1fr 1fr;gap:.5rem}.ralph-limits-grid .form-col input[type=number]{font-size:16px;min-height:36px;padding:.4rem .5rem;border-radius:6px}#modalRalphPhrase{font-size:16px;min-height:40px;border-radius:6px}.ralph-config-actions{margin-top:1rem}.ralph-config-actions .btn-toolbar{width:100%;min-height:44px;font-size:.85rem;border-radius:8px}.run-summary-filters{gap:.3rem;margin-bottom:.5rem}.filter-btn{padding:.35rem .75rem;font-size:.7rem;min-height:32px}.timeline-event{padding:.4rem .5rem;margin-bottom:.25rem;font-size:.7rem}.run-summary-footer{flex-direction:column;gap:.4rem;padding:.5rem 0}.run-summary-actions{flex-wrap:wrap;gap:.3rem}.run-summary-actions .btn-toolbar{flex:1;min-height:36px;font-size:.7rem;white-space:nowrap}.auto-refresh-label{font-size:.7rem}.ralph-panel{font-size:.75rem}.ralph-summary{padding:.4rem .5rem;padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right))}.project-insights-panel{max-width:100%;font-size:.65rem;bottom:calc(44px + 2rem + var(--safe-area-bottom))}.file-browser-panel{max-width:100%;max-height:50vh;bottom:calc(44px + 2rem + var(--safe-area-bottom))}.file-preview-window{width:100vw;max-width:100vw;height:var(--app-height, 100vh);max-height:var(--app-height, 100vh);border-radius:0;border-left:none;border-right:none}.file-preview-window,.file-preview-window.expanded{width:100vw!important;height:var(--app-height, 100vh)!important}#filePreviewExpandBtn,.file-preview-resize{display:none}.file-preview-editbar{padding-bottom:calc(.4rem + var(--safe-area-bottom))}.file-preview-overlay .file-preview-footer{padding-bottom:calc(.35rem + var(--safe-area-bottom))}.file-preview-body textarea.file-preview-editor{font-size:16px}.notification-drawer{width:100%;max-width:100%;right:0;border-radius:0;padding-left:var(--safe-area-left);padding-right:var(--safe-area-right);padding-bottom:var(--safe-area-bottom)}input,textarea,[contenteditable]{scroll-margin-bottom:200px;scroll-margin-top:80px}.keyboard-visible .modal-body{max-height:40vh;overflow-y:auto}.keyboard-visible #createCaseModal .modal-body{max-height:60vh}.mobile-case-picker .modal-backdrop{background:#00000080}.mobile-case-picker-sheet{max-height:80vh;max-height:80dvh;animation:slideUp .2s ease-out}@keyframes slideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}.mobile-case-picker-header .modal-close{width:32px;height:32px;font-size:1.5rem}.keyboard-visible .mobile-case-picker-sheet{max-height:45vh}.keyboard-visible .mobile-case-picker-body{max-height:28vh}.mobile-case-picker-footer{padding-bottom:calc(12px + var(--safe-area-bottom))}#createCaseModal .form-row{margin-bottom:1rem}#createCaseModal .form-row label{font-size:.8rem;margin-bottom:.4rem;font-weight:500;color:#e5e7eb}#createCaseModal .form-row input[type=text]{min-height:44px;font-size:16px;padding:.5rem .75rem;border-radius:8px}#createCaseModal .form-row .form-hint{font-size:.65rem;margin-top:.35rem;line-height:1.4}#createCaseModal .form-actions{padding:.75rem 1rem;padding-bottom:calc(.75rem + var(--safe-area-bottom));gap:.75rem}#createCaseModal .form-actions .btn-toolbar{min-height:44px!important;max-height:44px!important;height:44px!important;font-size:.85rem!important;font-weight:500;border-radius:8px}#caseModalSubmit.loading{opacity:.6;pointer-events:none}#createCaseModal.from-mobile .modal-content{animation:caseModalSlideUp .25s ease-out}@keyframes caseModalSlideUp{0%{transform:translateY(30px);opacity:0}to{transform:translateY(0);opacity:1}}.btn-case-create-mobile{min-height:48px!important;max-height:48px!important;height:48px!important;font-size:.85rem!important;font-weight:500;border-radius:10px}.settings-grid{grid-template-columns:1fr;gap:.35rem}.settings-grid-3col{grid-template-columns:1fr 1fr 1fr}.settings-item{padding:.35rem .5rem;font-size:.7rem}.settings-item-label{font-size:.7rem}.settings-section-header{font-size:.6rem;padding:.35rem 0 .2rem;margin-top:.5rem}.form-row{margin-bottom:.5rem}.form-row label{font-size:.7rem;margin-bottom:.2rem}.form-row .form-hint{font-size:.6rem}.form-row input[type=text],.form-row input[type=number],.form-row textarea,.form-row .form-select,.form-row select{font-size:.75rem;padding:.35rem .5rem;min-height:32px}.form-row-switch{gap:.3rem}.form-row-switch>label:first-child{font-size:.7rem}.form-section-header{font-size:.6rem;margin-top:.75rem}.event-type-grid{grid-template-columns:1fr 36px 36px 36px;gap:4px 4px;padding:6px;margin-top:6px}.event-header{font-size:.55rem}.event-label{font-size:.65rem}.event-type-grid input[type=checkbox]{width:12px;height:12px}.form-actions{gap:.5rem}.form-actions .btn-toolbar{flex:1;min-height:36px!important;max-height:36px!important;height:36px!important;font-size:.75rem!important}.subagent-window{position:fixed;width:calc(100% - 8px);max-width:calc(100% - 8px);height:110px;min-height:80px;max-height:110px;min-width:200px;border-radius:6px;resize:none;box-shadow:0 2px 8px #0006}.subagent-window:after{display:none}.subagent-window-header{padding:.2rem .4rem;min-height:24px}.subagent-window-title{gap:.2rem;overflow:hidden}.subagent-window-title .icon{font-size:.7rem}.subagent-window-title .id{font-size:.6rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:45vw}.subagent-window-title .status{font-size:.45rem;padding:.05rem .15rem}.subagent-model-badge{font-size:.45rem!important;padding:.05rem .15rem!important}.subagent-window-actions button{font-size:.7rem;padding:.15rem .35rem;min-width:26px;min-height:26px;display:flex;align-items:center;justify-content:center}.subagent-window-body{font-size:.6rem;padding:.2rem .35rem}.subagent-window-body .activity-line{gap:.15rem;padding:.05rem 0}.subagent-window-body .activity-line .time{font-size:.5rem}.subagent-window-body .activity-line .tool-name,.subagent-window-body .activity-line .tool-detail{font-size:.55rem}.subagent-window-parent{display:none}.session-tab .tab-subagent-badge{height:14px;padding:0 3px;border-radius:7px;margin-left:2px}.session-tab .tab-subagent-badge .subagent-label{font-size:.45rem}.subagent-dropdown{position:fixed!important;left:8px!important;right:8px!important;bottom:auto!important;min-width:auto!important;max-width:none!important;border-radius:8px;transform:none!important}.mobile-overview.visible{position:absolute;inset:0;z-index:10;display:flex;flex-direction:column;gap:.75rem;padding:.75rem .6rem calc(1rem + var(--safe-area-bottom));background:var(--bg-dark);overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}.mobile-overview-top{display:flex;align-items:center;justify-content:space-between;gap:.5rem;padding:0}.mobile-overview-brand{display:inline-flex;align-items:center;min-height:48px;font-size:1.5rem;font-weight:800;line-height:1;color:var(--accent-hover);letter-spacing:-.02em}.mobile-overview-header{position:relative;display:flex;flex-direction:column}.mobile-overview-run-group{display:flex;align-items:stretch;flex-shrink:0}.mobile-overview-run-group .mobile-overview-run{display:inline-flex;align-items:center;gap:.4rem;min-height:48px!important;height:48px!important;max-height:48px!important;padding:0 1.15rem!important;font-size:.95rem!important;line-height:1;font-weight:700;font-family:inherit;border-radius:10px 0 0 10px!important}.mobile-overview-run-mode{font-weight:600;font-size:.85rem;opacity:.8}.mobile-overview-run-group .mobile-overview-run-caret{display:inline-flex;align-items:center;justify-content:center;min-height:48px!important;height:48px!important;max-height:48px!important;min-width:48px!important;width:48px!important;padding:0!important;line-height:1;font-family:inherit;border-radius:0 10px 10px 0!important}.mobile-overview-run-group .mobile-overview-run-caret svg{display:block;width:20px!important;height:20px!important;margin:0!important}.mobile-overview-run-menu{display:flex;flex-direction:column;gap:.15rem;margin:.5rem 0 0;padding:.35rem;border:1px solid var(--border);border-radius:12px;background:var(--floating-bg);box-shadow:var(--elevated-shadow)}.mobile-overview-run-option{display:flex;align-items:center;gap:.5rem;min-height:44px;padding:0 .6rem;border:none;border-radius:8px;background:transparent;color:var(--text);font-family:inherit;font-size:.82rem;text-align:left}.mobile-overview-run-option.selected{background:var(--control-bg-hover)}.mobile-overview-run-option:active{background:var(--bg-hover)}.mobile-overview-run-option--add{color:var(--accent)}.mobile-overview-run-header{padding:.4rem .6rem .2rem;font-size:.6rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--text-muted)}.mobile-overview-section{display:flex;flex-direction:column;gap:.4rem}.mobile-overview-heading{display:flex;align-items:center;gap:.35rem;margin:.35rem 0 0;padding:0;font-size:.65rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--text-muted)}.mobile-overview-heading-count{color:var(--text-dim);font-weight:600}.mobile-overview-empty{margin:0;padding:.5rem 0;font-size:.75rem;color:var(--text-muted)}.mobile-overview-row{display:flex;align-items:center;gap:.6rem;width:100%;min-height:56px;padding:.5rem .7rem;border:1px solid var(--border);border-radius:12px;background:var(--bg-card);color:var(--text);font-family:inherit;text-align:left}.mobile-overview-row:active{background:var(--bg-hover)}.mobile-overview-row-wrap{width:100%}.mobile-overview-approval-strip{display:flex;flex-wrap:wrap;gap:.4rem;padding:.4rem .2rem .1rem}.mobile-overview-approval-btn{border:1px solid var(--border);border-radius:8px;background:var(--bg-card);color:var(--text);font-family:inherit;font-size:.72rem;padding:.35rem .6rem;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mobile-overview-approval-btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}.mobile-overview-approval-btn.danger{border-color:var(--error);color:var(--error)}.mobile-overview-row--needs{border-color:var(--red);animation:mobile-overview-blink-red 2.5s ease-in-out infinite}.mobile-overview-row--waiting{border-color:var(--yellow);animation:mobile-overview-blink-yellow 3.5s ease-in-out infinite}.mobile-overview-row--error{border-color:var(--red)}.mobile-overview-row--working{border-color:var(--green);animation:mobile-overview-breathe-green 2.2s ease-in-out infinite}@keyframes mobile-overview-breathe-green{0%,to{background:var(--bg-card);border-color:var(--border)}50%{background:#22c55e1a;border-color:var(--green)}}.mobile-overview-pill--working:after{content:"";display:inline-block;width:.75em;text-align:left;animation:mobile-overview-pill-dots 1.5s steps(1,end) infinite}@keyframes mobile-overview-pill-dots{0%{content:""}25%{content:"."}50%{content:".."}75%{content:"..."}}@keyframes mobile-overview-blink-red{0%,to{background:var(--bg-card);border-color:var(--border)}50%{background:#ef444424;border-color:var(--red)}}@keyframes mobile-overview-blink-yellow{0%,to{background:var(--bg-card);border-color:var(--border)}50%{background:#eab3081f;border-color:var(--yellow)}}.mobile-overview-row-body{display:flex;flex-direction:column;gap:.15rem;flex:1;min-width:0}.mobile-overview-row-title{display:block;font-size:.9rem;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-overview-row-case{color:var(--text-dim);font-weight:500}.mobile-overview-row-sub{display:block;font-size:.68rem;color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-overview-row-meta{display:flex;align-items:center;gap:.3rem;min-width:0;font-family:var(--font-mono, monospace);font-size:.63rem;color:var(--text-muted);white-space:nowrap;overflow:hidden}.mobile-overview-meta-item{min-width:0;overflow:hidden;text-overflow:ellipsis}.mobile-overview-meta-key{margin-right:.3rem;opacity:.6;text-transform:uppercase;letter-spacing:.05em}.mobile-overview-meta-sep{opacity:.45}.mobile-overview-row--working .mobile-overview-meta-since{color:var(--green);opacity:.95}.mobile-overview-dot{flex-shrink:0;width:9px;height:9px;border-radius:50%;background:var(--text-muted)}.mobile-overview-dot--needs,.mobile-overview-dot--error{background:var(--red)}.mobile-overview-dot--waiting{background:var(--yellow)}.mobile-overview-dot--working{background:var(--green);animation:pulse 1.5s infinite;box-shadow:0 0 8px 2px color-mix(in srgb,var(--green) 55%,transparent);will-change:opacity}.mobile-overview-dot{position:relative}.mobile-overview-dot--working:after{content:"";position:absolute;inset:-4px;border:2px solid rgba(34,197,94,.25);border-top-color:var(--green);border-radius:50%;animation:tab-load-spin .7s linear infinite}.mobile-overview-dot--idle{background:var(--green)}.mobile-overview-dot--done{background:var(--text-muted);opacity:.5}.mobile-overview-pill{flex-shrink:0;display:inline-flex;align-items:center;gap:.25rem;padding:.2rem .45rem;border:1px solid var(--border-light);border-radius:999px;font-size:.62rem;font-weight:600;color:var(--text-dim);white-space:nowrap}.mobile-overview-pill--needs,.mobile-overview-pill--error{border-color:var(--red);color:var(--red)}.mobile-overview-pill--waiting{border-color:var(--yellow);color:var(--yellow)}.mobile-overview-pill--idle,.mobile-overview-pill--working{border-color:var(--green);color:var(--green)}.mobile-overview-pill--exited{border-color:var(--text-muted);color:var(--text-muted)}.mobile-overview-pill--watching{border-color:var(--accent);color:var(--accent)}.mobile-overview-chevron{flex-shrink:0;color:var(--text-muted);font-size:1rem;line-height:1}.mobile-overview-row--past{background:transparent;border-style:dashed}.mobile-overview-row--past .mobile-overview-row-title{font-weight:500;color:var(--text-dim)}.mobile-overview-dot--past{background:transparent;border:1px solid var(--border-light)}.mobile-overview-pill--past{border-color:var(--border-light);color:var(--text-muted)}.mobile-overview-more{display:flex;align-items:center;justify-content:center;gap:.35rem;min-height:40px;border:none;border-radius:10px;background:var(--control-bg);color:var(--text-dim);font-family:inherit;font-size:.72rem;font-weight:600}.mobile-overview-more-count{padding:.05rem .35rem;border-radius:999px;background:var(--control-bg-hover);color:var(--text-muted)}}@media(prefers-reduced-motion:reduce){.mobile-overview-row--needs,.mobile-overview-row--waiting{animation:none}.mobile-overview-row--needs{background:#ef444424}.mobile-overview-row--waiting{background:#eab3081f}.mobile-overview-dot--working{animation:none}.mobile-overview-dot--working:after{border-color:var(--green);animation:none}.mobile-overview-row--working{animation:none}.mobile-overview-pill--working:after{content:"...";animation:none}}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.header,.toolbar,.keyboard-accessory-bar){background:var(--glass-bg);border-color:var(--glass-border);color:var(--text)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-voice-mobile,.btn-attach-mobile,.btn-settings-mobile,.btn-toolbar.btn-shell,.accessory-btn:not(.armed)){background:var(--control-bg);border-color:var(--control-border);color:var(--text-dim)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-voice-mobile:active,.btn-attach-mobile:active,.btn-settings-mobile:active,.btn-toolbar.btn-shell:hover,.btn-toolbar.btn-shell:active,.accessory-btn:active){background:var(--control-bg-hover);border-color:var(--control-border-hover);color:var(--text)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) .btn-attach-mobile-wrap:active .btn-attach-mobile{background:var(--control-bg-hover);border-color:var(--control-border-hover);color:var(--text)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-toolbar.btn-run.mode-claude,.btn-toolbar.btn-run-gear.mode-claude){background:linear-gradient(135deg,var(--accent-grad-a),var(--accent-grad-b));border-color:var(--accent);color:var(--accent-ink)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-toolbar.btn-run.mode-opencode,.btn-toolbar.btn-run-gear.mode-opencode){background:linear-gradient(135deg,var(--accent-d),var(--accent-grad-b));border-color:var(--accent);color:var(--accent-ink)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-toolbar.btn-run.mode-gemini,.btn-toolbar.btn-run-gear.mode-gemini){background:linear-gradient(135deg,#174ea6,#4f46e5);border-color:#315fc3;color:#fff}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-toolbar.btn-run.mode-antigravity,.btn-toolbar.btn-run-gear.mode-antigravity){background:linear-gradient(135deg,#0e7490,#0891b2);border-color:#155e75;color:#fff}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-toolbar.btn-run.mode-pi,.btn-toolbar.btn-run-gear.mode-pi){background:linear-gradient(135deg,#be185d,#db2777);border-color:#9d174d;color:#fff}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-toolbar.btn-run.mode-omp,.btn-toolbar.btn-run-gear.mode-omp){background:linear-gradient(135deg,#4f46e5,#6366f1);border-color:#4338ca;color:#fff}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-toolbar.btn-run.mode-copilot,.btn-toolbar.btn-run-gear.mode-copilot){background:linear-gradient(135deg,#6d28d9,#8b5cf6);border-color:#5b21b6;color:#fff}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-toolbar.btn-run.mode-grok,.btn-toolbar.btn-run-gear.mode-grok){background:linear-gradient(135deg,#27272a,#52525b);border-color:#18181b;color:#fff}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.btn-toolbar.btn-run.mode-deepseek,.btn-toolbar.btn-run-gear.mode-deepseek){background:linear-gradient(135deg,#2740c4,#4d6bfe);border-color:#1b2a8f;color:#fff}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) .btn-toolbar.btn-run-gear{border-left-color:var(--control-border-hover)!important}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.case-settings-popover-mobile,.mobile-case-picker-sheet){background:var(--floating-bg);border-color:var(--control-border);color:var(--text);box-shadow:var(--elevated-shadow)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) :is(.case-settings-popover-mobile .checkbox-inline,#createCaseModal .form-row label){color:var(--text)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) .case-settings-popover-mobile .form-hint{color:var(--text-muted)}html:is([data-skin=paper-gray],[data-skin=solarized-light],[data-skin=catppuccin-latte],[data-skin=rose-pine-dawn]) .mobile-case-picker .modal-backdrop{background:var(--modal-backdrop)}.ios-device.safari-browser{overscroll-behavior:none}@media(hover:none)and (pointer:coarse){.session-tab .tab-close,.session-tab .tab-gear{opacity:1;width:auto;padding:.15rem .25rem;align-items:center;justify-content:center}.btn-toolbar:hover,.btn-icon-header:hover{transform:none}.subagent-dropdown-trigger:active+.subagent-dropdown-menu,.subagent-dropdown-trigger:focus+.subagent-dropdown-menu{display:block}}@media(max-width:599px){.attachment-history-drawer{top:0;bottom:0;width:100%;max-width:100%;height:100vh;height:100dvh;border-left:none;border-radius:0;padding-top:var(--safe-area-top);padding-left:var(--safe-area-left);padding-right:var(--safe-area-right);padding-bottom:var(--safe-area-bottom)}.attachment-history-header{padding:12px}.attachment-history-list{padding:6px}.attachment-history-item{grid-template-columns:104px minmax(0,1fr);gap:8px;padding:8px 6px}.attachment-history-thumb{width:104px}.attachment-history-actions{gap:4px}.attachment-history-actions button{padding:4px 7px}}@media(max-width:599px){.reboot-restore-banner{padding:.4rem .5rem;padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right));font-size:.7rem;gap:.4rem}.reboot-restore-banner-detail,.reboot-restore-banner-note{display:none}.reboot-restore-banner-text{min-width:0;overflow:hidden;text-overflow:ellipsis}.reboot-restore-banner-accept,.reboot-restore-banner-dismiss{padding:.25rem .5rem}.reboot-restore-banner-accept{margin-left:auto}.offline-banner{padding:.4rem .5rem;padding-left:calc(.5rem + var(--safe-area-left));padding-right:calc(.5rem + var(--safe-area-right));font-size:.7rem;gap:.4rem}.offline-banner-detail{display:none}.offline-banner-retry{padding:.25rem .5rem;margin-left:auto}.offline-overlay-card{padding:22px 18px 18px}.offline-overlay-title{font-size:1.05rem}.offline-overlay-actions{flex-direction:column}.offline-overlay-btn{width:100%;padding:.65rem 1rem}}@media(max-width:860px){:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .modal-content.modal-lg{width:100%;max-width:100%;height:100%;max-height:100%}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-body{display:flex;flex-direction:column;min-height:0}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-rail{flex-direction:row;align-items:center;border-right:0;border-bottom:1px solid var(--border);background:transparent;padding:10px 14px;overflow:visible;flex-shrink:0}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-rail-items,:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-rail-foot{display:none}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-search{margin:0;flex:1}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-search input{padding:9px 10px 9px 30px;border-radius:10px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-head-actions:has(.set-head-save){padding:3px;border:1px solid var(--border);border-radius:12px;background:var(--bg-input)}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-head-save{display:inline-flex;height:36px;padding:0 16px;font-size:.86rem}#createCaseModal .set-head-save.loading{opacity:.6;pointer-events:none}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-head-actions .modal-close{width:36px;height:36px;font-size:1.35rem}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-foot{display:none}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-doc{padding:0 14px 34px;flex:1}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-jump{display:flex;position:sticky;top:0;z-index:4;align-items:center;gap:8px;width:100%;margin:10px 0 2px;padding:10px 12px;border-radius:11px;font:inherit;font-size:.82rem;color:var(--text);background:rgba(var(--accent-rgb),.13);border:1px solid rgba(var(--accent-rgb),.3);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);cursor:pointer}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-jump-ico{color:var(--accent);flex-shrink:0}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-jump-label{font-weight:580;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-jump-chev{margin-left:auto;color:var(--text-muted);flex-shrink:0;transition:transform .18s}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-jump[aria-expanded=true] .set-jump-chev{transform:rotate(180deg)}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-jump-veil{display:none;position:fixed;inset:0;z-index:8;background:#04080d9e}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-jump-menu{display:none;position:absolute;left:14px;right:14px;z-index:9;padding:7px;border-radius:16px;background:var(--bg-card);border:1px solid var(--control-border);box-shadow:var(--elevated-shadow);max-height:70vh;overflow-y:auto}#appSettingsModal.jump-open .set-jump-veil,#appSettingsModal.jump-open .set-jump-menu{display:block}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-jump-row{display:flex;align-items:center;gap:11px;width:100%;padding:11px 12px;border:0;border-radius:11px;background:transparent;color:var(--text-dim);font:inherit;font-size:.82rem;text-align:left}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-jump-row svg{color:var(--text-muted);flex-shrink:0}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-jump-row .set-jump-count{margin-left:auto;font-size:.62rem;color:var(--text-muted)}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-jump-row.active{background:rgba(var(--accent-rgb),.14);color:var(--text);font-weight:570}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-jump-row.active svg{color:var(--accent)}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-section{padding-top:0}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-section+.set-section{border-top:0;margin-top:0}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-section-head{gap:7px;margin:18px 0 2px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-section-head svg{padding:0;border:0;background:none;color:var(--text-muted);width:12px;height:12px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-section-head h2{font-size:.6rem;font-weight:640;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted)}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-section-head:after{content:"";flex:1;height:1px;background:linear-gradient(90deg,var(--border),transparent)}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-section-blurb{display:none}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-preview{margin-bottom:12px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-preview-stage{min-height:62px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-group{margin-top:14px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-group+.set-group{margin-top:16px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-group-head{margin-bottom:7px;padding:0 3px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-group-hint{padding:0 3px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-group-body{gap:0;background:#ffffff09;border:1px solid rgba(255,255,255,.06);border-radius:13px;overflow:hidden}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-group-body>.set-row{background:transparent;border:0;border-radius:0;padding:12px 13px;gap:12px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-group-body>.set-row+.set-row{border-top:1px solid rgba(255,255,255,.055)}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-group-body>.set-chips,:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-group-body>.set-modelgrid,:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-group-body>.set-minigrid,:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-group-body>#appSettingsShortcutsList{padding:12px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-group-body>.event-type-grid{padding:12px;margin:0}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-row-label{font-size:.84rem}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-row-desc{font-size:.69rem;max-width:none}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-row.has-field{flex-direction:column;align-items:stretch;gap:9px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-row.has-field .set-select,:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-row.has-field .set-input{width:100%;min-width:0;max-width:none;box-sizing:border-box}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-row-actions-wide{width:100%}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-row-actions-wide .set-input{flex:1;min-width:0}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-num{width:76px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .switch-sm{width:40px;height:24px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .switch-sm .slider:before{height:18px;width:18px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .switch-sm input:checked+.slider:before{transform:translate(16px)}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-chip{font-size:.78rem;padding:9px 14px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-modelgrid{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-minigrid{grid-template-columns:1fr}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-mini .set-select{width:148px}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-segment{overflow-x:auto;scrollbar-width:none}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-segment::-webkit-scrollbar{display:none}:is(#appSettingsModal,#sessionOptionsModal,#createCaseModal) .set-segment button{flex:0 0 auto;padding:8px 12px}}@media(max-width:860px){:is(#sessionOptionsModal,#createCaseModal) .set-rail{padding:8px 10px}:is(#sessionOptionsModal,#createCaseModal) .set-rail-items{display:flex;flex-direction:row;flex:1;min-width:0;gap:4px;overflow-x:auto;scrollbar-width:none}:is(#sessionOptionsModal,#createCaseModal) .set-rail-items::-webkit-scrollbar{display:none}:is(#sessionOptionsModal,#createCaseModal) .set-rail-item{white-space:nowrap;padding:8px 12px}:is(#sessionOptionsModal,#createCaseModal) .set-rail-item.active:before{display:none}:is(#sessionOptionsModal,#createCaseModal) .set-rail-item.active{background:rgba(var(--accent-rgb),.13)}}html[data-session-list=sidebar] .session-sidebar{position:absolute;top:0;bottom:0;left:0;width:min(280px,80vw);flex:0 0 auto;transform:translate(-100%);visibility:hidden;transition:transform var(--sidebar-transition),visibility var(--sidebar-transition);box-shadow:10px 0 28px #0000005c;z-index:12;padding-left:var(--safe-area-left)}html[data-session-list=sidebar][data-sidebar-detail=rich] .session-sidebar{width:min(280px,80vw);flex:0 0 auto}html[data-session-list=sidebar] .session-sidebar.open{transform:translate(0);visibility:visible}html[data-session-list=sidebar][data-sidebar=collapsed] .session-sidebar{flex-basis:auto;width:min(280px,80vw)}html[data-session-list=sidebar][data-sidebar=collapsed] .session-sidebar-head,html[data-session-list=sidebar][data-sidebar=collapsed] .session-sidebar-filter{display:flex}html[data-session-list=sidebar][data-sidebar=collapsed] .session-sidebar .session-tab{justify-content:flex-start;flex-wrap:nowrap;padding:.4rem .5rem}html[data-session-list=sidebar][data-sidebar=collapsed] .session-sidebar .tab-info{display:flex}html[data-session-list=sidebar][data-sidebar=collapsed] .session-sidebar .tab-number{display:inline-flex}html[data-session-list=sidebar][data-sidebar=collapsed] .session-sidebar .tab-subagent-badge{margin-left:4px}html[data-session-list=sidebar] .session-sidebar .session-tab{min-height:44px;max-height:none;flex-shrink:0}html[data-session-list=sidebar] .session-sidebar .session-tab .tab-gear,html[data-session-list=sidebar] .session-sidebar .session-tab .tab-close{display:inline-flex;align-items:center;justify-content:center;opacity:1;width:auto;min-width:28px;height:auto;margin-left:0;padding:.15rem .25rem}@media(prefers-reduced-motion:reduce){html[data-session-list=sidebar] .session-sidebar{transition:none}}@media(vertical-viewport-segments:2){.response-viewer{max-height:min(88vh,env(viewport-segment-height 0 1,88vh))}}@media(max-width:700px){.spreadsheet-sheet-tabs{padding-inline:4px;scroll-snap-type:x proximity}.spreadsheet-sheet-tab{min-width:96px;min-height:40px;scroll-snap-align:start}.spreadsheet-grid{min-height:55vh;-webkit-overflow-scrolling:touch;touch-action:pan-x pan-y}}
@@ -1,12 +1,18 @@
1
- "use strict";const AWAY_DIGEST_LAST_VIEWED_KEY="codeman-away-digest-last-viewed",FILE_BROWSER_SHOW_HIDDEN_KEY="codeman:fileBrowserShowHidden",TEXT_PREVIEW_MAX_BYTES=524288,TEXT_PREVIEW_MAX_LINES=500,MARKDOWN_PREVIEW_MAX_LINES=1e4,MARKDOWN_EXTS=new Set(["md","markdown"]),FILE_PREVIEW_PREF_KEYS={mdRendered:"codeman:filePreviewMdRendered",htmlRendered:"codeman:filePreviewHtmlRendered",lineNumbers:"codeman:filePreviewLineNumbers",wrap:"codeman:filePreviewWrap"},FILE_PREVIEW_PREF_DEFAULTS={mdRendered:!0,htmlRendered:!0,lineNumbers:!1,wrap:!0},AWAY_DIGEST_SECTIONS=[["needsAttention","Needs Attention"],["completed","Completed"],["stillRunning","Still Running"],["idle","Idle"],["informational","Informational"]];Object.assign(CodemanApp.prototype,{_addActivityEntry(e,t,s=50){const n=this.subagentActivity.get(e)||[];n.push(t),n.length>s&&n.shift(),this.subagentActivity.set(e,n)},_onTaskCreated(e){this.renderSessionTabs(),e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onTaskCompleted(e){this.renderSessionTabs(),e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onTaskFailed(e){this.renderSessionTabs(),e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onTaskUpdated(e){e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onMuxCreated(e){this.muxSessions.push(e),this.renderMuxSessions()},_onMuxKilled(e){this.muxSessions=this.muxSessions.filter(t=>t.sessionId!==e.sessionId),this.renderMuxSessions()},_onMuxDied(e){this.muxSessions=this.muxSessions.filter(t=>t.sessionId!==e.sessionId),this.renderMuxSessions(),this.showToast("Mux session died: "+this.getShortId(e.sessionId),"warning")},_onMuxStatsUpdated(e){this.muxSessions=e,document.getElementById("monitorPanel").classList.contains("open")&&this.renderMuxSessions()},_onRemoteSessionReconnected(e){const t=this.getShortId(e.sessionId);this.showToast(`Remote session ${t} reconnected`,"success"),this.activeSessionId===e.sessionId&&this._pollHostReachability?.(!0)},_onRemoteReconnectExhausted(e){const t=e.sessionId,s=this.getShortId(t);this.showToast(`Remote session ${s} dropped \u2014 auto-reconnect gave up`,"error",{duration:15e3,action:{label:"Reconnect",onClick:()=>{this.sessions&&this.sessions.has(t)?this.selectSession(t,{forceReload:!0}):this.showToast("Session no longer available","warning")}}})},_onBashToolStart(e){this.handleBashToolStart(e.sessionId,e.tool)},_onBashToolEnd(e){this.handleBashToolEnd(e.sessionId,e.tool)},_onBashToolsUpdate(e){this.handleBashToolsUpdate(e.sessionId,e.tools)},_onSubagentDiscovered(e){this.subagents.set(e.agentId,e),this.subagentActivity.set(e.agentId,[]),this.subagentToolResults.delete(e.agentId),this.subagentWindows.has(e.agentId)&&this.forceCloseSubagentWindow(e.agentId),this.renderSubagentPanel(),this.findParentSessionForSubagent(e.agentId),requestAnimationFrame(()=>{this.updateConnectionLines()});const t=this.subagentParentMap.get(e.agentId);this._notifySession(t||e.sessionId,"info","subagent-spawn","Subagent Spawned",e.description||"New background agent started")},_onSubagentUpdated(e){const t=this.subagents.get(e.agentId);t?(Object.assign(t,e),this.subagents.set(e.agentId,t)):this.subagents.set(e.agentId,e),this.renderSubagentPanel(),this.subagentWindows.has(e.agentId)&&(this.renderSubagentWindowContent(e.agentId),this.updateSubagentWindowHeader(e.agentId))},_onSubagentToolCall(e){this._addActivityEntry(e.agentId,{type:"tool",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.renderSubagentPanel(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},_onSubagentProgress(e){this._addActivityEntry(e.agentId,{type:"progress",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},_onSubagentMessage(e){this._addActivityEntry(e.agentId,{type:"message",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},_onSubagentToolResult(e){this.subagentToolResults.has(e.agentId)||this.subagentToolResults.set(e.agentId,new Map);const t=this.subagentToolResults.get(e.agentId);if(t.set(e.toolUseId,e),t.size>50){const s=t.keys().next().value;t.delete(s)}this._addActivityEntry(e.agentId,{type:"tool_result",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},async _onSubagentCompleted(e){const t=this.subagents.get(e.agentId);if(t&&(t.status="completed",this.subagents.set(e.agentId,t)),this.renderSubagentPanel(),this.updateSubagentWindows(),this.subagentWindows.has(e.agentId)){const n=this.subagentWindows.get(e.agentId);n&&!n.minimized&&(await this.closeSubagentWindow(e.agentId),this.saveSubagentWindowStates())}const s=this.subagentParentMap.get(e.agentId);this._notifySession(s||t?.sessionId||e.sessionId,"info","subagent-complete","Subagent Completed",t?.description||e.description||"Background agent finished"),setTimeout(()=>{this.subagents.get(e.agentId)?.status==="completed"&&(this.subagentActivity.delete(e.agentId),this.subagentToolResults.delete(e.agentId))},300*1e3),setTimeout(()=>{this.subagents.get(e.agentId)?.status==="completed"&&!this.subagentWindows.has(e.agentId)&&(this.subagents.delete(e.agentId),this.subagentParentMap.delete(e.agentId))},1800*1e3)},_onImageDetected(e){console.log("[Image Detected]",e),this.openImagePopup(e)},shouldOpenCommandPaletteFromShortcut(e){if(!e||!e.ctrlKey&&!e.metaKey&&!e.altKey)return!1;const s=typeof this.getShortcutRegistry=="function"&&typeof this.matchesShortcutEvent=="function"?this.getShortcutRegistry().find(a=>a.id==="command-palette"):null;if(s){if(s.disabled||!this.matchesShortcutEvent(e,s))return!1}else if((e.key||"").toLowerCase()!=="k"&&e.code!=="KeyK"||e.shiftKey)return!1;const n=e.target;if(!n)return!0;const i=(n.tagName||"").toUpperCase(),o=typeof n.className=="string"?n.className:"";return n.classList?.contains?.("xterm-helper-textarea")||o.includes("xterm-helper-textarea")?!0:!(i==="INPUT"||i==="TEXTAREA"||i==="SELECT"||n.isContentEditable||typeof n.closest=="function"&&n.closest('[contenteditable="true"]'))},_rememberOverlayFocus(e){this[e]=typeof document<"u"&&document.activeElement||null},_restoreOverlayFocus(e,t){const s=this[e];this[e]=null;const n=typeof document<"u"?document.body:null,i=typeof document<"u"?document.activeElement:null;if(!(i&&i!==n&&t?.contains?.(i)===!1)){if(s&&s!==n&&s.isConnected!==!1&&typeof s.focus=="function"){s.focus();return}this.activeSessionId&&this._shouldFocusTerminalForTabSwitch?.()!==!1&&this.terminal?.focus?.()}},openCommandPalette(){const e=document.getElementById("commandPaletteModal"),t=document.getElementById("commandPaletteSearch");!e||!t||(this.commandPaletteActiveIndex=0,t.value="",e.classList.add("active"),this._wireCommandPalette(),this.renderCommandPalette(),this._rememberOverlayFocus("_commandPalettePrevFocus"),t.focus(),t.select?.())},closeCommandPalette(){const e=document.getElementById("commandPaletteModal");e?.classList?.contains("active")&&(e.classList.remove("active"),this._restoreOverlayFocus("_commandPalettePrevFocus",e))},_wireCommandPalette(){if(this._commandPaletteWired)return;this._commandPaletteWired=!0;const e=document.getElementById("commandPaletteModal"),t=document.getElementById("commandPaletteSearch"),s=document.getElementById("commandPaletteList");t?.addEventListener("input",()=>{this.commandPaletteActiveIndex=0,this.renderCommandPalette()}),t?.addEventListener("keydown",async n=>{if(n.key==="ArrowDown"){n.preventDefault(),this.moveCommandPaletteSelection(1);return}if(n.key==="ArrowUp"){n.preventDefault(),this.moveCommandPaletteSelection(-1);return}if(n.key==="Enter"){n.preventDefault(),n.stopPropagation(),await this.activateCommandPaletteItem();return}n.key==="Escape"&&(n.preventDefault(),this.closeCommandPalette())}),e?.addEventListener("keydown",n=>{n.key==="Escape"&&(n.preventDefault(),this.closeCommandPalette())}),s?.addEventListener?.("click",n=>{const i=n.target?.closest?.("[data-command-index]");i&&(this.commandPaletteActiveIndex=Number(i.dataset.commandIndex)||0,this.activateCommandPaletteItem())})},buildCommandPaletteItems(e=""){const t=e.trim().toLowerCase(),s=[...Array.isArray(this.sessionOrder)?this.sessionOrder:[],...Array.from(this.sessions?.keys?.()||[]).filter(o=>!this.sessionOrder?.includes?.(o))],n=new Set,i=[];for(const o of s){if(n.has(o))continue;n.add(o);const l=this.sessions?.get?.(o);if(!l)continue;const a=this.getSessionName?.(l)||l.name||l.title||o.slice(0,8),r=[l.workingDir,l.mode,l.status].filter(Boolean),c=[a,l.workingDir,l.mode,l.status,o].filter(Boolean).join(" ").toLowerCase();t&&!c.includes(t)||i.push({id:`session:${o}`,type:"session",sessionId:o,title:a,subtitle:r.join(" \xB7 ")})}return i.push(this._buildCommandPaletteNewSessionItem(e)),i.push({id:"browse-sessions",type:"browse-sessions",title:"Browse all sessions\u2026",subtitle:"Open Session Manager"}),i},_buildCommandPaletteNewSessionItem(e=""){const t=this.runMode||this._runMode||"claude",s={claude:"Claude",opencode:"OpenCode",codex:"Codex",gemini:"Gemini",antigravity:"Antigravity",pi:"Pi",grok:"Grok",deepseek:"DeepSeek",omp:"OMP",copilot:"Copilot"},n=this._findCommandPaletteCaseMatch(e)||document.getElementById("quickStartCase")?.value||"testcase";return{id:"new-session",type:"new-session",caseName:n,title:"New session",subtitle:`Run ${s[t]||t} in ${n}`}},_findCommandPaletteCaseMatch(e=""){const t=e.trim().toLowerCase();if(!t||!Array.isArray(this.cases))return null;const s=o=>{const l=String(o?.name||"").trim();if(!l)return 0;const a=[l,o?.path,o?.casePath,o?.workingDir,o?.remote?.path,o?.remote?.hostId].filter(Boolean).join(" ").toLowerCase(),r=l.toLowerCase();return r===t?100:r.startsWith(t)?90:r.includes(t)?80:a.includes(t)?60:0};let n=null,i=0;for(const o of this.cases){const l=s(o);l>i&&(n=o,i=l)}return n?.name||null},renderCommandPalette(){const e=document.getElementById("commandPaletteSearch"),t=document.getElementById("commandPaletteList");if(!t)return;const s=e?.value||"",n=this.buildCommandPaletteItems(s);this.commandPaletteItems=n,this.commandPaletteActiveIndex=Math.max(0,Math.min(this.commandPaletteActiveIndex||0,n.length-1)),t.innerHTML=n.map((i,o)=>{const l=o===this.commandPaletteActiveIndex?" active":"",a=i.type==="new-session"?"+":i.type==="browse-sessions"?"\u2261":"\u203A",r=i.type==="browse-sessions"?" command-palette-item--browse":"";return`
2
- <button class="command-palette-item${l}${r}" type="button" data-command-index="${o}">
1
+ "use strict";const AWAY_DIGEST_LAST_VIEWED_KEY="codeman-away-digest-last-viewed",FILE_BROWSER_SHOW_HIDDEN_KEY="codeman:fileBrowserShowHidden",TEXT_PREVIEW_MAX_BYTES=524288,TEXT_PREVIEW_MAX_LINES=500,MARKDOWN_PREVIEW_MAX_LINES=1e4,MARKDOWN_EXTS=new Set(["md","markdown"]),FILE_PREVIEW_PREF_KEYS={mdRendered:"codeman:filePreviewMdRendered",htmlRendered:"codeman:filePreviewHtmlRendered",lineNumbers:"codeman:filePreviewLineNumbers",wrap:"codeman:filePreviewWrap",expanded:"codeman:filePreviewExpanded"},FILE_PREVIEW_PREF_DEFAULTS={mdRendered:!0,htmlRendered:!0,lineNumbers:!1,wrap:!0,expanded:!1},FILE_PREVIEW_HISTORY_MAX=50,AWAY_DIGEST_SECTIONS=[["needsAttention","Needs Attention"],["completed","Completed"],["stillRunning","Still Running"],["idle","Idle"],["informational","Informational"]];Object.assign(CodemanApp.prototype,{_addActivityEntry(e,t,s=50){const n=this.subagentActivity.get(e)||[];n.push(t),n.length>s&&n.shift(),this.subagentActivity.set(e,n)},_onTaskCreated(e){this.renderSessionTabs(),e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onTaskCompleted(e){this.renderSessionTabs(),e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onTaskFailed(e){this.renderSessionTabs(),e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onTaskUpdated(e){e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onMuxCreated(e){this.muxSessions.push(e),this.renderMuxSessions()},_onMuxKilled(e){this.muxSessions=this.muxSessions.filter(t=>t.sessionId!==e.sessionId),this.renderMuxSessions()},_onMuxDied(e){this.muxSessions=this.muxSessions.filter(t=>t.sessionId!==e.sessionId),this.renderMuxSessions(),this.showToast("Mux session died: "+this.getShortId(e.sessionId),"warning")},_onMuxStatsUpdated(e){this.muxSessions=e,document.getElementById("monitorPanel").classList.contains("open")&&this.renderMuxSessions()},_onRemoteSessionReconnected(e){const t=this.getShortId(e.sessionId);this.showToast(`Remote session ${t} reconnected`,"success"),this.activeSessionId===e.sessionId&&this._pollHostReachability?.(!0)},_onRemoteReconnectExhausted(e){const t=e.sessionId,s=this.getShortId(t);this.showToast(`Remote session ${s} dropped \u2014 auto-reconnect gave up`,"error",{duration:15e3,action:{label:"Reconnect",onClick:()=>{this.sessions&&this.sessions.has(t)?this.selectSession(t,{forceReload:!0}):this.showToast("Session no longer available","warning")}}})},_onBashToolStart(e){this.handleBashToolStart(e.sessionId,e.tool)},_onBashToolEnd(e){this.handleBashToolEnd(e.sessionId,e.tool)},_onBashToolsUpdate(e){this.handleBashToolsUpdate(e.sessionId,e.tools)},_onSubagentDiscovered(e){this.subagents.set(e.agentId,e),this.subagentActivity.set(e.agentId,[]),this.subagentToolResults.delete(e.agentId),this.subagentWindows.has(e.agentId)&&this.forceCloseSubagentWindow(e.agentId),this.renderSubagentPanel(),this.findParentSessionForSubagent(e.agentId),requestAnimationFrame(()=>{this.updateConnectionLines()});const t=this.subagentParentMap.get(e.agentId);this._notifySession(t||e.sessionId,"info","subagent-spawn","Subagent Spawned",e.description||"New background agent started")},_onSubagentUpdated(e){const t=this.subagents.get(e.agentId);t?(Object.assign(t,e),this.subagents.set(e.agentId,t)):this.subagents.set(e.agentId,e),this.renderSubagentPanel(),this.subagentWindows.has(e.agentId)&&(this.renderSubagentWindowContent(e.agentId),this.updateSubagentWindowHeader(e.agentId))},_onSubagentToolCall(e){this._addActivityEntry(e.agentId,{type:"tool",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.renderSubagentPanel(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},_onSubagentProgress(e){this._addActivityEntry(e.agentId,{type:"progress",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},_onSubagentMessage(e){this._addActivityEntry(e.agentId,{type:"message",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},_onSubagentToolResult(e){this.subagentToolResults.has(e.agentId)||this.subagentToolResults.set(e.agentId,new Map);const t=this.subagentToolResults.get(e.agentId);if(t.set(e.toolUseId,e),t.size>50){const s=t.keys().next().value;t.delete(s)}this._addActivityEntry(e.agentId,{type:"tool_result",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},async _onSubagentCompleted(e){const t=this.subagents.get(e.agentId);if(t&&(t.status="completed",this.subagents.set(e.agentId,t)),this.renderSubagentPanel(),this.updateSubagentWindows(),this.subagentWindows.has(e.agentId)){const n=this.subagentWindows.get(e.agentId);n&&!n.minimized&&(await this.closeSubagentWindow(e.agentId),this.saveSubagentWindowStates())}const s=this.subagentParentMap.get(e.agentId);this._notifySession(s||t?.sessionId||e.sessionId,"info","subagent-complete","Subagent Completed",t?.description||e.description||"Background agent finished"),setTimeout(()=>{this.subagents.get(e.agentId)?.status==="completed"&&(this.subagentActivity.delete(e.agentId),this.subagentToolResults.delete(e.agentId))},300*1e3),setTimeout(()=>{this.subagents.get(e.agentId)?.status==="completed"&&!this.subagentWindows.has(e.agentId)&&(this.subagents.delete(e.agentId),this.subagentParentMap.delete(e.agentId))},1800*1e3)},_onImageDetected(e){console.log("[Image Detected]",e),this.openImagePopup(e)},shouldOpenCommandPaletteFromShortcut(e){if(!e||!e.ctrlKey&&!e.metaKey&&!e.altKey)return!1;const s=typeof this.getShortcutRegistry=="function"&&typeof this.matchesShortcutEvent=="function"?this.getShortcutRegistry().find(a=>a.id==="command-palette"):null;if(s){if(s.disabled||!this.matchesShortcutEvent(e,s))return!1}else if((e.key||"").toLowerCase()!=="k"&&e.code!=="KeyK"||e.shiftKey)return!1;const n=e.target;if(!n)return!0;const i=(n.tagName||"").toUpperCase(),o=typeof n.className=="string"?n.className:"";return n.classList?.contains?.("xterm-helper-textarea")||o.includes("xterm-helper-textarea")?!0:!(i==="INPUT"||i==="TEXTAREA"||i==="SELECT"||n.isContentEditable||typeof n.closest=="function"&&n.closest('[contenteditable="true"]'))},_rememberOverlayFocus(e){this[e]=typeof document<"u"&&document.activeElement||null},_restoreOverlayFocus(e,t){const s=this[e];this[e]=null;const n=typeof document<"u"?document.body:null,i=typeof document<"u"?document.activeElement:null;if(!(i&&i!==n&&t?.contains?.(i)===!1)){if(s&&s!==n&&s.isConnected!==!1&&typeof s.focus=="function"){s.focus();return}this.activeSessionId&&this._shouldFocusTerminalForTabSwitch?.()!==!1&&this.terminal?.focus?.()}},openCommandPalette(){const e=document.getElementById("commandPaletteModal"),t=document.getElementById("commandPaletteSearch");!e||!t||(this.commandPaletteActiveIndex=0,this._resetCommandPaletteAgent(),t.value="",e.classList.add("active"),this._wireCommandPalette(),this.renderCommandPalette(),this._rememberOverlayFocus("_commandPalettePrevFocus"),t.focus(),t.select?.())},closeCommandPalette(){const e=document.getElementById("commandPaletteModal");e?.classList?.contains("active")&&(e.classList.remove("active"),this._restoreOverlayFocus("_commandPalettePrevFocus",e))},_wireCommandPalette(){if(this._commandPaletteWired)return;this._commandPaletteWired=!0;const e=document.getElementById("commandPaletteModal"),t=document.getElementById("commandPaletteSearch"),s=document.getElementById("commandPaletteList");t?.addEventListener("input",()=>{this.commandPaletteActiveIndex=0,this.renderCommandPalette()}),t?.addEventListener("keydown",async n=>{if((n.key==="ArrowLeft"||n.key==="ArrowRight")&&this._commandPaletteArrowCyclesAgent(n)){n.preventDefault(),this._cycleCommandPaletteAgent(n.key==="ArrowRight"?1:-1);return}if(n.key==="ArrowDown"){n.preventDefault(),this.moveCommandPaletteSelection(1);return}if(n.key==="ArrowUp"){n.preventDefault(),this.moveCommandPaletteSelection(-1);return}if(n.key==="Enter"){n.preventDefault(),n.stopPropagation(),await this.activateCommandPaletteItem();return}n.key==="Escape"&&(n.preventDefault(),this.closeCommandPalette())}),e?.addEventListener("keydown",n=>{n.key==="Escape"&&(n.preventDefault(),this.closeCommandPalette())}),s?.addEventListener?.("mousedown",n=>{n.target?.closest?.("[data-palette-agent-cycle]")&&n.preventDefault?.()}),s?.addEventListener?.("click",n=>{const i=n.target?.closest?.("[data-palette-agent-cycle]");if(i){n.preventDefault?.(),n.stopPropagation?.(),this._cycleCommandPaletteAgent(i.dataset.paletteAgentCycle==="prev"?-1:1);return}const o=n.target?.closest?.("[data-command-index]");o&&(this.commandPaletteActiveIndex=Number(o.dataset.commandIndex)||0,this.activateCommandPaletteItem())})},buildCommandPaletteItems(e=""){const t=e.trim().toLowerCase(),s=[...Array.isArray(this.sessionOrder)?this.sessionOrder:[],...Array.from(this.sessions?.keys?.()||[]).filter(o=>!this.sessionOrder?.includes?.(o))],n=new Set,i=[];for(const o of s){if(n.has(o))continue;n.add(o);const l=this.sessions?.get?.(o);if(!l)continue;const a=this.getSessionName?.(l)||l.name||l.title||o.slice(0,8),r=[l.workingDir,l.mode,l.status].filter(Boolean),c=[a,l.workingDir,l.mode,l.status,o].filter(Boolean).join(" ").toLowerCase();t&&!c.includes(t)||i.push({id:`session:${o}`,type:"session",sessionId:o,title:a,subtitle:r.join(" \xB7 ")})}return i.push(this._buildCommandPaletteNewSessionItem(e)),i.push({id:"browse-sessions",type:"browse-sessions",title:"Browse all sessions\u2026",subtitle:"Open Session Manager"}),i},_buildCommandPaletteNewSessionItem(e=""){const t=this._commandPaletteCaseName(e),s=this._commandPaletteAgent(t),n=s?.id||this.runMode||this._runMode||"claude",i={claude:"Claude",opencode:"OpenCode",codex:"Codex",gemini:"Gemini",antigravity:"Antigravity",pi:"Pi",grok:"Grok",deepseek:"DeepSeek",omp:"OMP",copilot:"Copilot"};return{id:"new-session",type:"new-session",caseName:t,mode:n,title:"New session",subtitle:`Run ${s?.label||i[n]||n} in ${t}`}},_commandPaletteCaseName(e=""){return this._findCommandPaletteCaseMatch(e)||document.getElementById("quickStartCase")?.value||"testcase"},_commandPaletteRowCase(){const e=(this.commandPaletteItems||[]).find(t=>t?.type==="new-session");return e?e.caseName:this._commandPaletteCaseName(document.getElementById("commandPaletteSearch")?.value||"")},_commandPaletteAgentChoices(e=this._commandPaletteRowCase()){const t=typeof window<"u"&&Array.isArray(window.__codemanCliCatalog)?window.__codemanCliCatalog:[],s=n=>typeof this._runModeAvailableForCase=="function"?this._runModeAvailableForCase(n,e):this.isCliAvailable?.(n)??!0;return t.filter(n=>n&&typeof n.id=="string"&&n.enabled&&(n.kind!=="agent"||s(n.id))).map(n=>({id:n.id,label:typeof n.label=="string"&&n.label.trim()||n.id}))},_commandPaletteAgent(e=this._commandPaletteRowCase()){const t=this._commandPaletteAgentChoices(e);if(t.length<2)return null;const s=this.runMode||this._runMode;return t.find(n=>n.id===this._commandPaletteAgentId)||t.find(n=>n.id===s)||t[0]},_resetCommandPaletteAgent(){this._commandPaletteAgentId=null},_cycleCommandPaletteAgent(e){const t=this._commandPaletteRowCase(),s=this._commandPaletteAgentChoices(t);if(s.length<2)return;const n=Math.max(0,s.findIndex(i=>i.id===this._commandPaletteAgent(t)?.id));this._commandPaletteAgentId=s[((n+e)%s.length+s.length)%s.length].id,this.renderCommandPalette()},_commandPaletteArrowCyclesAgent(e){const t=(this.commandPaletteItems||[])[this.commandPaletteActiveIndex||0];if(t?.type!=="new-session"||this._commandPaletteAgentChoices(t.caseName).length<2||e.altKey||e.ctrlKey||e.metaKey||e.shiftKey)return!1;const s=e.target,n=typeof s?.value=="string"?s.value:"",i=Number.isFinite(s?.selectionStart)?s.selectionStart:n.length,o=Number.isFinite(s?.selectionEnd)?s.selectionEnd:i;return i!==o?!1:e.key==="ArrowRight"?o>=n.length:i<=0},_findCommandPaletteCaseMatch(e=""){const t=e.trim().toLowerCase();if(!t||!Array.isArray(this.cases))return null;const s=o=>{const l=String(o?.name||"").trim();if(!l)return 0;const a=[l,o?.path,o?.casePath,o?.workingDir,o?.remote?.path,o?.remote?.hostId].filter(Boolean).join(" ").toLowerCase(),r=l.toLowerCase();return r===t?100:r.startsWith(t)?90:r.includes(t)?80:a.includes(t)?60:0};let n=null,i=0;for(const o of this.cases){const l=s(o);l>i&&(n=o,i=l)}return n?.name||null},renderCommandPalette(){const e=document.getElementById("commandPaletteSearch"),t=document.getElementById("commandPaletteList");if(!t)return;const s=e?.value||"",n=this.buildCommandPaletteItems(s);this.commandPaletteItems=n,this.commandPaletteActiveIndex=Math.max(0,Math.min(this.commandPaletteActiveIndex||0,n.length-1)),t.innerHTML=n.map((i,o)=>{const l=o===this.commandPaletteActiveIndex?" active":"",a=i.type==="new-session"?"+":i.type==="browse-sessions"?"\u2261":"\u203A",r=i.type==="browse-sessions"?" command-palette-item--browse":"",c=i.type==="new-session"?this._renderCommandPaletteAgentPicker(i.mode,i.caseName):"";return`
2
+ <button class="command-palette-item${l}${r}${c?" command-palette-item--agent":""}" type="button" data-command-index="${o}">
3
3
  <span class="command-palette-icon" aria-hidden="true">${a}</span>
4
4
  <span class="command-palette-text">
5
5
  <span class="command-palette-title">${escapeHtml(i.title)}</span>
6
6
  <span class="command-palette-subtitle">${escapeHtml(i.subtitle||"")}</span>
7
- </span>
7
+ </span>${c}
8
8
  </button>
9
- `}).join("")},moveCommandPaletteSelection(e){const t=this.commandPaletteItems||this.buildCommandPaletteItems(document.getElementById("commandPaletteSearch")?.value||"");t.length&&(this.commandPaletteActiveIndex=(this.commandPaletteActiveIndex+e+t.length)%t.length,this.renderCommandPalette())},async activateCommandPaletteItem(e=this.commandPaletteActiveIndex||0){const t=(this.commandPaletteItems||[])[e];if(t){if(this.closeCommandPalette(),t.type==="session"&&t.sessionId){await this.selectSession(t.sessionId);return}if(t.type==="browse-sessions"){this.openSessionManager();return}if(t.type==="new-session"){const s=document.getElementById("quickStartCase");if(s&&t.caseName){if(s.tagName==="SELECT"&&typeof s.appendChild=="function"&&!Array.from(s.options||[]).some(n=>n.value===t.caseName)){const n=document.createElement("option");n.value=t.caseName,n.textContent=t.caseName,s.appendChild(n)}typeof this.selectQuickStartCase=="function"?this.selectQuickStartCase(t.caseName):s.value=t.caseName}await this.run()}}},async openSessionManager(){const e=document.getElementById("sessionManagerModal");if(e&&(e.classList.add("active"),this._sessionManagerEscWired||(this._sessionManagerEscWired=!0,e.addEventListener("keydown",s=>{s.key==="Escape"&&(s.preventDefault(),s.stopPropagation(),this.closeSessionManager())}))),!Array.isArray(this.cases)||this.cases.length===0)try{const s=await fetch("/api/cases"),n=s.ok?await s.json():null;this.cases=n?.data||[]}catch{this.cases=this.cases||[]}const t=document.getElementById("sessionManagerSearch");t&&(this._sessionManagerSearchWired||(this._sessionManagerSearchWired=!0,t.addEventListener("input",()=>{const s=t.value.trim();this._debouncedCall("sessionManagerSearch",()=>this._loadSessionManagerList(s),200)})),t.value="",this._rememberOverlayFocus("_sessionManagerPrevFocus"),t.focus()),await this._loadSessionManagerList("")},closeSessionManager(){const e=document.getElementById("sessionManagerModal");e?.classList?.contains("active")&&(e.classList.remove("active"),this._restoreOverlayFocus("_sessionManagerPrevFocus",e))},_setSessionManagerMessage(e,t){e.replaceChildren();const s=document.createElement("p");s.className="empty-message",s.textContent=t,e.appendChild(s)},async _loadSessionManagerList(e=""){this._sessionManagerQuery=e;const t=document.getElementById("sessionManagerList");if(t)try{const s="/api/sessions/unified?limit=200"+(e?"&q="+encodeURIComponent(e):""),n=await fetch(s),i=await n.json().catch(()=>null);if(!n.ok||!i||i.success===!1||!i.data){this._setSessionManagerMessage(t,i?.error||`Failed to load sessions (HTTP ${n.status})`);return}const o=i.data.sessions||[];if(t.replaceChildren(),o.length===0){this._setSessionManagerMessage(t,e?"No sessions match your search":"No sessions found");return}for(const l of o){const a={sessionId:l.sessionId,workingDir:l.workingDir||"",sizeBytes:l.sizeBytes??0,lastModified:new Date(l.lastActivityAt??l.createdAt??Date.now()).toISOString(),firstPrompt:l.firstPrompt||l.name||"",gitBranch:l.gitBranch,worktreeName:l.worktreeName,worktreeRepo:l.worktreeRepo,mode:l.mode,claudeSessionId:l.claudeSessionId,resumeId:l.resumeId},r=!!this.sessions?.has?.(l.sessionId),c=this._buildHistoryItem(a,this.cases,{showViewAll:!1,onActivate:()=>{this.closeSessionManager(),r?this.selectSession(l.sessionId):a.workingDir&&this.resumeHistorySession(l.claudeSessionId||l.sessionId,a.workingDir,void 0,l.mode,l.resumeId)}});t.appendChild(c)}}catch(s){console.error("[_loadSessionManagerList]",s),this._setSessionManagerMessage(t,"Failed to load sessions")}},async openAwayDigest(e="since-last-visit"){this.awayDigestRange=e,this._awayDigestLoadedSuccessfully=!1,this._awayDigestSinceLastVisitGeneratedAt=void 0;const t=document.getElementById("awayDigestModal");t&&t.classList.add("active"),this.updateAwayDigestRangeControls(),await this.loadAwayDigest()},closeAwayDigest(){const e=document.getElementById("awayDigestModal"),t=this._awayDigestSinceLastVisitGeneratedAt;if(Number.isFinite(t))try{localStorage.setItem(AWAY_DIGEST_LAST_VIEWED_KEY,String(t))}catch(s){console.warn("Failed to save away digest last-viewed marker:",s)}e&&e.classList.remove("active")},_onSessionListMaybeChanged(){const e=document.getElementById("sessionManagerModal");e&&e.classList.contains("active")&&this._debouncedCall("sessionManagerRefresh",()=>this._loadSessionManagerList(this._sessionManagerQuery||""),400);const t=document.getElementById("welcomeOverlay");t&&t.classList.contains("visible")&&this._debouncedCall("welcomeHistoryRefresh",()=>this.loadHistorySessions(),600)},setAwayDigestRange(e){this.awayDigestRange=e,this._awayDigestLoadedSuccessfully=!1,this.updateAwayDigestRangeControls(),this.loadAwayDigest()},updateAwayDigestRangeControls(){const e=this.awayDigestRange||"since-last-visit";document.querySelectorAll("[data-away-range]").forEach(s=>{s.classList.toggle("active",s.dataset.awayRange===e)});const t=document.getElementById("awayDigestCustomRange");t&&t.classList.toggle("active",e==="custom"),e==="custom"&&this.ensureAwayDigestCustomDefaults()},ensureAwayDigestCustomDefaults(){const e=document.getElementById("awayDigestCustomSince"),t=document.getElementById("awayDigestCustomUntil");if(!e||!t)return;const s=new Date;if(t.value||(t.value=this.formatAwayDigestDateTimeLocal(s)),!e.value){const n=new Date(s.getTime()-36e5);e.value=this.formatAwayDigestDateTimeLocal(n)}},formatAwayDigestDateTimeLocal(e){const t=s=>String(s).padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}T${t(e.getHours())}:${t(e.getMinutes())}`},async loadAwayDigest(){const e=document.getElementById("awayDigestSummary"),t=document.getElementById("awayDigestFreshness"),s=document.getElementById("awayDigestSections");e&&(e.innerHTML='<div class="away-digest-loading">Loading digest...</div>'),t&&(t.textContent=""),s&&(s.innerHTML="");try{const n=this.awayDigestRange||"since-last-visit",i=new URLSearchParams({range:n});if(n==="since-last-visit"){const a=this.readAwayDigestLastViewed();Number.isFinite(a)&&i.set("lastViewed",String(a))}if(n==="custom"){this.ensureAwayDigestCustomDefaults();const a=this.readAwayDigestDateTimeInput("awayDigestCustomSince"),r=this.readAwayDigestDateTimeInput("awayDigestCustomUntil");if(!Number.isFinite(a))throw new Error("Choose a custom start time");i.set("since",String(a)),Number.isFinite(r)&&i.set("until",String(r))}const o=await fetch(`/api/away-digest?${i.toString()}`),l=await o.json();if(!o.ok||!l.success)throw new Error(l.error||"Failed to load away digest");this._awayDigestLoadedSuccessfully=!0,this._awayDigestGeneratedAt=l.digest.generatedAt,n==="since-last-visit"&&(this._awayDigestSinceLastVisitGeneratedAt=l.digest.generatedAt),this.renderAwayDigest(l.digest)}catch(n){const i=n instanceof Error?n.message:"Failed to load away digest";console.error("Failed to fetch away digest:",n),e&&(e.innerHTML='<div class="away-digest-load-error">Failed to load away digest</div>'),s&&(s.innerHTML=`<div class="empty-message">${escapeHtml(i)}</div>`),this.showToast(i,"error")}},readAwayDigestLastViewed(){try{const e=localStorage.getItem(AWAY_DIGEST_LAST_VIEWED_KEY),t=Number(e);return Number.isFinite(t)?t:void 0}catch{return}},readAwayDigestDateTimeInput(e){const t=document.getElementById(e);if(!t||!t.value)return;const s=Date.parse(t.value);return Number.isFinite(s)?s:void 0},renderAwayDigest(e){const t=document.getElementById("awayDigestSummary"),s=document.getElementById("awayDigestFreshness"),n=document.getElementById("awayDigestSections");if(!t||!s||!n)return;const i=e.totals.inputTokens||0,o=e.totals.outputTokens||0,l=e.totals.estimatedCost||0;t.innerHTML=`
9
+ `}).join("")},_renderCommandPaletteAgentPicker(e,t){const s=this._commandPaletteAgentChoices(t);if(s.length<2)return"";const n=s.find(i=>i.id===e)||s[0];return`
10
+ <span class="command-palette-agent" aria-hidden="true" title="Agent for the new session (Left/Right to change)">
11
+ <span class="command-palette-agent-arrow" data-palette-agent-cycle="prev">&lsaquo;</span>
12
+ <span class="run-mode-dot ${escapeHtml(n.id)}" aria-hidden="true"></span>
13
+ <span class="command-palette-agent-label">${escapeHtml(n.label)}</span>
14
+ <span class="command-palette-agent-arrow" data-palette-agent-cycle="next">&rsaquo;</span>
15
+ </span>`},moveCommandPaletteSelection(e){const t=this.commandPaletteItems||this.buildCommandPaletteItems(document.getElementById("commandPaletteSearch")?.value||"");t.length&&(this.commandPaletteActiveIndex=(this.commandPaletteActiveIndex+e+t.length)%t.length,this.renderCommandPalette())},async activateCommandPaletteItem(e=this.commandPaletteActiveIndex||0){const t=(this.commandPaletteItems||[])[e];if(t){if(this.closeCommandPalette(),t.type==="session"&&t.sessionId){await this.selectSession(t.sessionId);return}if(t.type==="browse-sessions"){this.openSessionManager();return}if(t.type==="new-session"){const s=document.getElementById("quickStartCase");if(s&&t.caseName){if(s.tagName==="SELECT"&&typeof s.appendChild=="function"&&!Array.from(s.options||[]).some(i=>i.value===t.caseName)){const i=document.createElement("option");i.value=t.caseName,i.textContent=t.caseName,s.appendChild(i)}typeof this.selectQuickStartCase=="function"?this.selectQuickStartCase(t.caseName):s.value=t.caseName}const n=this._runMode;t.mode&&(this._runMode=t.mode);try{await this.run()}finally{this._runMode=n}}}},async openSessionManager(){const e=document.getElementById("sessionManagerModal");if(e&&(e.classList.add("active"),this._sessionManagerEscWired||(this._sessionManagerEscWired=!0,e.addEventListener("keydown",s=>{s.key==="Escape"&&(s.preventDefault(),s.stopPropagation(),this.closeSessionManager())}))),!Array.isArray(this.cases)||this.cases.length===0)try{const s=await fetch("/api/cases"),n=s.ok?await s.json():null;this.cases=n?.data||[]}catch{this.cases=this.cases||[]}const t=document.getElementById("sessionManagerSearch");t&&(this._sessionManagerSearchWired||(this._sessionManagerSearchWired=!0,t.addEventListener("input",()=>{const s=t.value.trim();this._debouncedCall("sessionManagerSearch",()=>this._loadSessionManagerList(s),200)})),t.value="",this._rememberOverlayFocus("_sessionManagerPrevFocus"),t.focus()),await this._loadSessionManagerList("")},closeSessionManager(){const e=document.getElementById("sessionManagerModal");e?.classList?.contains("active")&&(e.classList.remove("active"),this._restoreOverlayFocus("_sessionManagerPrevFocus",e))},_setSessionManagerMessage(e,t){e.replaceChildren();const s=document.createElement("p");s.className="empty-message",s.textContent=t,e.appendChild(s)},async _loadSessionManagerList(e=""){this._sessionManagerQuery=e;const t=document.getElementById("sessionManagerList");if(t)try{const s="/api/sessions/unified?limit=200"+(e?"&q="+encodeURIComponent(e):""),n=await fetch(s),i=await n.json().catch(()=>null);if(!n.ok||!i||i.success===!1||!i.data){this._setSessionManagerMessage(t,i?.error||`Failed to load sessions (HTTP ${n.status})`);return}const o=i.data.sessions||[];if(t.replaceChildren(),o.length===0){this._setSessionManagerMessage(t,e?"No sessions match your search":"No sessions found");return}for(const l of o){const a={sessionId:l.sessionId,workingDir:l.workingDir||"",sizeBytes:l.sizeBytes??0,lastModified:new Date(l.lastActivityAt??l.createdAt??Date.now()).toISOString(),firstPrompt:l.firstPrompt||l.name||"",gitBranch:l.gitBranch,worktreeName:l.worktreeName,worktreeRepo:l.worktreeRepo,mode:l.mode,claudeSessionId:l.claudeSessionId,resumeId:l.resumeId},r=!!this.sessions?.has?.(l.sessionId),c=this._buildHistoryItem(a,this.cases,{showViewAll:!1,onActivate:()=>{this.closeSessionManager(),r?this.selectSession(l.sessionId):a.workingDir&&this.resumeHistorySession(l.claudeSessionId||l.sessionId,a.workingDir,void 0,l.mode,l.resumeId)}});t.appendChild(c)}}catch(s){console.error("[_loadSessionManagerList]",s),this._setSessionManagerMessage(t,"Failed to load sessions")}},async openAwayDigest(e="since-last-visit"){this.awayDigestRange=e,this._awayDigestLoadedSuccessfully=!1,this._awayDigestSinceLastVisitGeneratedAt=void 0;const t=document.getElementById("awayDigestModal");t&&t.classList.add("active"),this.updateAwayDigestRangeControls(),await this.loadAwayDigest()},closeAwayDigest(){const e=document.getElementById("awayDigestModal"),t=this._awayDigestSinceLastVisitGeneratedAt;if(Number.isFinite(t))try{localStorage.setItem(AWAY_DIGEST_LAST_VIEWED_KEY,String(t))}catch(s){console.warn("Failed to save away digest last-viewed marker:",s)}e&&e.classList.remove("active")},_onSessionListMaybeChanged(){const e=document.getElementById("sessionManagerModal");e&&e.classList.contains("active")&&this._debouncedCall("sessionManagerRefresh",()=>this._loadSessionManagerList(this._sessionManagerQuery||""),400);const t=document.getElementById("welcomeOverlay");t&&t.classList.contains("visible")&&this._debouncedCall("welcomeHistoryRefresh",()=>this.loadHistorySessions(),600)},setAwayDigestRange(e){this.awayDigestRange=e,this._awayDigestLoadedSuccessfully=!1,this.updateAwayDigestRangeControls(),this.loadAwayDigest()},updateAwayDigestRangeControls(){const e=this.awayDigestRange||"since-last-visit";document.querySelectorAll("[data-away-range]").forEach(s=>{s.classList.toggle("active",s.dataset.awayRange===e)});const t=document.getElementById("awayDigestCustomRange");t&&t.classList.toggle("active",e==="custom"),e==="custom"&&this.ensureAwayDigestCustomDefaults()},ensureAwayDigestCustomDefaults(){const e=document.getElementById("awayDigestCustomSince"),t=document.getElementById("awayDigestCustomUntil");if(!e||!t)return;const s=new Date;if(t.value||(t.value=this.formatAwayDigestDateTimeLocal(s)),!e.value){const n=new Date(s.getTime()-36e5);e.value=this.formatAwayDigestDateTimeLocal(n)}},formatAwayDigestDateTimeLocal(e){const t=s=>String(s).padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}T${t(e.getHours())}:${t(e.getMinutes())}`},async loadAwayDigest(){const e=document.getElementById("awayDigestSummary"),t=document.getElementById("awayDigestFreshness"),s=document.getElementById("awayDigestSections");e&&(e.innerHTML='<div class="away-digest-loading">Loading digest...</div>'),t&&(t.textContent=""),s&&(s.innerHTML="");try{const n=this.awayDigestRange||"since-last-visit",i=new URLSearchParams({range:n});if(n==="since-last-visit"){const a=this.readAwayDigestLastViewed();Number.isFinite(a)&&i.set("lastViewed",String(a))}if(n==="custom"){this.ensureAwayDigestCustomDefaults();const a=this.readAwayDigestDateTimeInput("awayDigestCustomSince"),r=this.readAwayDigestDateTimeInput("awayDigestCustomUntil");if(!Number.isFinite(a))throw new Error("Choose a custom start time");i.set("since",String(a)),Number.isFinite(r)&&i.set("until",String(r))}const o=await fetch(`/api/away-digest?${i.toString()}`),l=await o.json();if(!o.ok||!l.success)throw new Error(l.error||"Failed to load away digest");this._awayDigestLoadedSuccessfully=!0,this._awayDigestGeneratedAt=l.digest.generatedAt,n==="since-last-visit"&&(this._awayDigestSinceLastVisitGeneratedAt=l.digest.generatedAt),this.renderAwayDigest(l.digest)}catch(n){const i=n instanceof Error?n.message:"Failed to load away digest";console.error("Failed to fetch away digest:",n),e&&(e.innerHTML='<div class="away-digest-load-error">Failed to load away digest</div>'),s&&(s.innerHTML=`<div class="empty-message">${escapeHtml(i)}</div>`),this.showToast(i,"error")}},readAwayDigestLastViewed(){try{const e=localStorage.getItem(AWAY_DIGEST_LAST_VIEWED_KEY),t=Number(e);return Number.isFinite(t)?t:void 0}catch{return}},readAwayDigestDateTimeInput(e){const t=document.getElementById(e);if(!t||!t.value)return;const s=Date.parse(t.value);return Number.isFinite(s)?s:void 0},renderAwayDigest(e){const t=document.getElementById("awayDigestSummary"),s=document.getElementById("awayDigestFreshness"),n=document.getElementById("awayDigestSections");if(!t||!s||!n)return;const i=e.totals.inputTokens||0,o=e.totals.outputTokens||0,l=e.totals.estimatedCost||0;t.innerHTML=`
10
16
  <div class="away-digest-card">
11
17
  <span class="away-digest-card-label">Needs Attention</span>
12
18
  <span class="away-digest-card-value">${e.totals.needsAttention}</span>
@@ -67,14 +73,14 @@
67
73
  <span class="stat-card-value">${this.formatTokens(h+d)}</span>
68
74
  <span class="stat-card-cost">~$${u.toFixed(2)}</span>
69
75
  </div>
70
- `;const f=document.getElementById("statsChart"),w=document.getElementById("statsChartDays"),y=[];for(let m=6;m>=0;m--){const S=new Date;S.setDate(S.getDate()-m);const $=S.toISOString().split("T")[0],b=t.find(C=>C.date===$);y.push({date:$,dayName:S.toLocaleDateString("en-US",{weekday:"short"}),tokens:b?b.inputTokens+b.outputTokens:0,cost:b?b.estimatedCost:0})}const v=Math.max(...y.map(m=>m.tokens),1);f.innerHTML=y.map(m=>{const S=Math.max(m.tokens/v*100,3),$=`${m.dayName}: ${this.formatTokens(m.tokens)} (~$${m.cost.toFixed(2)})`;return`<div class="bar" style="height: ${S}%" data-tooltip="${$}"></div>`}).join(""),w.innerHTML=y.map(m=>`<span>${m.dayName}</span>`).join("");const g=document.getElementById("statsTable"),T=t.slice(0,14);T.length===0?g.innerHTML='<div class="stats-no-data">No usage data recorded yet</div>':g.innerHTML=`
76
+ `;const f=document.getElementById("statsChart"),w=document.getElementById("statsChartDays"),y=[];for(let m=6;m>=0;m--){const S=new Date;S.setDate(S.getDate()-m);const $=S.toISOString().split("T")[0],b=t.find(T=>T.date===$);y.push({date:$,dayName:S.toLocaleDateString("en-US",{weekday:"short"}),tokens:b?b.inputTokens+b.outputTokens:0,cost:b?b.estimatedCost:0})}const v=Math.max(...y.map(m=>m.tokens),1);f.innerHTML=y.map(m=>{const S=Math.max(m.tokens/v*100,3),$=`${m.dayName}: ${this.formatTokens(m.tokens)} (~$${m.cost.toFixed(2)})`;return`<div class="bar" style="height: ${S}%" data-tooltip="${$}"></div>`}).join(""),w.innerHTML=y.map(m=>`<span>${m.dayName}</span>`).join("");const g=document.getElementById("statsTable"),C=t.slice(0,14);C.length===0?g.innerHTML='<div class="stats-no-data">No usage data recorded yet</div>':g.innerHTML=`
71
77
  <div class="stats-table-header">
72
78
  <span>Date</span>
73
79
  <span>Input</span>
74
80
  <span>Output</span>
75
81
  <span>Cost</span>
76
82
  </div>
77
- ${T.map(m=>`
83
+ ${C.map(m=>`
78
84
  <div class="stats-table-row">
79
85
  <span class="cell cell-date">${new Date(m.date+"T00:00:00").toLocaleDateString("en-US",{month:"short",day:"numeric"})}</span>
80
86
  <span class="cell">${this.formatTokens(m.inputTokens)}</span>
@@ -236,12 +242,12 @@
236
242
  ${d}
237
243
  ${p}
238
244
  </div>
239
- `}).join("")}n.querySelectorAll(".file-tree-item").forEach(a=>{a.addEventListener("click",()=>{const r=a.dataset.path;a.dataset.type==="directory"?this._openFileBrowserSearchDirectory({...o,path:r}):this.openFilePreview(r,t)})});const l=this.$("fileBrowserStatus");if(l){const a=s.matchCount===void 0?e.length:s.matchCount;l.textContent=`${a} ${a===1?"match":"matches"}${s.truncated?" (truncated)":""}`}},_findFileBrowserDirectory(e,t,s=[]){if(!Array.isArray(e))return null;for(const n of e){if(!n||typeof n!="object")continue;if(n.type==="directory"&&n.path===t)return{target:n,ancestors:[...s]};if(n.type!=="directory"||!Array.isArray(n.children))continue;const i=this._findFileBrowserDirectory(n.children,t,[...s,n.path]);if(i)return i}return null},_isFileBrowserDirectoryContextCurrent(e){const t=this._ensureFileBrowserState(),s=this.$?.("fileBrowserSearch"),n=typeof s?.value=="string"?s.value:t.filter;return e&&t.ownerSessionId===e.ownerSessionId&&this.activeSessionId===e.ownerSessionId&&t.treeEpoch===e.treeEpoch&&t.searchEpoch===e.searchEpoch&&this.fileBrowserShowHidden===!0===e.showHidden&&t.filter===e.rawInput&&n===e.rawInput&&n.trim()===e.query&&t.view===e.view&&this.$?.("fileBrowserPanel")?.classList.contains("visible")===!0},_promptFileBrowserDirectoryReload(){this.showToast?.("Reload files before opening this folder","info")},_openFileBrowserSearchDirectory(e){if(!this._isFileBrowserDirectoryContextCurrent(e))return;const t=this._ensureFileBrowserState(),s=t.normalState;if(!this._isFileBrowserNormalCompatible(s,e.ownerSessionId,e.showHidden,e.treeEpoch)){t.deferredDirectoryTarget=null,this._promptFileBrowserDirectoryReload();return}if(s.phase==="loading"){t.deferredDirectoryTarget={...e};return}if(t.deferredDirectoryTarget=null,s.phase!=="ready"){this._promptFileBrowserDirectoryReload();return}const n=this._findFileBrowserDirectory(s.data?.tree,e.path);if(!n){this._promptFileBrowserDirectoryReload();return}this._leaveFileBrowserSearchForDirectory([...n.ancestors,n.target.path],s)},_completeDeferredFileBrowserDirectory(e){const t=this._ensureFileBrowserState(),s=t.deferredDirectoryTarget;if(!s)return!1;if(!this._isFileBrowserDirectoryContextCurrent(s))return t.deferredDirectoryTarget===s&&(t.deferredDirectoryTarget=null),!1;if(!this._isFileBrowserNormalCompatible(e,s.ownerSessionId,s.showHidden,s.treeEpoch)||e.phase!=="ready"&&e.phase!=="error")return!1;if(t.deferredDirectoryTarget=null,e.phase==="error")return this._promptFileBrowserDirectoryReload(),!1;const n=this._findFileBrowserDirectory(e.data?.tree,s.path);return n?(this._leaveFileBrowserSearchForDirectory([...n.ancestors,n.target.path],e),!0):(this._promptFileBrowserDirectoryReload(),!1)},_leaveFileBrowserSearchForDirectory(e,t){const s=this._ensureFileBrowserState();s.inFlight?.timer!==void 0&&s.inFlight?.timer!==null&&clearTimeout(s.inFlight.timer),s.searchEpoch++,s.inFlight=null,s.filter="",s.matches=[],s.deferredDirectoryTarget=null,s.view="normal",this.fileBrowserFilter="";const n=this.$?.("fileBrowserSearch");n&&(n.value=""),this._syncFileBrowserExpandBtn();for(const i of e)typeof i=="string"&&this.fileBrowserExpandedDirs?.add?.(i);this.fileBrowserData=t.data,this._renderFileBrowserNormalState(t)},expandAllDirectories(e){for(const t of e)t.type==="directory"&&(this.fileBrowserExpandedDirs.add(t.path),t.children&&this.expandAllDirectories(t.children))},collapseAllDirectories(){this.fileBrowserExpandedDirs.clear()},toggleFileBrowserExpand(){if(this._hasFileBrowserQuery()){this._syncFileBrowserExpandBtn();return}this.fileBrowserAllExpanded=!this.fileBrowserAllExpanded;const e=this.$("fileBrowserExpandBtn");this.fileBrowserAllExpanded?(this.expandAllDirectories(this.fileBrowserData?.tree||[]),e&&(e.innerHTML="\u229F")):(this.collapseAllDirectories(),e&&(e.innerHTML="\u229E")),this.renderFileBrowserTree()},refreshFileBrowser(){const e=this._ensureFileBrowserState();e.inFlight?.timer!==void 0&&e.inFlight?.timer!==null&&clearTimeout(e.inFlight.timer),e.inFlight=null,e.searchEpoch++,e.filter="",e.matches=[],e.deferredDirectoryTarget=null,e.view="normal",this.fileBrowserFilter="",this.fileBrowserExpandedDirs.clear(),this.fileBrowserAllExpanded=!1;const t=this.$("fileBrowserExpandBtn");t&&(t.innerHTML="\u229E");const s=this.$("fileBrowserSearch");s&&(s.value=""),this._syncFileBrowserExpandBtn();const n=e.ownerSessionId||this.activeSessionId;if(!(!n||this.activeSessionId!==n))return this.loadFileBrowser(n,{force:!0})},toggleFileBrowserButton(){const t=this.$("fileBrowserPanel")?.classList.contains("visible"),s=document.querySelector(".btn-file-viewer");if(t){this.closeFileBrowserPanel(),s&&s.setAttribute("aria-expanded","false");return}if(!this.activeSessionId){this.showToast("Open a session to browse its files","info");return}const n=this.loadAppSettingsFromStorage();n.showFileBrowser=!0,this.saveAppSettingsToStorage(n);const i=document.getElementById("appSettingsShowFileBrowser");i&&(i.checked=!0),this.applyMonitorVisibility(),s&&s.setAttribute("aria-expanded","true")},closeFileBrowserPanel(){const e=this.$("fileBrowserPanel");if(this._resetFileBrowserForHide(),e&&(e.classList.remove("visible"),e.style.left="",e.style.top="",e.style.bottom="",e.style.right=""),this.fileBrowserDragListeners){const i=this.fileBrowserDragListeners;document.removeEventListener("mousemove",i.move),document.removeEventListener("mouseup",i.up),document.removeEventListener("touchmove",i.touchMove),document.removeEventListener("touchend",i.up),document.removeEventListener("touchcancel",i.up),i.handle&&(i.handle.removeEventListener("mousedown",i.handleMouseDown),i.handle.removeEventListener("touchstart",i.handleTouchStart),i._onFirstDrag&&(i.handle.removeEventListener("mousedown",i._onFirstDrag),i.handle.removeEventListener("touchstart",i._onFirstDrag))),this.fileBrowserDragListeners=null}const t=this.loadAppSettingsFromStorage();t.showFileBrowser=!1,this.saveAppSettingsToStorage(t);const s=document.getElementById("appSettingsShowFileBrowser");s&&(s.checked=!1);const n=document.querySelector(".btn-file-viewer");n&&n.setAttribute("aria-expanded","false")},_isExternalPreviewPath(e,t){if(typeof e=="string"&&e.startsWith("~/"))return!0;if(typeof e!="string"||!e.startsWith("/"))return!1;const s=this.sessions.get(t)?.workingDir;if(!s)return!1;const n=s.endsWith("/")?s:`${s}/`;return e!==s&&!e.startsWith(n)},async _registerExternalPreview(e,t){try{const s=await fetch(`/api/sessions/${t}/attachments`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e,notify:!1})}),n=await s.json().catch(()=>null);if(s.ok&&n?.success&&n.data?.attachmentId)return{attachmentId:n.data.attachmentId,size:n.data.size||0};const i=n?.error||`Cannot open this file (HTTP ${s.status})`;return/unsupported/i.test(i)?{error:`Cannot preview .${(e.split(".").pop()||"").toLowerCase()} from outside the session workspace (images, video, audio, PDF, Office documents and text files only).`}:{error:i}}catch(s){return{error:s.message||"Cannot open this file"}}},async openFilePreview(e,t=this.activeSessionId,s=null,n={}){if(!t||!e)return;const i=n.folderFile||null;!i&&this.folderGrid&&(this.folderGrid.index=null),this._updateFolderPreviewNav(i?null:this._previewFolderPath(e,t,s));const o=this.$("filePreviewOverlay"),l=this.$("filePreviewTitle"),a=this.$("filePreviewBody"),r=this.$("filePreviewFooter");if(!o||!a)return;const c=this._filePreviewLoad=(this._filePreviewLoad||0)+1,h=()=>c!==this._filePreviewLoad;this._resetFilePreviewEdit(),this._stopFilePreviewMedia(),this.filePreviewDetachUrl="";const d=this.$("filePreviewDetachBtn");d&&(d.hidden=!0),this.filePreviewText=null,this.filePreviewPage=null,this.filePreviewPageRefused=!1,this._updateFilePreviewToolbar("none"),o.classList.add("visible"),l.textContent=e,a.innerHTML='<div class="binary-message">Loading...</div>',r.textContent="";const u=(e.split(".").pop()||"").toLowerCase();if(!s&&rendersAsPage(e)&&this._filePreviewPref("htmlRendered")){const g=await this._mintHtmlViewUrl(e,t);if(g){r.textContent="HTML",this.filePreviewPage={filePath:e,sessionId:t},this.filePreviewDetachUrl=g,d&&(d.hidden=!1),a.innerHTML=`<iframe src="${escapeHtml(g)}" title="${escapeHtml(e)}" sandbox="allow-scripts allow-forms allow-popups allow-modals allow-downloads"></iframe>`,this._updateFilePreviewToolbar("page");return}this.filePreviewPageRefused=!0}let p="",f=0;if(!s&&!i&&this._isExternalPreviewPath(e,t)){const g=await this._registerExternalPreview(e,t);if(h())return;s=g.attachmentId||null,p=g.error||"",f=g.size||0}if(!s&&p){r.textContent="",a.innerHTML=`<div class="binary-message">${escapeHtml(p)}</div>`;return}const w=u==="docx"||u==="pptx",y=s?`/api/sessions/${t}/attachments/${encodeURIComponent(s)}`:i?`/api/sessions/${t}/folders/${encodeURIComponent(i.folderId)}/files/${encodeURIComponent(i.name)}`:null;if(this.filePreviewDetachUrl=CodemanBase.url(y?`${y}/${w?"preview":"raw"}`:w?`/api/sessions/${t}/file-preview?path=${encodeURIComponent(e)}`:`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}`),d&&(d.hidden=!1),y){const g=CodemanBase.url(y),T=new Set(["png","jpg","jpeg","gif","webp","bmp","svg"]),m=new Set(["mp4","webm","mov","m4v","ogv"]),S=new Set(["mp3","wav","ogg","oga","m4a","aac","flac","opus"]);if(i&&!f&&(f=n.size||0),r.textContent=f?`${this.formatFileSize(f)} \u2022 ${u}`:u.toUpperCase(),T.has(u))a.innerHTML=`<img src="${escapeHtml(`${g}/raw`)}" alt="${escapeHtml(e)}">`;else if(m.has(u))a.innerHTML=`<video src="${escapeHtml(`${g}/raw`)}" controls autoplay playsinline preload="metadata"></video>`;else if(S.has(u))a.innerHTML=`<audio src="${escapeHtml(`${g}/raw`)}" controls autoplay preload="metadata"></audio>`;else if(u==="pdf")a.innerHTML=`<iframe src="${escapeHtml(`${g}/raw`)}" title="${escapeHtml(e)}"></iframe>`;else if(u==="docx"||u==="pptx")a.innerHTML=`<iframe src="${escapeHtml(`${g}/preview`)}" title="${escapeHtml(e)}"></iframe>`;else if(u==="xlsx")this._openSpreadsheetPreview(a,`${g}/raw`,f);else try{const $=await fetch(`${g}/raw`,{headers:{Range:"bytes=0-524287"}});if(!$.ok)throw new Error("Failed to load attachment");const b=await $.text();if(h())return;const C=$.status===206&&b.length>=524288,E=b.split(`
240
- `),I=MARKDOWN_EXTS.has(u)?1/0:500,B=E.length>I,D=B?E.slice(0,I).join(`
241
- `):b;if(this.filePreviewContent=D,this.filePreviewText={ext:u,sessionId:t,filePath:e,attachmentId:s||i?.folderId},this._renderFilePreviewText(),B||C){const F=B?`showing first ${I} lines`:"showing the start of the file";r.textContent=`${r.textContent} (${F})`}}catch($){if(h())return;a.innerHTML=`<div class="binary-message">Error: ${escapeHtml($.message)}</div>`}return}if(u==="docx"||u==="pptx"){r.textContent=u.toUpperCase();const g=CodemanBase.url(`/api/sessions/${t}/file-preview?path=${encodeURIComponent(e)}`);a.innerHTML=`<iframe src="${escapeHtml(g)}" title="${escapeHtml(e)}"></iframe>`;return}if(u==="pdf"){r.textContent="PDF";const g=CodemanBase.url(`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}`);a.innerHTML=`<iframe src="${escapeHtml(g)}" title="${escapeHtml(e)}"></iframe>`;return}if(u==="svg"){r.textContent="SVG";try{const g=await fetch(`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}`);if(!g.ok)throw new Error("Failed to load image");const T=await g.text();if(h())return;const m=URL.createObjectURL(new Blob([T],{type:"image/svg+xml"}));a.innerHTML=`<img src="${m}" alt="${escapeHtml(e)}">`;const S=a.querySelector("img");S&&(S.onload=()=>URL.revokeObjectURL(m))}catch(g){if(h())return;a.innerHTML=`<div class="binary-message">Error: ${escapeHtml(g.message)}</div>`}return}const v=MARKDOWN_EXTS.has(u)?1e4:500;try{const g=await fetch(`/api/sessions/${t}/file-content?path=${encodeURIComponent(e)}&lines=${v}`);if(!g.ok)throw new Error("Failed to load file");const T=await g.json();if(h())return;if(!T.success)throw new Error(T.error||"Failed to load file");const m=T.data;if(m.type==="image")a.innerHTML=`<img src="${escapeHtml(CodemanBase.url(m.url))}" alt="${escapeHtml(e)}">`,r.textContent=`${this.formatFileSize(m.size)} \u2022 ${m.extension}`;else if(m.type==="video")a.innerHTML=`<video src="${escapeHtml(CodemanBase.url(m.url))}" controls autoplay playsinline preload="metadata"></video>`,r.textContent=`${this.formatFileSize(m.size)} \u2022 ${m.extension}`;else if(m.type==="audio")a.innerHTML=`<audio src="${escapeHtml(CodemanBase.url(m.url))}" controls autoplay preload="metadata"></audio>`,r.textContent=`${this.formatFileSize(m.size)} \u2022 ${m.extension}`;else if(m.type==="spreadsheet")this._openSpreadsheetPreview(a,CodemanBase.url(m.url),m.size),r.textContent=`${this.formatFileSize(m.size)} \u2022 ${m.extension}`;else if(m.type==="binary"){const S=CodemanBase.url(`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}&download=true`);a.innerHTML=`<div class="binary-message">Binary file (${this.formatFileSize(m.size)})<br>Cannot preview<br><a href="${escapeHtml(S)}" download>Download</a></div>`,r.textContent=m.extension||"binary"}else{this.filePreviewContent=m.content,this.filePreviewText={ext:u,sessionId:t,filePath:e},this._renderFilePreviewText();const S=m.truncated?` (showing ${v}/${m.totalLines} lines)`:"";if(r.textContent=`${m.totalLines} lines \u2022 ${this.formatFileSize(m.size)}${S}`,m.editable){this.filePreviewEditTarget={sessionId:t,filePath:e};const $=this.$("filePreviewEditBtn");$&&($.hidden=!1)}}}catch(g){if(h())return;console.error("Failed to preview file:",g),a.innerHTML=`<div class="binary-message">Error: ${escapeHtml(g.message)}</div>`}},async openFolderGrid(e,t=this.activeSessionId){if(!t||!e)return;const s=this.$("folderGridOverlay"),n=this.$("folderGridBody");if(!s||!n)return;this._bindFolderGridKeys();const i=this._folderGridLoad=(this._folderGridLoad||0)+1;let o=null,l=0;try{const a=await fetch(`/api/sessions/${t}/folders`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e})});l=a.status,o=await a.json().catch(()=>null)}catch(a){if(i!==this._folderGridLoad)return;this.showToast(`Cannot open folder: ${a.message||a}`,"error");return}if(i===this._folderGridLoad){if(!o?.success||!o.data){const a=o?.error||`HTTP ${l}`;if(l===400&&/not a folder/i.test(a)){this.openFilePreview(e,t);return}this.showToast(`Cannot open folder ${e}: ${a}`,"error");return}this.folderGrid={sessionId:t,...o.data,index:null},this._renderFolderGrid(),s.classList.add("visible"),n.scrollTop=0}},closeFolderGrid(){this._folderGridLoad=(this._folderGridLoad||0)+1,this.$("folderGridOverlay")?.classList.remove("visible");const e=this.$("folderGridBody");e&&(e.innerHTML=""),this.folderGrid=null,this._updateFolderPreviewNav(null)},folderGridUp(){const e=this.folderGrid;!e||e.path==="/"||this.openFolderGrid(e.path.slice(0,e.path.lastIndexOf("/"))||"/",e.sessionId)},_renderFolderGrid(){const e=this.folderGrid;if(!e)return;const t=this.$("folderGridTitle"),s=this.$("folderGridFolders"),n=this.$("folderGridBody"),i=this.$("folderGridFooter");t.textContent=e.path,t.title=e.path;const o=this.$("folderGridUpBtn");o&&(o.disabled=e.path==="/"),s.innerHTML="";for(const r of e.folders){const c=document.createElement("button");c.type="button",c.className="folder-grid-chip",c.textContent=`${r}/`,c.onclick=()=>this.openFolderGrid(`${e.path==="/"?"":e.path}/${r}`,e.sessionId),s.appendChild(c)}if(n.innerHTML="",e.files.length===0){const r=document.createElement("div");r.className="folder-grid-empty",r.textContent="No previewable files in this folder.",n.appendChild(r)}e.files.forEach((r,c)=>{const h=document.createElement("button");h.type="button",h.className="folder-grid-tile",h.title=`${r.name} \u2022 ${this.formatFileSize(r.size)}`,h.dataset.index=String(c);const d=document.createElement("div");d.className="folder-grid-thumb";const u=r.extension.toUpperCase(),p=this._folderFileUrl(e,r.name,""),f=r.attachmentType==="image"?`${p}/raw`:["pdf","docx","pptx"].includes(r.extension)?`${p}/thumbnail`:null;if(f){const y=document.createElement("img");y.loading="lazy",y.decoding="async",y.alt=r.name,y.src=f,y.onerror=()=>{d.textContent=u},d.appendChild(y)}else d.textContent=u;const w=document.createElement("span");w.className="folder-grid-name",w.textContent=r.name,h.append(d,w),h.onclick=()=>this._openFolderGridFile(c),n.appendChild(h)});const l=`${e.files.length} file${e.files.length===1?"":"s"}`,a=e.folders.length?` \u2022 ${e.folders.length} folder${e.folders.length===1?"":"s"}`:"";i.textContent=`${l}${a}${e.truncated?" (folder too large \u2014 showing the first entries)":""}`},_folderFileUrl(e,t,s){return CodemanBase.url(`/api/sessions/${e.sessionId}/folders/${encodeURIComponent(e.folderId)}/files/${encodeURIComponent(t)}${s}`)},_openFolderGridFile(e){const t=this.folderGrid,s=t?.files[e];if(!s)return;const n=this.$("folderGridBody");n?.querySelectorAll(".folder-grid-tile.current").forEach(o=>o.classList.remove("current"));const i=n?.querySelector(`.folder-grid-tile[data-index="${e}"]`);i?.classList.add("current"),i?.scrollIntoView({block:"nearest"}),this.openFilePreview(`${t.path==="/"?"":t.path}/${s.name}`,t.sessionId,null,{folderFile:{folderId:t.folderId,name:s.name},size:s.size}),t.index=e,t.lastIndex=e,this._updateFolderPreviewNav(null)},stepFolderPreview(e){const t=this.folderGrid;if(!t||t.index===null||t.files.length===0||this.filePreviewEdit?.dirty&&!confirm("Discard unsaved changes?"))return;const s=(t.index+e+t.files.length)%t.files.length;this._openFolderGridFile(s)},openFolderOfPreview(){const e=this.filePreviewFolderTarget;e&&(this.closeFilePreview(),this.openFolderGrid(e.dir,e.sessionId))},_previewFolderPath(e,t,s){if(typeof e!="string"||s&&!e.includes("/"))return null;const n=this.sessions?.get?.(t)?.workingDir,i=typeof resolveLinkedFilePath=="function"?resolveLinkedFilePath(e,n):e;if(!i.startsWith("/")&&!i.startsWith("~/"))return null;const o=i.lastIndexOf("/");return{dir:i.slice(0,o)||"/",sessionId:t}},_updateFolderPreviewNav(e){const t=!!this.folderGrid&&this.folderGrid.index!==null&&this.folderGrid.files.length>1,s=this.$("filePreviewPrevBtn"),n=this.$("filePreviewNextBtn");s&&(s.hidden=!t),n&&(n.hidden=!t),e!==void 0&&(this.filePreviewFolderTarget=e);const i=!!this.folderGrid&&this.folderGrid.index!==null,o=this.$("filePreviewFolderBtn");o&&(o.hidden=i||!this.filePreviewFolderTarget)},_bindFolderGridKeys(){this._folderGridKeysBound||(this._folderGridKeysBound=!0,document.addEventListener("keydown",e=>{const t=this.folderGrid;if(!t||e.altKey||e.ctrlKey||e.metaKey)return;const s=this.$("filePreviewOverlay")?.classList.contains("visible");if(!this.$("folderGridOverlay")?.classList.contains("visible"))return;const i=e.target;if(i&&(i.isContentEditable||/^(INPUT|TEXTAREA|SELECT)$/.test(i.tagName)&&!i.classList?.contains("xterm-helper-textarea"))||this.filePreviewEdit)return;let l=!0;s&&t.index!==null&&e.key==="ArrowLeft"?this.stepFolderPreview(-1):s&&t.index!==null&&e.key==="ArrowRight"?this.stepFolderPreview(1):!s&&(e.key==="ArrowLeft"||e.key==="ArrowRight")&&t.files.length?this._openFolderGridFile(t.lastIndex??0):e.key==="Escape"?s?this.closeFilePreview():this.closeFolderGrid():l=!1,l&&(e.preventDefault(),e.stopPropagation())},!0))},closeFilePreview(){if(this.filePreviewEdit?.dirty&&!confirm("Discard unsaved changes?"))return;this._resetFilePreviewEdit(),this.folderGrid&&(this.folderGrid.index=null),this._updateFolderPreviewNav(null);const e=this.$("filePreviewOverlay");e&&e.classList.remove("visible"),this._stopFilePreviewMedia(),this.filePreviewContent="",this.filePreviewText=null,this._updateFilePreviewToolbar("none"),this.filePreviewDetachUrl="";const t=this.$("filePreviewDetachBtn");t&&(t.hidden=!0)},detachFilePreview(){if(!this.filePreviewDetachUrl)return;const e=this.openInHostWindow?.(this.filePreviewDetachUrl)??null;if(e!==null){e?this.closeFilePreview():this.showToast("Could not open a new window for this preview","error");return}const t=window.open(this.filePreviewDetachUrl,"_blank");if(!t){this.showToast("Pop-up blocked: allow pop-ups for this site to detach previews","error");return}t.opener=null,this.closeFilePreview()},_stopFilePreviewMedia(){this._disposeSpreadsheetPreview();const e=this.$("filePreviewBody");if(e){for(const t of e.querySelectorAll("video, audio"))try{t.pause(),t.removeAttribute("src"),t.load()}catch(s){console.warn("Failed to stop preview media:",s)}e.innerHTML=""}},_openSpreadsheetPreview(e,t,s){this._disposeSpreadsheetPreview();const n=window.CodemanSpreadsheetPreview;if(!n?.open){e.innerHTML='<div class="binary-message">Spreadsheet preview is unavailable.</div>';return}e.textContent="";const i={};this._spreadsheetPreviewToken=i,this._spreadsheetPreview=n.open({container:e,url:t,size:s,isCurrent:()=>this._spreadsheetPreviewToken===i})},_disposeSpreadsheetPreview(){const e=this._spreadsheetPreview;this._spreadsheetPreview=null,this._spreadsheetPreviewToken=null;try{e?.dispose()}catch(t){console.warn("Failed to dispose spreadsheet preview:",t)}},_filePreviewPref(e){try{const t=localStorage.getItem(FILE_PREVIEW_PREF_KEYS[e]);if(t==="1")return!0;if(t==="0")return!1}catch{}return FILE_PREVIEW_PREF_DEFAULTS[e]},_setFilePreviewPref(e,t){try{localStorage.setItem(FILE_PREVIEW_PREF_KEYS[e],t?"1":"0")}catch{}},_renderFilePreviewText(){const e=this.filePreviewText,t=this.$("filePreviewBody");if(!e||!t)return;const n=MARKDOWN_EXTS.has(e.ext)&&this._filePreviewPref("mdRendered");if(n){const i=document.createElement("template");i.innerHTML=`<div class="rv-text file-preview-md" data-i18n-skip>${this._renderMarkdown(this.filePreviewContent,{breaks:!1})}</div>`;const o=i.content.firstElementChild;this._rebaseFilePreviewMarkdownRefs(o,e),this._linkifyFilePaths(o);for(const l of o.querySelectorAll("a.rv-path:not([data-session-id])"))l.dataset.sessionId=e.sessionId;t.replaceChildren(i.content),this._bindResponseViewerInteractions(t)}else{const i=document.createElement("pre");i.className="file-preview-text",i.classList.toggle("wrap",this._filePreviewPref("wrap")),i.classList.toggle("show-lines",this._filePreviewPref("lineNumbers"));const o=document.createElement("code");o.innerHTML=this.filePreviewContent.split(`
245
+ `}).join("")}n.querySelectorAll(".file-tree-item").forEach(a=>{a.addEventListener("click",()=>{const r=a.dataset.path;a.dataset.type==="directory"?this._openFileBrowserSearchDirectory({...o,path:r}):this.openFilePreview(r,t)})});const l=this.$("fileBrowserStatus");if(l){const a=s.matchCount===void 0?e.length:s.matchCount;l.textContent=`${a} ${a===1?"match":"matches"}${s.truncated?" (truncated)":""}`}},_findFileBrowserDirectory(e,t,s=[]){if(!Array.isArray(e))return null;for(const n of e){if(!n||typeof n!="object")continue;if(n.type==="directory"&&n.path===t)return{target:n,ancestors:[...s]};if(n.type!=="directory"||!Array.isArray(n.children))continue;const i=this._findFileBrowserDirectory(n.children,t,[...s,n.path]);if(i)return i}return null},_isFileBrowserDirectoryContextCurrent(e){const t=this._ensureFileBrowserState(),s=this.$?.("fileBrowserSearch"),n=typeof s?.value=="string"?s.value:t.filter;return e&&t.ownerSessionId===e.ownerSessionId&&this.activeSessionId===e.ownerSessionId&&t.treeEpoch===e.treeEpoch&&t.searchEpoch===e.searchEpoch&&this.fileBrowserShowHidden===!0===e.showHidden&&t.filter===e.rawInput&&n===e.rawInput&&n.trim()===e.query&&t.view===e.view&&this.$?.("fileBrowserPanel")?.classList.contains("visible")===!0},_promptFileBrowserDirectoryReload(){this.showToast?.("Reload files before opening this folder","info")},_openFileBrowserSearchDirectory(e){if(!this._isFileBrowserDirectoryContextCurrent(e))return;const t=this._ensureFileBrowserState(),s=t.normalState;if(!this._isFileBrowserNormalCompatible(s,e.ownerSessionId,e.showHidden,e.treeEpoch)){t.deferredDirectoryTarget=null,this._promptFileBrowserDirectoryReload();return}if(s.phase==="loading"){t.deferredDirectoryTarget={...e};return}if(t.deferredDirectoryTarget=null,s.phase!=="ready"){this._promptFileBrowserDirectoryReload();return}const n=this._findFileBrowserDirectory(s.data?.tree,e.path);if(!n){this._promptFileBrowserDirectoryReload();return}this._leaveFileBrowserSearchForDirectory([...n.ancestors,n.target.path],s)},_completeDeferredFileBrowserDirectory(e){const t=this._ensureFileBrowserState(),s=t.deferredDirectoryTarget;if(!s)return!1;if(!this._isFileBrowserDirectoryContextCurrent(s))return t.deferredDirectoryTarget===s&&(t.deferredDirectoryTarget=null),!1;if(!this._isFileBrowserNormalCompatible(e,s.ownerSessionId,s.showHidden,s.treeEpoch)||e.phase!=="ready"&&e.phase!=="error")return!1;if(t.deferredDirectoryTarget=null,e.phase==="error")return this._promptFileBrowserDirectoryReload(),!1;const n=this._findFileBrowserDirectory(e.data?.tree,s.path);return n?(this._leaveFileBrowserSearchForDirectory([...n.ancestors,n.target.path],e),!0):(this._promptFileBrowserDirectoryReload(),!1)},_leaveFileBrowserSearchForDirectory(e,t){const s=this._ensureFileBrowserState();s.inFlight?.timer!==void 0&&s.inFlight?.timer!==null&&clearTimeout(s.inFlight.timer),s.searchEpoch++,s.inFlight=null,s.filter="",s.matches=[],s.deferredDirectoryTarget=null,s.view="normal",this.fileBrowserFilter="";const n=this.$?.("fileBrowserSearch");n&&(n.value=""),this._syncFileBrowserExpandBtn();for(const i of e)typeof i=="string"&&this.fileBrowserExpandedDirs?.add?.(i);this.fileBrowserData=t.data,this._renderFileBrowserNormalState(t)},expandAllDirectories(e){for(const t of e)t.type==="directory"&&(this.fileBrowserExpandedDirs.add(t.path),t.children&&this.expandAllDirectories(t.children))},collapseAllDirectories(){this.fileBrowserExpandedDirs.clear()},toggleFileBrowserExpand(){if(this._hasFileBrowserQuery()){this._syncFileBrowserExpandBtn();return}this.fileBrowserAllExpanded=!this.fileBrowserAllExpanded;const e=this.$("fileBrowserExpandBtn");this.fileBrowserAllExpanded?(this.expandAllDirectories(this.fileBrowserData?.tree||[]),e&&(e.innerHTML="\u229F")):(this.collapseAllDirectories(),e&&(e.innerHTML="\u229E")),this.renderFileBrowserTree()},refreshFileBrowser(){const e=this._ensureFileBrowserState();e.inFlight?.timer!==void 0&&e.inFlight?.timer!==null&&clearTimeout(e.inFlight.timer),e.inFlight=null,e.searchEpoch++,e.filter="",e.matches=[],e.deferredDirectoryTarget=null,e.view="normal",this.fileBrowserFilter="",this.fileBrowserExpandedDirs.clear(),this.fileBrowserAllExpanded=!1;const t=this.$("fileBrowserExpandBtn");t&&(t.innerHTML="\u229E");const s=this.$("fileBrowserSearch");s&&(s.value=""),this._syncFileBrowserExpandBtn();const n=e.ownerSessionId||this.activeSessionId;if(!(!n||this.activeSessionId!==n))return this.loadFileBrowser(n,{force:!0})},toggleFileBrowserButton(){const t=this.$("fileBrowserPanel")?.classList.contains("visible"),s=document.querySelector(".btn-file-viewer");if(t){this.closeFileBrowserPanel(),s&&s.setAttribute("aria-expanded","false");return}if(!this.activeSessionId){this.showToast("Open a session to browse its files","info");return}const n=this.loadAppSettingsFromStorage();n.showFileBrowser=!0,this.saveAppSettingsToStorage(n);const i=document.getElementById("appSettingsShowFileBrowser");i&&(i.checked=!0),this.applyMonitorVisibility(),s&&s.setAttribute("aria-expanded","true")},closeFileBrowserPanel(){const e=this.$("fileBrowserPanel");if(this._resetFileBrowserForHide(),e&&(e.classList.remove("visible"),e.style.left="",e.style.top="",e.style.bottom="",e.style.right=""),this.fileBrowserDragListeners){const i=this.fileBrowserDragListeners;document.removeEventListener("mousemove",i.move),document.removeEventListener("mouseup",i.up),document.removeEventListener("touchmove",i.touchMove),document.removeEventListener("touchend",i.up),document.removeEventListener("touchcancel",i.up),i.handle&&(i.handle.removeEventListener("mousedown",i.handleMouseDown),i.handle.removeEventListener("touchstart",i.handleTouchStart),i._onFirstDrag&&(i.handle.removeEventListener("mousedown",i._onFirstDrag),i.handle.removeEventListener("touchstart",i._onFirstDrag))),this.fileBrowserDragListeners=null}const t=this.loadAppSettingsFromStorage();t.showFileBrowser=!1,this.saveAppSettingsToStorage(t);const s=document.getElementById("appSettingsShowFileBrowser");s&&(s.checked=!1);const n=document.querySelector(".btn-file-viewer");n&&n.setAttribute("aria-expanded","false")},_isExternalPreviewPath(e,t){if(typeof e=="string"&&e.startsWith("~/"))return!0;if(typeof e!="string"||!e.startsWith("/"))return!1;const s=this.sessions.get(t)?.workingDir;if(!s)return!1;const n=s.endsWith("/")?s:`${s}/`;return e!==s&&!e.startsWith(n)},async _registerExternalPreview(e,t){try{const s=await fetch(`/api/sessions/${t}/attachments`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e,notify:!1})}),n=await s.json().catch(()=>null);if(s.ok&&n?.success&&n.data?.attachmentId)return{attachmentId:n.data.attachmentId,size:n.data.size||0};const i=n?.error||`Cannot open this file (HTTP ${s.status})`;return/unsupported/i.test(i)?{error:`Cannot preview .${(e.split(".").pop()||"").toLowerCase()} from outside the session workspace (images, video, audio, PDF, Office documents and text files only).`}:{error:i}}catch(s){return{error:s.message||"Cannot open this file"}}},async openFilePreview(e,t=this.activeSessionId,s=null,n={}){if(!t||!e)return;const i=n.folderFile||null;!i&&this.folderGrid&&(this.folderGrid.index=null),this._updateFolderPreviewNav(i?null:this._previewFolderPath(e,t,s));const o=this.$("filePreviewOverlay"),l=this.$("filePreviewTitle"),a=this.$("filePreviewBody"),r=this.$("filePreviewFooter");if(!o||!a)return;this._recordFilePreviewHistory(e,t,s,n),this._bindFilePreviewChrome();const c=this._filePreviewLoad=(this._filePreviewLoad||0)+1,h=()=>c!==this._filePreviewLoad;this._resetFilePreviewEdit(),this._stopFilePreviewMedia(),this.filePreviewDetachUrl="";const d=this.$("filePreviewDetachBtn");d&&(d.hidden=!0),this.filePreviewText=null,this.filePreviewPage=null,this.filePreviewPageRefused=!1,this._updateFilePreviewToolbar("none"),o.classList.add("visible"),this._applyFilePreviewExpanded(),l.textContent=e,a.innerHTML='<div class="binary-message">Loading...</div>',r.textContent="";const u=(e.split(".").pop()||"").toLowerCase();if(!s&&rendersAsPage(e)&&this._filePreviewPref("htmlRendered")){const g=await this._mintHtmlViewUrl(e,t);if(g){r.textContent="HTML",this.filePreviewPage={filePath:e,sessionId:t},this.filePreviewDetachUrl=g,d&&(d.hidden=!1),a.innerHTML=`<iframe src="${escapeHtml(g)}" title="${escapeHtml(e)}" sandbox="allow-scripts allow-forms allow-popups allow-modals allow-downloads"></iframe>`,this._updateFilePreviewToolbar("page");return}this.filePreviewPageRefused=!0}let p="",f=0;if(!s&&!i&&this._isExternalPreviewPath(e,t)){const g=await this._registerExternalPreview(e,t);if(h())return;s=g.attachmentId||null,p=g.error||"",f=g.size||0}if(!s&&p){r.textContent="",a.innerHTML=`<div class="binary-message">${escapeHtml(p)}</div>`;return}const w=u==="docx"||u==="pptx",y=s?`/api/sessions/${t}/attachments/${encodeURIComponent(s)}`:i?`/api/sessions/${t}/folders/${encodeURIComponent(i.folderId)}/files/${encodeURIComponent(i.name)}`:null;if(this.filePreviewDetachUrl=CodemanBase.url(y?`${y}/${w?"preview":"raw"}`:w?`/api/sessions/${t}/file-preview?path=${encodeURIComponent(e)}`:`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}`),d&&(d.hidden=!1),y){const g=CodemanBase.url(y),C=new Set(["png","jpg","jpeg","gif","webp","bmp","svg"]),m=new Set(["mp4","webm","mov","m4v","ogv"]),S=new Set(["mp3","wav","ogg","oga","m4a","aac","flac","opus"]);if(i&&!f&&(f=n.size||0),r.textContent=f?`${this.formatFileSize(f)} \u2022 ${u}`:u.toUpperCase(),C.has(u))a.innerHTML=`<img src="${escapeHtml(`${g}/raw`)}" alt="${escapeHtml(e)}">`;else if(m.has(u))a.innerHTML=`<video src="${escapeHtml(`${g}/raw`)}" controls autoplay playsinline preload="metadata"></video>`;else if(S.has(u))a.innerHTML=`<audio src="${escapeHtml(`${g}/raw`)}" controls autoplay preload="metadata"></audio>`;else if(u==="pdf")a.innerHTML=`<iframe src="${escapeHtml(`${g}/raw`)}" title="${escapeHtml(e)}"></iframe>`;else if(u==="docx"||u==="pptx")a.innerHTML=`<iframe src="${escapeHtml(`${g}/preview`)}" title="${escapeHtml(e)}"></iframe>`;else if(u==="xlsx")this._openSpreadsheetPreview(a,`${g}/raw`,f);else try{const $=await fetch(`${g}/raw`,{headers:{Range:"bytes=0-524287"}});if(!$.ok)throw new Error("Failed to load attachment");const b=await $.text();if(h())return;const T=$.status===206&&b.length>=524288,E=b.split(`
246
+ `),I=MARKDOWN_EXTS.has(u)?1/0:500,P=E.length>I,B=P?E.slice(0,I).join(`
247
+ `):b;if(this.filePreviewContent=B,this.filePreviewText={ext:u,sessionId:t,filePath:e,attachmentId:s||i?.folderId},this._renderFilePreviewText(),P||T){const x=P?`showing first ${I} lines`:"showing the start of the file";r.textContent=`${r.textContent} (${x})`}}catch($){if(h())return;a.innerHTML=`<div class="binary-message">Error: ${escapeHtml($.message)}</div>`}return}if(u==="docx"||u==="pptx"){r.textContent=u.toUpperCase();const g=CodemanBase.url(`/api/sessions/${t}/file-preview?path=${encodeURIComponent(e)}`);a.innerHTML=`<iframe src="${escapeHtml(g)}" title="${escapeHtml(e)}"></iframe>`;return}if(u==="pdf"){r.textContent="PDF";const g=CodemanBase.url(`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}`);a.innerHTML=`<iframe src="${escapeHtml(g)}" title="${escapeHtml(e)}"></iframe>`;return}if(u==="svg"){r.textContent="SVG";try{const g=await fetch(`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}`);if(!g.ok)throw new Error("Failed to load image");const C=await g.text();if(h())return;const m=URL.createObjectURL(new Blob([C],{type:"image/svg+xml"}));a.innerHTML=`<img src="${m}" alt="${escapeHtml(e)}">`;const S=a.querySelector("img");S&&(S.onload=()=>URL.revokeObjectURL(m))}catch(g){if(h())return;a.innerHTML=`<div class="binary-message">Error: ${escapeHtml(g.message)}</div>`}return}const v=MARKDOWN_EXTS.has(u)?1e4:500;try{const g=await fetch(`/api/sessions/${t}/file-content?path=${encodeURIComponent(e)}&lines=${v}`);if(!g.ok)throw new Error("Failed to load file");const C=await g.json();if(h())return;if(!C.success)throw new Error(C.error||"Failed to load file");const m=C.data;if(m.type==="image")a.innerHTML=`<img src="${escapeHtml(CodemanBase.url(m.url))}" alt="${escapeHtml(e)}">`,r.textContent=`${this.formatFileSize(m.size)} \u2022 ${m.extension}`;else if(m.type==="video")a.innerHTML=`<video src="${escapeHtml(CodemanBase.url(m.url))}" controls autoplay playsinline preload="metadata"></video>`,r.textContent=`${this.formatFileSize(m.size)} \u2022 ${m.extension}`;else if(m.type==="audio")a.innerHTML=`<audio src="${escapeHtml(CodemanBase.url(m.url))}" controls autoplay preload="metadata"></audio>`,r.textContent=`${this.formatFileSize(m.size)} \u2022 ${m.extension}`;else if(m.type==="spreadsheet")this._openSpreadsheetPreview(a,CodemanBase.url(m.url),m.size),r.textContent=`${this.formatFileSize(m.size)} \u2022 ${m.extension}`;else if(m.type==="binary"){const S=CodemanBase.url(`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}&download=true`);a.innerHTML=`<div class="binary-message">Binary file (${this.formatFileSize(m.size)})<br>Cannot preview<br><a href="${escapeHtml(S)}" download>Download</a></div>`,r.textContent=m.extension||"binary"}else{this.filePreviewContent=m.content,this.filePreviewText={ext:u,sessionId:t,filePath:e},this._renderFilePreviewText();const S=m.truncated?` (showing ${v}/${m.totalLines} lines)`:"";if(r.textContent=`${m.totalLines} lines \u2022 ${this.formatFileSize(m.size)}${S}`,m.editable){this.filePreviewEditTarget={sessionId:t,filePath:e};const $=this.$("filePreviewEditBtn");$&&($.hidden=!1)}}}catch(g){if(h())return;console.error("Failed to preview file:",g),a.innerHTML=`<div class="binary-message">Error: ${escapeHtml(g.message)}</div>`}},async openFolderGrid(e,t=this.activeSessionId){if(!t||!e)return;const s=this.$("folderGridOverlay"),n=this.$("folderGridBody");if(!s||!n)return;this._bindFolderGridKeys();const i=this._folderGridLoad=(this._folderGridLoad||0)+1;let o=null,l=0;try{const a=await fetch(`/api/sessions/${t}/folders`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e})});l=a.status,o=await a.json().catch(()=>null)}catch(a){if(i!==this._folderGridLoad)return;this.showToast(`Cannot open folder: ${a.message||a}`,"error");return}if(i===this._folderGridLoad){if(!o?.success||!o.data){const a=o?.error||`HTTP ${l}`;if(l===400&&/not a folder/i.test(a)){this.openFilePreview(e,t);return}this.showToast(`Cannot open folder ${e}: ${a}`,"error");return}this.folderGrid={sessionId:t,...o.data,index:null},this._renderFolderGrid(),s.classList.add("visible"),n.scrollTop=0}},closeFolderGrid(){this._folderGridLoad=(this._folderGridLoad||0)+1,this.$("folderGridOverlay")?.classList.remove("visible");const e=this.$("folderGridBody");e&&(e.innerHTML=""),this.folderGrid=null,this._updateFolderPreviewNav(null)},folderGridUp(){const e=this.folderGrid;!e||e.path==="/"||this.openFolderGrid(e.path.slice(0,e.path.lastIndexOf("/"))||"/",e.sessionId)},_renderFolderGrid(){const e=this.folderGrid;if(!e)return;const t=this.$("folderGridTitle"),s=this.$("folderGridFolders"),n=this.$("folderGridBody"),i=this.$("folderGridFooter");t.textContent=e.path,t.title=e.path;const o=this.$("folderGridUpBtn");o&&(o.disabled=e.path==="/"),s.innerHTML="";for(const r of e.folders){const c=document.createElement("button");c.type="button",c.className="folder-grid-chip",c.textContent=`${r}/`,c.onclick=()=>this.openFolderGrid(`${e.path==="/"?"":e.path}/${r}`,e.sessionId),s.appendChild(c)}if(n.innerHTML="",e.files.length===0){const r=document.createElement("div");r.className="folder-grid-empty",r.textContent="No previewable files in this folder.",n.appendChild(r)}e.files.forEach((r,c)=>{const h=document.createElement("button");h.type="button",h.className="folder-grid-tile",h.title=`${r.name} \u2022 ${this.formatFileSize(r.size)}`,h.dataset.index=String(c);const d=document.createElement("div");d.className="folder-grid-thumb";const u=r.extension.toUpperCase(),p=this._folderFileUrl(e,r.name,""),f=r.attachmentType==="image"?`${p}/raw`:["pdf","docx","pptx"].includes(r.extension)?`${p}/thumbnail`:null;if(f){const y=document.createElement("img");y.loading="lazy",y.decoding="async",y.alt=r.name,y.src=f,y.onerror=()=>{d.textContent=u},d.appendChild(y)}else d.textContent=u;const w=document.createElement("span");w.className="folder-grid-name",w.textContent=r.name,h.append(d,w),h.onclick=()=>this._openFolderGridFile(c),n.appendChild(h)});const l=`${e.files.length} file${e.files.length===1?"":"s"}`,a=e.folders.length?` \u2022 ${e.folders.length} folder${e.folders.length===1?"":"s"}`:"";i.textContent=`${l}${a}${e.truncated?" (folder too large \u2014 showing the first entries)":""}`},_folderFileUrl(e,t,s){return CodemanBase.url(`/api/sessions/${e.sessionId}/folders/${encodeURIComponent(e.folderId)}/files/${encodeURIComponent(t)}${s}`)},_openFolderGridFile(e){const t=this.folderGrid,s=t?.files[e];if(!s)return;const n=this.$("folderGridBody");n?.querySelectorAll(".folder-grid-tile.current").forEach(o=>o.classList.remove("current"));const i=n?.querySelector(`.folder-grid-tile[data-index="${e}"]`);i?.classList.add("current"),i?.scrollIntoView({block:"nearest"}),this.openFilePreview(`${t.path==="/"?"":t.path}/${s.name}`,t.sessionId,null,{folderFile:{folderId:t.folderId,name:s.name},size:s.size}),t.index=e,t.lastIndex=e,this._updateFolderPreviewNav(null)},stepFolderPreview(e){const t=this.folderGrid;if(!t||t.index===null||t.files.length===0||this.filePreviewEdit?.dirty&&!confirm("Discard unsaved changes?"))return;const s=(t.index+e+t.files.length)%t.files.length;this._openFolderGridFile(s)},_recordFilePreviewHistory(e,t,s,n){const i=this.filePreviewHistory=this.filePreviewHistory||{entries:[],index:-1};if(!this._filePreviewHistoryStepping){const o=i.entries[i.index];o&&o.filePath===e&&o.sessionId===t&&(o.attachmentId||null)===(s||null)||(i.entries.length=i.index+1,i.entries.push({filePath:e,sessionId:t,attachmentId:s||null,options:n}),i.entries.length>FILE_PREVIEW_HISTORY_MAX&&i.entries.shift(),i.index=i.entries.length-1)}this._updateFilePreviewHistoryNav()},stepFilePreviewHistory(e){const t=this.filePreviewHistory;if(!t)return;const s=t.index+e;if(s<0||s>=t.entries.length||this.filePreviewEdit?.dirty&&!confirm("Discard unsaved changes?"))return;t.index=s;const n=t.entries[s];this._filePreviewHistoryStepping=!0;try{const i=n.options?.folderFile;if(i&&i.folderId===this.folderGrid?.folderId){const o=this.folderGrid.files.findIndex(l=>l.name===i.name);if(o!==-1)return this._openFolderGridFile(o)}return this.openFilePreview(n.filePath,n.sessionId,n.attachmentId,n.options||{})}finally{this._filePreviewHistoryStepping=!1}},_updateFilePreviewHistoryNav(){const e=this.filePreviewHistory,t=!!e&&e.entries.length>1,s=this.$("filePreviewBackBtn"),n=this.$("filePreviewForwardBtn");s&&(s.hidden=!t,s.disabled=!t||e.index<=0),n&&(n.hidden=!t,n.disabled=!t||e.index>=e.entries.length-1)},toggleFilePreviewExpanded(){this._setFilePreviewPref("expanded",!this._filePreviewPref("expanded")),this._applyFilePreviewExpanded()},_applyFilePreviewExpanded(){const e=this._filePreviewPref("expanded");this.$("filePreviewOverlay")?.querySelector?.(".file-preview-window")?.classList?.toggle("expanded",e),this.$("filePreviewExpandBtn")?.setAttribute("aria-pressed",e?"true":"false")},_bindFilePreviewChrome(){this._filePreviewChromeBound||(this._filePreviewChromeBound=!0,document.addEventListener("keydown",e=>{if(!e.altKey||e.ctrlKey||e.metaKey||e.shiftKey||e.key!=="ArrowLeft"&&e.key!=="ArrowRight"||!this.$("filePreviewOverlay")?.classList.contains("visible"))return;const t=e.target;if(t&&(t.isContentEditable||/^(INPUT|TEXTAREA|SELECT)$/.test(t.tagName)&&!t.classList?.contains("xterm-helper-textarea")))return;e.preventDefault(),e.stopPropagation();const s=this.filePreviewHistory,n=e.key==="ArrowLeft"?-1:1;!s||s.index+n<0||s.index+n>=s.entries.length||this.stepFilePreviewHistory(n)},!0),this._bindFilePreviewResize())},_bindFilePreviewResize(){const e=this.$("filePreviewResize"),t=e?.parentElement;!e||!t||e.addEventListener("pointerdown",s=>{if(s.button!==0)return;s.preventDefault();const n=s.clientX,i=s.clientY,o=t.offsetWidth,l=t.offsetHeight;e.setPointerCapture?.(s.pointerId);const a=c=>{const h=Math.max(320,Math.min(window.innerWidth*.96,o+2*(c.clientX-n))),d=Math.max(240,Math.min(window.innerHeight*.94,l+2*(c.clientY-i)));t.style.width=`${Math.round(h)}px`,t.style.height=`${Math.round(d)}px`},r=()=>{e.removeEventListener("pointermove",a),e.removeEventListener("pointerup",r),e.removeEventListener("pointercancel",r)};e.addEventListener("pointermove",a),e.addEventListener("pointerup",r),e.addEventListener("pointercancel",r)})},openFolderOfPreview(){const e=this.filePreviewFolderTarget;e&&(this.closeFilePreview(),this.openFolderGrid(e.dir,e.sessionId))},_previewFolderPath(e,t,s){if(typeof e!="string"||s&&!e.includes("/"))return null;const n=this.sessions?.get?.(t)?.workingDir,i=typeof resolveLinkedFilePath=="function"?resolveLinkedFilePath(e,n):e;if(!i.startsWith("/")&&!i.startsWith("~/"))return null;const o=i.lastIndexOf("/");return{dir:i.slice(0,o)||"/",sessionId:t}},_updateFolderPreviewNav(e){const t=!!this.folderGrid&&this.folderGrid.index!==null&&this.folderGrid.files.length>1,s=this.$("filePreviewPrevBtn"),n=this.$("filePreviewNextBtn");s&&(s.hidden=!t),n&&(n.hidden=!t),e!==void 0&&(this.filePreviewFolderTarget=e);const i=!!this.folderGrid&&this.folderGrid.index!==null,o=this.$("filePreviewFolderBtn");o&&(o.hidden=i||!this.filePreviewFolderTarget)},_bindFolderGridKeys(){this._folderGridKeysBound||(this._folderGridKeysBound=!0,document.addEventListener("keydown",e=>{const t=this.folderGrid;if(!t||e.altKey||e.ctrlKey||e.metaKey)return;const s=this.$("filePreviewOverlay")?.classList.contains("visible");if(!this.$("folderGridOverlay")?.classList.contains("visible"))return;const i=e.target;if(i&&(i.isContentEditable||/^(INPUT|TEXTAREA|SELECT)$/.test(i.tagName)&&!i.classList?.contains("xterm-helper-textarea"))||this.filePreviewEdit)return;let l=!0;s&&t.index!==null&&e.key==="ArrowLeft"?this.stepFolderPreview(-1):s&&t.index!==null&&e.key==="ArrowRight"?this.stepFolderPreview(1):!s&&(e.key==="ArrowLeft"||e.key==="ArrowRight")&&t.files.length?this._openFolderGridFile(t.lastIndex??0):e.key==="Escape"?s?this.closeFilePreview():this.closeFolderGrid():l=!1,l&&(e.preventDefault(),e.stopPropagation())},!0))},closeFilePreview(){if(this.filePreviewEdit?.dirty&&!confirm("Discard unsaved changes?"))return;this._resetFilePreviewEdit(),this.folderGrid&&(this.folderGrid.index=null),this._updateFolderPreviewNav(null),this.filePreviewHistory=null,this._updateFilePreviewHistoryNav();const e=this.$("filePreviewOverlay");e&&e.classList.remove("visible"),this._stopFilePreviewMedia(),this.filePreviewContent="",this.filePreviewText=null,this._updateFilePreviewToolbar("none"),this.filePreviewDetachUrl="";const t=this.$("filePreviewDetachBtn");t&&(t.hidden=!0)},detachFilePreview(){if(!this.filePreviewDetachUrl)return;const e=this.openInHostWindow?.(this.filePreviewDetachUrl)??null;if(e!==null){e?this.closeFilePreview():this.showToast("Could not open a new window for this preview","error");return}const t=window.open(this.filePreviewDetachUrl,"_blank");if(!t){this.showToast("Pop-up blocked: allow pop-ups for this site to detach previews","error");return}t.opener=null,this.closeFilePreview()},_stopFilePreviewMedia(){this._disposeSpreadsheetPreview();const e=this.$("filePreviewBody");if(e){for(const t of e.querySelectorAll("video, audio"))try{t.pause(),t.removeAttribute("src"),t.load()}catch(s){console.warn("Failed to stop preview media:",s)}e.innerHTML=""}},_openSpreadsheetPreview(e,t,s){this._disposeSpreadsheetPreview();const n=window.CodemanSpreadsheetPreview;if(!n?.open){e.innerHTML='<div class="binary-message">Spreadsheet preview is unavailable.</div>';return}e.textContent="";const i={};this._spreadsheetPreviewToken=i,this._spreadsheetPreview=n.open({container:e,url:t,size:s,isCurrent:()=>this._spreadsheetPreviewToken===i})},_disposeSpreadsheetPreview(){const e=this._spreadsheetPreview;this._spreadsheetPreview=null,this._spreadsheetPreviewToken=null;try{e?.dispose()}catch(t){console.warn("Failed to dispose spreadsheet preview:",t)}},_filePreviewPref(e){try{const t=localStorage.getItem(FILE_PREVIEW_PREF_KEYS[e]);if(t==="1")return!0;if(t==="0")return!1}catch{}return FILE_PREVIEW_PREF_DEFAULTS[e]},_setFilePreviewPref(e,t){try{localStorage.setItem(FILE_PREVIEW_PREF_KEYS[e],t?"1":"0")}catch{}},_renderFilePreviewText(){const e=this.filePreviewText,t=this.$("filePreviewBody");if(!e||!t)return;const n=MARKDOWN_EXTS.has(e.ext)&&this._filePreviewPref("mdRendered");if(n){const i=document.createElement("template");i.innerHTML=`<div class="rv-text file-preview-md" data-i18n-skip>${this._renderMarkdown(this.filePreviewContent,{breaks:!1})}</div>`;const o=i.content.firstElementChild;this._rebaseFilePreviewMarkdownRefs(o,e),this._linkifyFilePaths(o);for(const l of o.querySelectorAll("a.rv-path:not([data-session-id])"))l.dataset.sessionId=e.sessionId;t.replaceChildren(i.content),this._bindResponseViewerInteractions(t)}else{const i=document.createElement("pre");i.className="file-preview-text",i.classList.toggle("wrap",this._filePreviewPref("wrap")),i.classList.toggle("show-lines",this._filePreviewPref("lineNumbers"));const o=document.createElement("code");o.innerHTML=this.filePreviewContent.split(`
242
248
  `).map(l=>`<span class="fp-line">${escapeHtml(l)}</span>`).join(`
243
249
  `),i.appendChild(o),t.replaceChildren(i)}this._updateFilePreviewToolbar(n?"markdown":"text")},_rebaseFilePreviewMarkdownRefs(e,{sessionId:t,filePath:s,attachmentId:n}){const i=s.includes("/")?s.slice(0,s.lastIndexOf("/")+1):"",o=!!n&&!s.startsWith("/"),l=r=>!!r&&!/^[a-z][a-z0-9+.-]*:/i.test(r)&&!r.startsWith("//")&&!r.startsWith("#"),a=r=>{let c=r.split("#")[0].split("?")[0];try{c=decodeURIComponent(c)}catch{}const h=[];for(const d of(c.startsWith("/")?c.slice(1):i+c).split("/"))d==="."||d===""&&h.length||(d===".."&&h.length&&h[h.length-1]!==".."&&h[h.length-1]!==""?h.pop():h.push(d));return h.join("/")};for(const r of e.querySelectorAll("img[src]")){const c=r.getAttribute("src")||"";if(o&&l(c)){r.replaceWith(r.getAttribute("alt")||c);continue}if(l(c)){const h=a(c);r.setAttribute("src",CodemanBase.url(`/api/sessions/${t}/file-raw?path=${encodeURIComponent(h)}`))}r.addEventListener("error",()=>r.replaceWith(r.getAttribute("alt")||c),{once:!0})}for(const r of e.querySelectorAll("a[href]")){const c=r.getAttribute("href")||"";if(l(c)){if(o){r.replaceWith(...r.childNodes);continue}r.className="rv-path",r.dataset.path=a(c),r.dataset.sessionId=t,r.setAttribute("href","#"),r.removeAttribute("target"),r.removeAttribute("rel")}}},_updateFilePreviewToolbar(e){const t=(o,l,a)=>{const r=this.$(o);r&&(r.hidden=!l,l&&r.setAttribute("aria-pressed",String(a)))},s=e!=="none"&&MARKDOWN_EXTS.has(this.filePreviewText?.ext||"");t("filePreviewMdBtn",s,e==="markdown");const n=this.filePreviewText,i=e==="text"&&!this.filePreviewPageRefused&&rendersAsPage(n?.filePath)&&(!n.attachmentId||n.filePath.startsWith("/"));t("filePreviewPageBtn",e==="page"||i,e==="page"),t("filePreviewLinesBtn",e==="text",this._filePreviewPref("lineNumbers")),t("filePreviewWrapBtn",e==="text",this._filePreviewPref("wrap"))},async _mintHtmlViewUrl(e,t){try{const s=await fetch(`/api/sessions/${t}/html-view`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e})}),n=await s.json().catch(()=>({}));return s.ok&&n.success?CodemanBase.url(n.data.url):null}catch{return null}},toggleFilePreviewPage(){const e=this.filePreviewPage||this.filePreviewText;if(e)return this._setFilePreviewPref("htmlRendered",!this._filePreviewPref("htmlRendered")),this.openFilePreview(e.filePath,e.sessionId)},toggleFilePreviewMd(){this._setFilePreviewPref("mdRendered",!this._filePreviewPref("mdRendered")),this._renderFilePreviewText()},toggleFilePreviewLines(){this._toggleFilePreviewTextClass("lineNumbers","show-lines")},toggleFilePreviewWrap(){this._toggleFilePreviewTextClass("wrap","wrap")},_toggleFilePreviewTextClass(e,t){const s=!this._filePreviewPref(e);this._setFilePreviewPref(e,s);const n=this.$("filePreviewBody")?.querySelector(":scope > pre.file-preview-text");n&&n.classList.toggle(t,s),this._updateFilePreviewToolbar("text")},_resetFilePreviewEdit(){this.filePreviewEdit=null,this.filePreviewEditTarget=null;const e=this.$("filePreviewEditBtn");e&&(e.hidden=!0);const t=this.$("filePreviewEditBar");t&&(t.hidden=!0);const s=this.$("filePreviewDirty");s&&(s.hidden=!0);const n=this.$("filePreviewSaveBtn");n&&(n.disabled=!0,n.textContent="Save")},async enterFilePreviewEdit(){const e=this.filePreviewEditTarget;if(!e||this.filePreviewEdit)return;const t=this.$("filePreviewBody"),s=this.$("filePreviewFooter");if(!t)return;let n;try{const a=await fetch(`/api/sessions/${e.sessionId}/file-content?path=${encodeURIComponent(e.filePath)}&edit=1`),r=await a.json().catch(()=>null);if(!r||r.success!==!0)throw new Error(r?.error||`Failed to load file for editing (HTTP ${a.status})`);n=r.data}catch(a){this.showToast(a.message,"error");return}this.filePreviewEdit={sessionId:e.sessionId,filePath:e.filePath,baseHash:n.hash,eol:n.eol,original:n.content,dirty:!1,saving:!1};const i=document.createElement("textarea");i.className="file-preview-editor",i.spellcheck=!1,i.setAttribute("autocapitalize","off"),i.setAttribute("autocorrect","off"),i.setAttribute("autocomplete","off"),i.wrap="off",i.value=n.content,i.addEventListener("input",()=>this._onFilePreviewEditInput()),t.innerHTML="",t.appendChild(i),this._updateFilePreviewToolbar("none");const o=this.$("filePreviewEditBtn");o&&(o.hidden=!0);const l=this.$("filePreviewEditBar");if(l&&(l.hidden=!1),s){const a=n.eol==="crlf"?" \u2022 CRLF":"";s.textContent=`Editing \u2022 ${n.totalLines} lines \u2022 ${this.formatFileSize(n.size)}${a}`}},_onFilePreviewEditInput(){const e=this.filePreviewEdit;if(!e)return;const t=this.$("filePreviewBody")?.querySelector("textarea.file-preview-editor");if(!t)return;e.dirty=t.value!==e.original;const s=this.$("filePreviewDirty");s&&(s.hidden=!e.dirty);const n=this.$("filePreviewSaveBtn");n&&(n.disabled=!e.dirty||e.saving)},cancelFilePreviewEdit(){const e=this.filePreviewEdit;if(!e||e.dirty&&!confirm("Discard unsaved changes?"))return;const{sessionId:t,filePath:s}=e;this._resetFilePreviewEdit(),this.openFilePreview(s,t)},async saveFilePreviewEdit(e=!1){const t=this.filePreviewEdit;if(!t||t.saving)return;const s=this.$("filePreviewBody")?.querySelector("textarea.file-preview-editor");if(!s)return;t.saving=!0;const n=this.$("filePreviewSaveBtn");n&&(n.disabled=!0,n.textContent="Saving\u2026");const i=()=>{t.saving=!1,n&&(n.textContent="Save"),this._onFilePreviewEditInput()};let o=null,l=0;try{const c=await fetch(`/api/sessions/${t.sessionId}/file-content`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t.filePath,content:s.value,baseHash:t.baseHash,eol:t.eol??void 0,force:e||void 0})});l=c.status,o=await c.json().catch(()=>null)}catch(c){i(),this.showToast(`Save failed: ${c.message}`,"error");return}if(l===409||o?.errorCode==="CONFLICT"){i(),confirm(`File changed on disk since you loaded it.
244
- OK overwrites it with your version; Cancel keeps your draft open.`)&&this.saveFilePreviewEdit(!0);return}if(!o||o.success!==!0){i(),this.showToast(`Save failed: ${o?.error||`HTTP ${l}`}`,"error");return}const{sessionId:a,filePath:r}=t;this._resetFilePreviewEdit(),this.showToast("Saved","success"),this.openFilePreview(r,a)},_onAttachmentDetected(e){if(console.log("[Attachment Detected]",e),this.addAttachmentCard(e),e.sessionId){const t=this.attachmentHistoryCounts.get(e.sessionId)??this.sessions.get(e.sessionId)?.attachmentHistory?.length??0;this.attachmentHistoryCounts.set(e.sessionId,Math.min(t+1,100)),e.sessionId===this.activeSessionId&&(this.updateAttachmentHistoryBadge(),this.attachmentHistoryDrawerOpen&&this._debouncedCall("attachmentHistoryRefresh",()=>{this.attachmentHistoryDrawerOpen&&this.activeSessionId===e.sessionId&&this.loadAttachmentHistory(e.sessionId)},250))}},ensureAttachmentCardStack(){let e=this.attachmentCardStack||document.getElementById("attachmentCardStack");return e||(e=document.createElement("div"),e.id="attachmentCardStack",e.className="attachment-card-stack",document.body.appendChild(e)),this.attachmentCardStack=e,e},openAttachmentInNewTab(e,t,s=null){const n=CodemanBase.url(s?`/api/sessions/${e}/attachments/${encodeURIComponent(s)}/raw`:`/api/sessions/${e}/file-raw?path=${encodeURIComponent(t)}`);window.open(n,"_blank")},addAttachmentCard(e){const{sessionId:t,relativePath:s,fileName:n,timestamp:i,size:o,attachmentType:l,extension:a,attachmentId:r,rawUrl:c,previewUrl:h,thumbnailUrl:d}=e,u=s||n,p=r||`${t}-${i}-${n}`;if(this.attachmentCards.has(p)){this.attachmentCards.get(p).element.focus?.();return}if(this.attachmentCards.size>=10){const E=this.attachmentCards.keys().next().value;E&&this.closeAttachmentCard(E)}const w=this.ensureAttachmentCardStack(),v=this.sessions.get(t)?.name||t.substring(0,8),g=CodemanBase.url(c||(r?`/api/sessions/${t}/attachments/${encodeURIComponent(r)}/raw`:`/api/sessions/${t}/file-raw?path=${encodeURIComponent(u)}`)),T=CodemanBase.url(h||(r?`/api/sessions/${t}/attachments/${encodeURIComponent(r)}/preview`:null)),m=CodemanBase.url(d||(r?`/api/sessions/${t}/attachments/${encodeURIComponent(r)}/thumbnail`:`/api/sessions/${t}/file-thumbnail?path=${encodeURIComponent(u)}`)),S=r?`${g}?download=true`:`${g}&download=true`,$=(a||l||"file").toUpperCase(),b=document.createElement("article");b.className=`attachment-card attachment-${escapeHtml(l||"file")}`,b.tabIndex=0,b.dataset.attachmentId=p,b.dataset.previewUrl=T||"",b.innerHTML=`
250
+ OK overwrites it with your version; Cancel keeps your draft open.`)&&this.saveFilePreviewEdit(!0);return}if(!o||o.success!==!0){i(),this.showToast(`Save failed: ${o?.error||`HTTP ${l}`}`,"error");return}const{sessionId:a,filePath:r}=t;this._resetFilePreviewEdit(),this.showToast("Saved","success"),this.openFilePreview(r,a)},_onAttachmentDetected(e){if(console.log("[Attachment Detected]",e),this.addAttachmentCard(e),e.sessionId){const t=this.attachmentHistoryCounts.get(e.sessionId)??this.sessions.get(e.sessionId)?.attachmentHistory?.length??0;this.attachmentHistoryCounts.set(e.sessionId,Math.min(t+1,100)),e.sessionId===this.activeSessionId&&(this.updateAttachmentHistoryBadge(),this.attachmentHistoryDrawerOpen&&this._debouncedCall("attachmentHistoryRefresh",()=>{this.attachmentHistoryDrawerOpen&&this.activeSessionId===e.sessionId&&this.loadAttachmentHistory(e.sessionId)},250))}},ensureAttachmentCardStack(){let e=this.attachmentCardStack||document.getElementById("attachmentCardStack");return e||(e=document.createElement("div"),e.id="attachmentCardStack",e.className="attachment-card-stack",document.body.appendChild(e)),this.attachmentCardStack=e,e},openAttachmentInNewTab(e,t,s=null){const n=CodemanBase.url(s?`/api/sessions/${e}/attachments/${encodeURIComponent(s)}/raw`:`/api/sessions/${e}/file-raw?path=${encodeURIComponent(t)}`);window.open(n,"_blank")},addAttachmentCard(e){const{sessionId:t,relativePath:s,fileName:n,timestamp:i,size:o,attachmentType:l,extension:a,attachmentId:r,rawUrl:c,previewUrl:h,thumbnailUrl:d}=e,u=s||n,p=r||`${t}-${i}-${n}`;if(this.attachmentCards.has(p)){this.attachmentCards.get(p).element.focus?.();return}if(this.attachmentCards.size>=10){const E=this.attachmentCards.keys().next().value;E&&this.closeAttachmentCard(E)}const w=this.ensureAttachmentCardStack(),v=this.sessions.get(t)?.name||t.substring(0,8),g=CodemanBase.url(c||(r?`/api/sessions/${t}/attachments/${encodeURIComponent(r)}/raw`:`/api/sessions/${t}/file-raw?path=${encodeURIComponent(u)}`)),C=CodemanBase.url(h||(r?`/api/sessions/${t}/attachments/${encodeURIComponent(r)}/preview`:null)),m=CodemanBase.url(d||(r?`/api/sessions/${t}/attachments/${encodeURIComponent(r)}/thumbnail`:`/api/sessions/${t}/file-thumbnail?path=${encodeURIComponent(u)}`)),S=r?`${g}?download=true`:`${g}&download=true`,$=(a||l||"file").toUpperCase(),b=document.createElement("article");b.className=`attachment-card attachment-${escapeHtml(l||"file")}`,b.tabIndex=0,b.dataset.attachmentId=p,b.dataset.previewUrl=C||"",b.innerHTML=`
245
251
  <div class="attachment-thumbnail">
246
252
  ${m?`<img class="attachment-thumbnail-img" src="${escapeHtml(m)}" alt="">`:""}
247
253
  <div class="attachment-thumbnail-fallback ${m?"":"visible"}">${escapeHtml($)}</div>
@@ -259,7 +265,7 @@ OK overwrites it with your version; Cancel keeps your draft open.`)&&this.saveFi
259
265
  </div>
260
266
  </div>
261
267
  <button type="button" class="attachment-close-btn" title="Dismiss">&times;</button>
262
- `;const C=b.querySelector(".attachment-thumbnail-img");C&&(C.onerror=()=>{C.remove(),b.querySelector(".attachment-thumbnail-fallback")?.classList.add("visible")}),b.querySelector(".attachment-preview-btn")?.addEventListener("click",()=>{this.openFilePreview(u,t,r||null)}),b.querySelector(".attachment-open-btn")?.addEventListener("click",()=>{this.openAttachmentInNewTab(t,u,r||null)}),b.querySelector(".attachment-close-btn")?.addEventListener("click",()=>{this.closeAttachmentCard(p)}),w.prepend(b),this.attachmentCards.set(p,{element:b,sessionId:t,filePath:u}),this._refreshAttachmentClearAll()},_refreshAttachmentClearAll(){const e=this.attachmentCardStack;if(!e)return;let t=e.querySelector(".attachment-clear-all");if(this.attachmentCards.size<2){t&&(t.hidden=!0);return}t||(t=document.createElement("button"),t.type="button",t.className="attachment-clear-all",t.textContent="Clear all",t.title="Dismiss all attachment cards",t.addEventListener("click",()=>this.closeAllAttachmentCards()),e.prepend(t)),t.hidden=!1},closeAttachmentCard(e){const t=this.attachmentCards.get(e);t&&(t.element.remove(),this.attachmentCards.delete(e),this.attachmentCardStack&&this.attachmentCards.size===0?(this.attachmentCardStack.remove(),this.attachmentCardStack=null):this._refreshAttachmentClearAll())},closeAllAttachmentCards(){for(const e of[...this.attachmentCards.keys()])this.closeAttachmentCard(e)},closeSessionAttachmentCards(e){const t=[];for(const[s,n]of this.attachmentCards)n.sessionId===e&&t.push(s);for(const s of t)this.closeAttachmentCard(s)},updateAttachmentHistoryBadge(e=null){const t=document.getElementById("attachmentHistoryBadge"),s=document.getElementById("attachmentsHistoryBtn"),n=this.activeSessionId,i=e??(n&&this.attachmentHistoryCounts.get(n)||0);t&&(t.textContent=i>99?"99+":String(i),t.style.display=i>0?"":"none"),s&&(s.classList.toggle("active",this.attachmentHistoryDrawerOpen),s.setAttribute("aria-expanded",this.attachmentHistoryDrawerOpen?"true":"false"))},ensureAttachmentHistoryDrawer(){let e=document.getElementById("attachmentHistoryDrawer");return e||(e=document.createElement("aside"),e.id="attachmentHistoryDrawer",e.className="attachment-history-drawer",e.setAttribute("aria-label","Attachment history"),e.innerHTML=`
268
+ `;const T=b.querySelector(".attachment-thumbnail-img");T&&(T.onerror=()=>{T.remove(),b.querySelector(".attachment-thumbnail-fallback")?.classList.add("visible")}),b.querySelector(".attachment-preview-btn")?.addEventListener("click",()=>{this.openFilePreview(u,t,r||null)}),b.querySelector(".attachment-open-btn")?.addEventListener("click",()=>{this.openAttachmentInNewTab(t,u,r||null)}),b.querySelector(".attachment-close-btn")?.addEventListener("click",()=>{this.closeAttachmentCard(p)}),w.prepend(b),this.attachmentCards.set(p,{element:b,sessionId:t,filePath:u}),this._refreshAttachmentClearAll()},_refreshAttachmentClearAll(){const e=this.attachmentCardStack;if(!e)return;let t=e.querySelector(".attachment-clear-all");if(this.attachmentCards.size<2){t&&(t.hidden=!0);return}t||(t=document.createElement("button"),t.type="button",t.className="attachment-clear-all",t.textContent="Clear all",t.title="Dismiss all attachment cards",t.addEventListener("click",()=>this.closeAllAttachmentCards()),e.prepend(t)),t.hidden=!1},closeAttachmentCard(e){const t=this.attachmentCards.get(e);t&&(t.element.remove(),this.attachmentCards.delete(e),this.attachmentCardStack&&this.attachmentCards.size===0?(this.attachmentCardStack.remove(),this.attachmentCardStack=null):this._refreshAttachmentClearAll())},closeAllAttachmentCards(){for(const e of[...this.attachmentCards.keys()])this.closeAttachmentCard(e)},closeSessionAttachmentCards(e){const t=[];for(const[s,n]of this.attachmentCards)n.sessionId===e&&t.push(s);for(const s of t)this.closeAttachmentCard(s)},updateAttachmentHistoryBadge(e=null){const t=document.getElementById("attachmentHistoryBadge"),s=document.getElementById("attachmentsHistoryBtn"),n=this.activeSessionId,i=e??(n&&this.attachmentHistoryCounts.get(n)||0);t&&(t.textContent=i>99?"99+":String(i),t.style.display=i>0?"":"none"),s&&(s.classList.toggle("active",this.attachmentHistoryDrawerOpen),s.setAttribute("aria-expanded",this.attachmentHistoryDrawerOpen?"true":"false"))},ensureAttachmentHistoryDrawer(){let e=document.getElementById("attachmentHistoryDrawer");return e||(e=document.createElement("aside"),e.id="attachmentHistoryDrawer",e.className="attachment-history-drawer",e.setAttribute("aria-label","Attachment history"),e.innerHTML=`
263
269
  <div class="attachment-history-header">
264
270
  <div>
265
271
  <div class="attachment-history-title">Attachments</div>
@@ -327,7 +333,7 @@ OK overwrites it with your version; Cancel keeps your draft open.`)&&this.saveFi
327
333
  onerror="this.parentElement.innerHTML='<div class=\\'image-error\\'>Failed to load image</div>'"
328
334
  onclick="app.openImageInNewTab(${escapeHtml(JSON.stringify(v))})" />
329
335
  </div>
330
- `,document.body.appendChild(g);const T=this.makeWindowDraggable(g,g.querySelector(".image-popup-header"));g.addEventListener("mousedown",()=>{g.style.zIndex=++this.imagePopupZIndex}),this.imagePopups.set(a,{element:g,sessionId:t,filePath:s,dragListeners:T})},closeImagePopup(e){const t=this.imagePopups.get(e);t&&(t.dragListeners&&(document.removeEventListener("mousemove",t.dragListeners.move),document.removeEventListener("mouseup",t.dragListeners.up),t.dragListeners.touchMove&&(document.removeEventListener("touchmove",t.dragListeners.touchMove),document.removeEventListener("touchend",t.dragListeners.up),document.removeEventListener("touchcancel",t.dragListeners.up)),t.dragListeners.handle&&(t.dragListeners.handle.removeEventListener("mousedown",t.dragListeners.handleMouseDown),t.dragListeners.handle.removeEventListener("touchstart",t.dragListeners.handleTouchStart))),t.element.remove(),this.imagePopups.delete(e))},openImageInNewTab(e){window.open(e,"_blank")},closeSessionImagePopups(e){const t=[];for(const[s,n]of this.imagePopups)n.sessionId===e&&t.push(s);for(const s of t)this.closeImagePopup(s)},async loadMuxSessions(){try{const t=await(await fetch("/api/mux-sessions")).json();this.muxSessions=t.data?.sessions||[],this.renderMuxSessions()}catch(e){console.error("Failed to load mux sessions:",e)}},killAllMuxSessions(){const e=this.muxSessions?.length||0;if(e===0){alert("No sessions to kill");return}document.getElementById("killAllCount").textContent=e;const t=document.getElementById("killAllModal");t.classList.add("active"),this.activeFocusTrap=new FocusTrap(t),this.activeFocusTrap.activate()},closeKillAllModal(){document.getElementById("killAllModal").classList.remove("active"),this.activeFocusTrap&&(this.activeFocusTrap.deactivate(),this.activeFocusTrap=null)},async confirmKillAll(e){this.closeKillAllModal();try{if(e){if((await(await fetch("/api/sessions",{method:"DELETE"})).json()).success){this.sessions.clear(),this.muxSessions=[],this.activeSessionId=null;try{localStorage.removeItem("codeman-active-session")}catch{}this.renderSessionTabs(),this.renderMuxSessions(),this._resetTerminalForReplay(),this.toast("All sessions and tmux killed","success")}}else{this.sessions.clear(),this.activeSessionId=null;try{localStorage.removeItem("codeman-active-session")}catch{}this.renderSessionTabs(),this._resetTerminalForReplay(),this.toast("All tabs removed, tmux still running","info")}}catch(t){console.error("Failed to kill sessions:",t),this.toast("Failed to kill sessions: "+t.message,"error")}},renderMuxSessions(){this._debouncedCall("muxSessions",this._renderMuxSessionsImmediate)},_renderMuxSessionsImmediate(){const e=document.getElementById("muxSessionsBody");if(!this.muxSessions||this.muxSessions.length===0){e.innerHTML='<div class="monitor-empty">No mux sessions</div>';return}let t="";for(const s of this.muxSessions){const n=s.stats||{memoryMB:0,cpuPercent:0,childCount:0},i=this.sessions.get(s.sessionId),o=i?i.status:"unknown",l=i?i.isWorking:!1;let a,r;o==="idle"&&!l?(a="IDLE",r="status-idle"):o==="busy"||l?(a="WORKING",r="status-working"):o==="stopped"?(a="STOPPED",r="status-stopped"):(a=o.toUpperCase(),r="");const c=i&&i.tokens?i.tokens:null,h=i?i.totalCost:0,d=i&&i.cliModel||"",u=d.includes("opus")?"opus":d.includes("sonnet")?"sonnet":d.includes("haiku")?"haiku":"",p=i?i.ralphTodoStats:null;let f="";if(p&&p.total>0){const T=Math.round(p.completed/p.total*100);f=`<span class="process-stat todo-progress">${p.completed}/${p.total} (${T}%)</span>`}let w="";c&&c.total>0&&(w=`<span class="process-stat tokens">${(c.total/1e3).toFixed(1)}k tok</span>`);let y="";h>0&&(y=`<span class="process-stat cost">$${h.toFixed(2)}</span>`);let v="";u&&(v=`<span class="monitor-model-badge ${u}">${u}</span>`);const g=escapeHtml(JSON.stringify(s.sessionId));t+=`
336
+ `,document.body.appendChild(g);const C=this.makeWindowDraggable(g,g.querySelector(".image-popup-header"));g.addEventListener("mousedown",()=>{g.style.zIndex=++this.imagePopupZIndex}),this.imagePopups.set(a,{element:g,sessionId:t,filePath:s,dragListeners:C})},closeImagePopup(e){const t=this.imagePopups.get(e);t&&(t.dragListeners&&(document.removeEventListener("mousemove",t.dragListeners.move),document.removeEventListener("mouseup",t.dragListeners.up),t.dragListeners.touchMove&&(document.removeEventListener("touchmove",t.dragListeners.touchMove),document.removeEventListener("touchend",t.dragListeners.up),document.removeEventListener("touchcancel",t.dragListeners.up)),t.dragListeners.handle&&(t.dragListeners.handle.removeEventListener("mousedown",t.dragListeners.handleMouseDown),t.dragListeners.handle.removeEventListener("touchstart",t.dragListeners.handleTouchStart))),t.element.remove(),this.imagePopups.delete(e))},openImageInNewTab(e){window.open(e,"_blank")},closeSessionImagePopups(e){const t=[];for(const[s,n]of this.imagePopups)n.sessionId===e&&t.push(s);for(const s of t)this.closeImagePopup(s)},async loadMuxSessions(){try{const t=await(await fetch("/api/mux-sessions")).json();this.muxSessions=t.data?.sessions||[],this.renderMuxSessions()}catch(e){console.error("Failed to load mux sessions:",e)}},killAllMuxSessions(){const e=this.muxSessions?.length||0;if(e===0){alert("No sessions to kill");return}document.getElementById("killAllCount").textContent=e;const t=document.getElementById("killAllModal");t.classList.add("active"),this.activeFocusTrap=new FocusTrap(t),this.activeFocusTrap.activate()},closeKillAllModal(){document.getElementById("killAllModal").classList.remove("active"),this.activeFocusTrap&&(this.activeFocusTrap.deactivate(),this.activeFocusTrap=null)},async confirmKillAll(e){this.closeKillAllModal();try{if(e){if((await(await fetch("/api/sessions",{method:"DELETE"})).json()).success){this.sessions.clear(),this.muxSessions=[],this.activeSessionId=null;try{localStorage.removeItem("codeman-active-session")}catch{}this.renderSessionTabs(),this.renderMuxSessions(),this._resetTerminalForReplay(),this.toast("All sessions and tmux killed","success")}}else{this.sessions.clear(),this.activeSessionId=null;try{localStorage.removeItem("codeman-active-session")}catch{}this.renderSessionTabs(),this._resetTerminalForReplay(),this.toast("All tabs removed, tmux still running","info")}}catch(t){console.error("Failed to kill sessions:",t),this.toast("Failed to kill sessions: "+t.message,"error")}},renderMuxSessions(){this._debouncedCall("muxSessions",this._renderMuxSessionsImmediate)},_renderMuxSessionsImmediate(){const e=document.getElementById("muxSessionsBody");if(!this.muxSessions||this.muxSessions.length===0){e.innerHTML='<div class="monitor-empty">No mux sessions</div>';return}let t="";for(const s of this.muxSessions){const n=s.stats||{memoryMB:0,cpuPercent:0,childCount:0},i=this.sessions.get(s.sessionId),o=i?i.status:"unknown",l=i?i.isWorking:!1;let a,r;o==="idle"&&!l?(a="IDLE",r="status-idle"):o==="busy"||l?(a="WORKING",r="status-working"):o==="stopped"?(a="STOPPED",r="status-stopped"):(a=o.toUpperCase(),r="");const c=i&&i.tokens?i.tokens:null,h=i?i.totalCost:0,d=i&&i.cliModel||"",u=d.includes("opus")?"opus":d.includes("sonnet")?"sonnet":d.includes("haiku")?"haiku":"",p=i?i.ralphTodoStats:null;let f="";if(p&&p.total>0){const C=Math.round(p.completed/p.total*100);f=`<span class="process-stat todo-progress">${p.completed}/${p.total} (${C}%)</span>`}let w="";c&&c.total>0&&(w=`<span class="process-stat tokens">${(c.total/1e3).toFixed(1)}k tok</span>`);let y="";h>0&&(y=`<span class="process-stat cost">$${h.toFixed(2)}</span>`);let v="";u&&(v=`<span class="monitor-model-badge ${u}">${u}</span>`);const g=escapeHtml(JSON.stringify(s.sessionId));t+=`
331
337
  <div class="process-item process-item-clickable" onclick="app.selectSession(${g})" title="Switch to session">
332
338
  <span class="monitor-status-badge ${r}">${a}</span>
333
339
  <div class="process-info">
@@ -358,4 +364,4 @@ OK overwrites it with your version; Cancel keeps your draft open.`)&&this.saveFi
358
364
  ${o.status!=="completed"?`<button class="btn-toolbar btn-sm btn-danger" onclick="app.killSubagent(${escapeHtml(JSON.stringify(o.agentId))})" title="Kill agent">Kill</button>`:""}
359
365
  </div>
360
366
  </div>
361
- `}e.innerHTML=i},async killMuxSession(e){if(confirm("Kill this mux session?")){try{await this.closeSession(e,!0)}catch{try{await fetch(`/api/mux-sessions/${e}`,{method:"DELETE"})}catch{}this.showToast("Tmux session killed","success")}this.muxSessions=this.muxSessions.filter(t=>t.sessionId!==e),this.renderMuxSessions()}},async reconcileMuxSessions(){try{const t=await(await fetch("/api/mux-sessions/reconcile",{method:"POST"})).json();t.data?.dead&&t.data.dead.length>0?(this.showToast(`Found ${t.data.dead.length} dead mux session(s)`,"warning"),await this.loadMuxSessions()):this.showToast("All mux sessions are alive","success")}catch{this.showToast("Failed to reconcile mux sessions","error")}},toggleNotifications(){this.notificationManager?.toggleDrawer()},async launchMultiMonitor(){try{const e=await fetch("/api/system/span-displays",{method:"POST"}),t=await e.json().catch(()=>({}));e.ok&&t.success?this.showToast("Opening Codeman across all displays\u2026","success"):this.showToast(t.error||"Could not open spanning window","error")}catch(e){this.showToast("Could not open spanning window: "+(e?.message||e),"error")}},toast(e,t="info"){return this.showToast(e,t)},showToast(e,t="info",s={}){const{duration:n=this.notificationManager?.getToastDurationMs?.()??3e3,action:i}=s,o=document.createElement("div");o.className=`toast toast-${t}`;const l=document.createElement("span");if(l.className="toast-message",l.textContent=e,o.appendChild(l),i){const h=document.createElement("button");h.textContent=i.label,h.style.cssText="margin-left:12px;padding:2px 10px;background:rgba(255,255,255,0.15);border:1px solid rgba(255,255,255,0.3);border-radius:3px;color:inherit;cursor:pointer;font-size:12px",h.onclick=d=>{d.stopPropagation(),i.onClick(),o.remove()},o.appendChild(h)}let a=null;const r=()=>{a&&clearTimeout(a),o.classList.remove("show"),setTimeout(()=>o.remove(),200)},c=document.createElement("button");return c.className="toast-close",c.textContent="\xD7",c.setAttribute("aria-label","Dismiss"),c.onclick=h=>{h.stopPropagation(),r()},o.appendChild(c),this._toastStack().appendChild(o),requestAnimationFrame(()=>o.classList.add("show")),n>0&&(a=setTimeout(r,n)),{dismiss:r,setMessage:h=>{l.textContent=h}}},_toastStack(){return this._toastContainer||(this._toastContainer=document.querySelector(".toast-container"),this._toastContainer||(this._toastContainer=document.createElement("div"),this._toastContainer.className="toast-container",document.body.appendChild(this._toastContainer))),this._toastContainer},showSecurityNotice(e,t={}){const s=this._noticeCard("security-notice",t.onClose),n=this._noticeEl("div","security-notice-main");n.append(this._noticeEl("div","security-notice-eyebrow","Security notice")),n.append(...this._noticeTextBlock(e));const i=this._noticeEl("div","security-notice-actions"),o=this._noticeLinkButton(e,s,()=>s.close("link"));return o&&i.append(o),i.append(this._noticeButton("security-notice-quiet","Dismiss",()=>s.close("dismiss"))),n.append(i),s.el.append(this._noticeIcon("shield","security-notice-icon"),n,s.closeButton),s.mount(),{dismiss:()=>s.close(null)}},showUpdateNotice({text:e,releaseUrl:t,notices:s,onNoticeSeen:n}){const i=r=>{try{n?.(r)}catch(c){console.error("[notice] onNoticeSeen failed:",c)}},o=this._noticeCard("security-notice update-notice",r=>{if(r==="close")for(const c of s)i(c.id)}),l=this._noticeEl("div","security-notice-main");l.append(this._noticeEl("p","update-notice-text",e));const a=this._noticeEl("div","security-notice-actions");for(const r of s){const c=this._noticeEl("section","security-notice-section"),h=this._noticeEl("div","security-notice-section-head");h.append(this._noticeIcon("shield"),this._noticeEl("span","security-notice-eyebrow","Security notice")),c.append(h,...this._noticeTextBlock(r)),l.append(c);const d=this._noticeLinkButton(r,o,()=>{i(r.id),o.close("link")});d&&a.append(d)}return a.append(this._noticeButton("security-notice-secondary","See what's new",o.act(()=>window.open(t,"_blank","noopener,noreferrer")))),l.append(a),o.el.append(this._noticeIcon("update","security-notice-icon update-notice-icon"),l,o.closeButton),o.mount(),{dismiss:()=>o.close(null)}},_noticeCard(e,t){const s=this._noticeEl("div",e);s.setAttribute("role","alert"),s.setAttribute("aria-live","assertive");let n=!1;const i=r=>{if(!n&&(n=!0,s.inert=!0,s.classList.remove("show"),setTimeout(()=>s.remove(),200),r&&typeof t=="function"))try{t(r)}catch(c){console.error("[notice] onClose failed:",c)}},o=this._noticeButton("security-notice-close","\xD7",()=>i("close"));return o.setAttribute("aria-label","Close"),{el:s,closeButton:o,close:i,mount:()=>{this._toastStack().appendChild(s),requestAnimationFrame(()=>s.classList.add("show"))},act:r=>()=>{n||r()}}},_noticeTextBlock(e){const t=[];return e.title&&t.push(this._noticeEl("div","security-notice-title",e.title,!0)),t.push(this._noticeEl("p","security-notice-body",e.message,!0)),t},_noticeLinkButton(e,t,s){const n=e.url;return window.CodemanSecurityNotices?.urlOk?.(n)?this._noticeButton("security-notice-primary",e.label,t.act(()=>{window.open(n,"_blank","noopener,noreferrer"),s()}),!0):null},_noticeButton(e,t,s,n=!1){const i=this._noticeEl("button",e,t,n);return i.type="button",i.onclick=o=>{o.stopPropagation(),s()},i},_noticeEl(e,t,s,n=!1){const i=document.createElement(e);return i.className=t,s!==void 0&&(i.textContent=s),n&&i.setAttribute("data-i18n-skip",""),i},_noticeIcon(e,t){const s="http://www.w3.org/2000/svg",n=document.createElementNS(s,"svg");for(const[l,a]of Object.entries({viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round","aria-hidden":"true",focusable:"false"}))n.setAttribute(l,a);const i=e==="shield"?[["path",{d:"M12 3 4.5 6v5.2c0 4.5 3.1 8.4 7.5 9.8 4.4-1.4 7.5-5.3 7.5-9.8V6L12 3z"}],["path",{d:"M12 8.5v4.5"}],["path",{d:"M12 16.5h.01"}]]:[["circle",{cx:"12",cy:"12",r:"9"}],["path",{d:"M12 16.5v-9"}],["path",{d:"m8.5 11 3.5-3.5 3.5 3.5"}]];for(const[l,a]of i){const r=document.createElementNS(s,l);for(const[c,h]of Object.entries(a))r.setAttribute(c,h);n.appendChild(r)}if(!t)return n;const o=this._noticeEl("span",t);return o.setAttribute("aria-hidden","true"),o.appendChild(n),o},_showCenterStatus(e,t={}){const{type:s="info",onCancel:n}=t;let i=document.getElementById("customModelCenterStatus");i||(i=document.createElement("div"),i.id="customModelCenterStatus",document.body.appendChild(i)),i._hideTimer&&(clearTimeout(i._hideTimer),i._hideTimer=null),i.className=`center-status-banner center-status-${s}`,i.innerHTML="";const o=()=>{i.classList.remove("show"),i._hideTimer=setTimeout(()=>{i.hidden=!0,i._hideTimer=null},200)};if(s!=="error"){const a=document.createElement("span");a.className="center-status-spinner",a.setAttribute("aria-hidden","true"),i.appendChild(a)}const l=document.createElement("span");if(l.className="center-status-text",l.textContent=e,i.appendChild(l),s==="error"){const a=document.createElement("button");a.className="center-status-close",a.textContent="\xD7",a.setAttribute("aria-label","Dismiss"),a.onclick=r=>{r.stopPropagation(),o()},i.appendChild(a)}else if(n){const a=document.createElement("button");a.className="center-status-cancel",a.textContent="Cancel",a.onclick=r=>{r.stopPropagation(),n()},i.appendChild(a)}return i.hidden=!1,requestAnimationFrame(()=>i.classList.add("show")),{dismiss:o,setMessage:a=>{const r=i.querySelector(".center-status-text");r&&(r.textContent=a)}}},startSystemStatsPolling(){this.stopSystemStatsPolling(),this.fetchSystemStats(),this.systemStatsInterval=setInterval(()=>{this.fetchSystemStats()},2e3)},stopSystemStatsPolling(){this.systemStatsInterval&&(clearInterval(this.systemStatsInterval),this.systemStatsInterval=null)},async fetchSystemStats(){const e=document.getElementById("headerSystemStats");if(!(!e||e.style.display==="none"))try{const s=await(await fetch("/api/system/stats")).json();this.updateSystemStatsDisplay(s.data)}catch{}},updateSystemStatsDisplay(e){const t=this.$("statCpu"),s=this.$("statCpuBar"),n=this.$("statMem"),i=this.$("statMemBar");if(t&&s&&(t.textContent=`${e.cpu}%`,s.style.width=`${Math.min(100,e.cpu)}%`,s.classList.remove("medium","high"),t.classList.remove("high"),e.cpu>80?(s.classList.add("high"),t.classList.add("high")):e.cpu>50&&s.classList.add("medium")),this._setStatRing("statCpuRing",e.cpu),this._setStatRing("statMemRing",e.memory?.percent),n&&i){const o=(e.memory.usedMB/1024).toFixed(1);n.textContent=`${o}G`,i.style.width=`${Math.min(100,e.memory.percent)}%`,i.classList.remove("medium","high"),n.classList.remove("high"),e.memory.percent>80?(i.classList.add("high"),n.classList.add("high")):e.memory.percent>50&&i.classList.add("medium")}},_setStatRing(e,t){const s=this.$(e);if(!s)return;const n=Number(t),i=Number.isFinite(n)?Math.round(Math.min(100,Math.max(0,n))):0;s.style.setProperty("--pu",String(i)),s.classList.toggle("high",i>80)},async _onClipboardWrite(e){const t=e?.text;if(typeof t=="string")try{await navigator.clipboard.writeText(t),this.showToast(`Copied to clipboard (${t.length} chars)`,"success")}catch{this._showClipboardFallback(t)}},_showClipboardFallback(e){const t=document.createElement("div");t.style.cssText="position:fixed;inset:0;background:rgba(0,0,0,0.6);z-index:10000;display:flex;align-items:center;justify-content:center";const s=document.createElement("div");s.style.cssText="background:#1e1e2e;border:1px solid #444;border-radius:8px;padding:16px;max-width:600px;width:90%;max-height:60vh;display:flex;flex-direction:column;gap:12px";const n=document.createElement("div");n.style.cssText="display:flex;justify-content:space-between;align-items:center";const i=document.createElement("span");i.style.cssText="color:#cdd6f4;font-weight:600",i.textContent="Clipboard (browser blocked auto-copy)";const o=document.createElement("button");o.style.cssText="background:none;border:none;color:#cdd6f4;font-size:18px;cursor:pointer",o.textContent="\xD7",n.appendChild(i),n.appendChild(o);const l=document.createElement("textarea");l.readOnly=!0,l.style.cssText="background:#181825;color:#cdd6f4;border:1px solid #555;border-radius:4px;padding:8px;font-family:monospace;font-size:13px;resize:none;height:200px;width:100%",l.value=e;const a=document.createElement("button");a.style.cssText="background:#89b4fa;color:#1e1e2e;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-weight:600",a.textContent="Copy to Clipboard",s.appendChild(n),s.appendChild(l),s.appendChild(a),t.appendChild(s),document.body.appendChild(t),a.onclick=async()=>{try{await navigator.clipboard.writeText(e),this.showToast("Copied to clipboard","success"),t.remove()}catch{l.select(),document.execCommand("copy"),this.showToast("Copied (fallback)","success"),t.remove()}};const r=()=>t.remove();o.onclick=r,t.onclick=c=>{c.target===t&&r()}}});
367
+ `}e.innerHTML=i},async killMuxSession(e){if(confirm("Kill this mux session?")){try{await this.closeSession(e,!0)}catch{try{await fetch(`/api/mux-sessions/${e}`,{method:"DELETE"})}catch{}this.showToast("Tmux session killed","success")}this.muxSessions=this.muxSessions.filter(t=>t.sessionId!==e),this.renderMuxSessions()}},async reconcileMuxSessions(){try{const t=await(await fetch("/api/mux-sessions/reconcile",{method:"POST"})).json();t.data?.dead&&t.data.dead.length>0?(this.showToast(`Found ${t.data.dead.length} dead mux session(s)`,"warning"),await this.loadMuxSessions()):this.showToast("All mux sessions are alive","success")}catch{this.showToast("Failed to reconcile mux sessions","error")}},toggleNotifications(){this.notificationManager?.toggleDrawer()},async launchMultiMonitor(){try{const e=await fetch("/api/system/span-displays",{method:"POST"}),t=await e.json().catch(()=>({}));e.ok&&t.success?this.showToast("Opening Codeman across all displays\u2026","success"):this.showToast(t.error||"Could not open spanning window","error")}catch(e){this.showToast("Could not open spanning window: "+(e?.message||e),"error")}},toast(e,t="info"){return this.showToast(e,t)},showToast(e,t="info",s={}){const{duration:n=this.notificationManager?.getToastDurationMs?.()??3e3,action:i}=s,o=document.createElement("div");o.className=`toast toast-${t}`;const l=document.createElement("span");if(l.className="toast-message",l.textContent=e,o.appendChild(l),i){const h=document.createElement("button");h.textContent=i.label,h.style.cssText="margin-left:12px;padding:2px 10px;background:rgba(255,255,255,0.15);border:1px solid rgba(255,255,255,0.3);border-radius:3px;color:inherit;cursor:pointer;font-size:12px",h.onclick=d=>{d.stopPropagation(),i.onClick(),o.remove()},o.appendChild(h)}let a=null;const r=()=>{a&&clearTimeout(a),o.classList.remove("show"),setTimeout(()=>o.remove(),200)},c=document.createElement("button");return c.className="toast-close",c.textContent="\xD7",c.setAttribute("aria-label","Dismiss"),c.onclick=h=>{h.stopPropagation(),r()},o.appendChild(c),this._toastStack().appendChild(o),requestAnimationFrame(()=>o.classList.add("show")),n>0&&(a=setTimeout(r,n)),{dismiss:r,setMessage:h=>{l.textContent=h}}},_toastStack(){return this._toastContainer||(this._toastContainer=document.querySelector(".toast-container"),this._toastContainer||(this._toastContainer=document.createElement("div"),this._toastContainer.className="toast-container",document.body.appendChild(this._toastContainer))),this._toastContainer},showSecurityNotice(e,t={}){const s=this._noticeCard("security-notice",t.onClose),n=this._noticeEl("div","security-notice-main");n.append(this._noticeEl("div","security-notice-eyebrow","Security notice")),n.append(...this._noticeTextBlock(e));const i=this._noticeEl("div","security-notice-actions"),o=this._noticeLinkButton(e,s,()=>s.close("link"));return o&&i.append(o),i.append(this._noticeButton("security-notice-quiet","Dismiss",()=>s.close("dismiss"))),n.append(i),s.el.append(this._noticeIcon("shield","security-notice-icon"),n,s.closeButton),s.mount(),{dismiss:()=>s.close(null)}},showUpdateNotice({text:e,releaseUrl:t,notices:s,onNoticeSeen:n}){const i=r=>{try{n?.(r)}catch(c){console.error("[notice] onNoticeSeen failed:",c)}},o=this._noticeCard("security-notice update-notice",r=>{if(r==="close")for(const c of s)i(c.id)}),l=this._noticeEl("div","security-notice-main");l.append(this._noticeEl("p","update-notice-text",e));const a=this._noticeEl("div","security-notice-actions");for(const r of s){const c=this._noticeEl("section","security-notice-section"),h=this._noticeEl("div","security-notice-section-head");h.append(this._noticeIcon("shield"),this._noticeEl("span","security-notice-eyebrow","Security notice")),c.append(h,...this._noticeTextBlock(r)),l.append(c);const d=this._noticeLinkButton(r,o,()=>{i(r.id),o.close("link")});d&&a.append(d)}return a.append(this._noticeButton("security-notice-secondary","See what's new",o.act(()=>window.open(t,"_blank","noopener,noreferrer")))),l.append(a),o.el.append(this._noticeIcon("update","security-notice-icon update-notice-icon"),l,o.closeButton),o.mount(),{dismiss:()=>o.close(null)}},_noticeCard(e,t){const s=this._noticeEl("div",e);s.setAttribute("role","alert"),s.setAttribute("aria-live","assertive");let n=!1;const i=r=>{if(!n&&(n=!0,s.inert=!0,s.classList.remove("show"),setTimeout(()=>s.remove(),200),r&&typeof t=="function"))try{t(r)}catch(c){console.error("[notice] onClose failed:",c)}},o=this._noticeButton("security-notice-close","\xD7",()=>i("close"));return o.setAttribute("aria-label","Close"),{el:s,closeButton:o,close:i,mount:()=>{this._toastStack().appendChild(s),requestAnimationFrame(()=>s.classList.add("show"))},act:r=>()=>{n||r()}}},_noticeTextBlock(e){const t=[];return e.title&&t.push(this._noticeEl("div","security-notice-title",e.title,!0)),t.push(this._noticeEl("p","security-notice-body",e.message,!0)),t},_noticeLinkButton(e,t,s){const n=e.url;return window.CodemanSecurityNotices?.urlOk?.(n)?this._noticeButton("security-notice-primary",e.label,t.act(()=>{window.open(n,"_blank","noopener,noreferrer"),s()}),!0):null},_noticeButton(e,t,s,n=!1){const i=this._noticeEl("button",e,t,n);return i.type="button",i.onclick=o=>{o.stopPropagation(),s()},i},_noticeEl(e,t,s,n=!1){const i=document.createElement(e);return i.className=t,s!==void 0&&(i.textContent=s),n&&i.setAttribute("data-i18n-skip",""),i},_noticeIcon(e,t){const s="http://www.w3.org/2000/svg",n=document.createElementNS(s,"svg");for(const[l,a]of Object.entries({viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round","aria-hidden":"true",focusable:"false"}))n.setAttribute(l,a);const i=e==="shield"?[["path",{d:"M12 3 4.5 6v5.2c0 4.5 3.1 8.4 7.5 9.8 4.4-1.4 7.5-5.3 7.5-9.8V6L12 3z"}],["path",{d:"M12 8.5v4.5"}],["path",{d:"M12 16.5h.01"}]]:[["circle",{cx:"12",cy:"12",r:"9"}],["path",{d:"M12 16.5v-9"}],["path",{d:"m8.5 11 3.5-3.5 3.5 3.5"}]];for(const[l,a]of i){const r=document.createElementNS(s,l);for(const[c,h]of Object.entries(a))r.setAttribute(c,h);n.appendChild(r)}if(!t)return n;const o=this._noticeEl("span",t);return o.setAttribute("aria-hidden","true"),o.appendChild(n),o},_showCenterStatus(e,t={}){const{type:s="info",onCancel:n}=t;let i=document.getElementById("customModelCenterStatus");i||(i=document.createElement("div"),i.id="customModelCenterStatus",document.body.appendChild(i)),i._hideTimer&&(clearTimeout(i._hideTimer),i._hideTimer=null),i.className=`center-status-banner center-status-${s}`,i.innerHTML="";const o=()=>{i.classList.remove("show"),i._hideTimer=setTimeout(()=>{i.hidden=!0,i._hideTimer=null},200)};if(s!=="error"){const a=document.createElement("span");a.className="center-status-spinner",a.setAttribute("aria-hidden","true"),i.appendChild(a)}const l=document.createElement("span");if(l.className="center-status-text",l.textContent=e,i.appendChild(l),s==="error"){const a=document.createElement("button");a.className="center-status-close",a.textContent="\xD7",a.setAttribute("aria-label","Dismiss"),a.onclick=r=>{r.stopPropagation(),o()},i.appendChild(a)}else if(n){const a=document.createElement("button");a.className="center-status-cancel",a.textContent="Cancel",a.onclick=r=>{r.stopPropagation(),n()},i.appendChild(a)}return i.hidden=!1,requestAnimationFrame(()=>i.classList.add("show")),{dismiss:o,setMessage:a=>{const r=i.querySelector(".center-status-text");r&&(r.textContent=a)}}},startSystemStatsPolling(){this.stopSystemStatsPolling(),this.fetchSystemStats(),this.systemStatsInterval=setInterval(()=>{this.fetchSystemStats()},2e3)},stopSystemStatsPolling(){this.systemStatsInterval&&(clearInterval(this.systemStatsInterval),this.systemStatsInterval=null)},async fetchSystemStats(){const e=document.getElementById("headerSystemStats");if(!(!e||e.style.display==="none")&&!this._systemStatsPending){this._systemStatsPending=!0;try{const t=this.loadAppSettingsFromStorage?.()??{},s=["gpu",t.showGpuStats,"cpumhz",t.showCpuMhz],n=[];for(let l=0;l<s.length;l+=2)s[l+1]===!0&&n.push(`${s[l]}=1`);const o=await(await fetch("/api/system/stats"+(n.length?"?"+n.join("&"):""),{signal:typeof AbortSignal<"u"&&typeof AbortSignal.timeout=="function"?AbortSignal.timeout(8e3):void 0})).json();this.updateSystemStatsDisplay(o.data)}catch{}finally{this._systemStatsPending=!1}}},updateSystemStatsDisplay(e){const t=this.$("statCpu"),s=this.$("statCpuBar"),n=this.$("statMem"),i=this.$("statMemBar");if(t&&s&&(t.textContent=`${e.cpu}%`,s.style.width=`${Math.min(100,e.cpu)}%`,s.classList.remove("medium","high"),t.classList.remove("high"),e.cpu>80?(s.classList.add("high"),t.classList.add("high")):e.cpu>50&&s.classList.add("medium")),this._setStatRing("statCpuRing",e.cpu),this._setStatRing("statMemRing",e.memory?.percent),n&&i){const o=(e.memory.usedMB/1024).toFixed(1);n.textContent=`${o}G`,i.style.width=`${Math.min(100,e.memory.percent)}%`,i.classList.remove("medium","high"),n.classList.remove("high"),e.memory.percent>80?(i.classList.add("high"),n.classList.add("high")):e.memory.percent>50&&i.classList.add("medium")}this._updateHostSensors(e)},_updateHostSensors(e){const t=this.loadAppSettingsFromStorage?.()??{},s=(r,c)=>{const h=this.$(r);h&&(h.hidden=!c)},n=(r,c,h,d,u)=>{const p=this.$(r);p&&(p.textContent=u,p.classList.toggle("high",d>80)),this._setStatRing(c,d);const f=this.$(h);f&&(f.style.width=`${Math.min(100,d)}%`)},i=t.showGpuStats===!0?e.gpu:void 0;if(s("statGpuItem",!!i),i&&n("statGpu","statGpuRing","statGpuBar",i.percent,`${i.percent}%`),s("statVramItem",!!(i&&i.memUsedMB!==void 0)),i&&i.memUsedMB!==void 0){const r=`${(i.memUsedMB/1024).toFixed(1)}G`,c=this.$("statVramRing");if(this.$("statVramItem")?.classList.toggle("stat-item--ringless",i.memPercent===void 0),i.memPercent!==void 0)n("statVram","statVramRing","statVramBar",i.memPercent,r),c&&(c.style.display="");else{const h=this.$("statVram");h&&(h.textContent=r),c&&(c.style.display="none")}}s("statGpuMhzItem",!!(i&&i.mhz!==void 0));const o=i&&i.mhz!==void 0?this.$("statGpuMhz"):null;o&&(o.textContent=`${i.mhz} MHz`);const l=t.showCpuMhz===!0&&e.cpuMhz!==void 0?e.cpuMhz:void 0;s("statCpuMhzItem",l!==void 0);const a=l!==void 0?this.$("statCpuMhz"):null;a&&(a.textContent=`${l} MHz`)},_setStatRing(e,t){const s=this.$(e);if(!s)return;const n=Number(t),i=Number.isFinite(n)?Math.round(Math.min(100,Math.max(0,n))):0;s.style.setProperty("--pu",String(i)),s.classList.toggle("high",i>80)},async _onClipboardWrite(e){const t=e?.text;if(typeof t=="string")try{await navigator.clipboard.writeText(t),this.showToast(`Copied to clipboard (${t.length} chars)`,"success")}catch{this._showClipboardFallback(t)}},_showClipboardFallback(e){const t=document.createElement("div");t.style.cssText="position:fixed;inset:0;background:rgba(0,0,0,0.6);z-index:10000;display:flex;align-items:center;justify-content:center";const s=document.createElement("div");s.style.cssText="background:#1e1e2e;border:1px solid #444;border-radius:8px;padding:16px;max-width:600px;width:90%;max-height:60vh;display:flex;flex-direction:column;gap:12px";const n=document.createElement("div");n.style.cssText="display:flex;justify-content:space-between;align-items:center";const i=document.createElement("span");i.style.cssText="color:#cdd6f4;font-weight:600",i.textContent="Clipboard (browser blocked auto-copy)";const o=document.createElement("button");o.style.cssText="background:none;border:none;color:#cdd6f4;font-size:18px;cursor:pointer",o.textContent="\xD7",n.appendChild(i),n.appendChild(o);const l=document.createElement("textarea");l.readOnly=!0,l.style.cssText="background:#181825;color:#cdd6f4;border:1px solid #555;border-radius:4px;padding:8px;font-family:monospace;font-size:13px;resize:none;height:200px;width:100%",l.value=e;const a=document.createElement("button");a.style.cssText="background:#89b4fa;color:#1e1e2e;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-weight:600",a.textContent="Copy to Clipboard",s.appendChild(n),s.appendChild(l),s.appendChild(a),t.appendChild(s),document.body.appendChild(t),a.onclick=async()=>{try{await navigator.clipboard.writeText(e),this.showToast("Copied to clipboard","success"),t.remove()}catch{l.select(),document.execCommand("copy"),this.showToast("Copied (fallback)","success"),t.remove()}};const r=()=>t.remove();o.onclick=r,t.onclick=c=>{c.target===t&&r()}}});