aicodeman 1.35.0 → 1.41.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.
- package/README.md +33 -7
- package/dist/attachment-registry.d.ts +6 -0
- package/dist/attachment-registry.d.ts.map +1 -1
- package/dist/attachment-registry.js +9 -3
- package/dist/attachment-registry.js.map +1 -1
- package/dist/cli-agent.d.ts +225 -0
- package/dist/cli-agent.d.ts.map +1 -0
- package/dist/cli-agent.js +767 -0
- package/dist/cli-agent.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +8 -32
- package/dist/cli.js.map +1 -1
- package/dist/codeman-credentials.d.ts +27 -0
- package/dist/codeman-credentials.d.ts.map +1 -0
- package/dist/codeman-credentials.js +66 -0
- package/dist/codeman-credentials.js.map +1 -0
- package/dist/config/cli-registry/patterns.d.ts +6 -0
- package/dist/config/cli-registry/patterns.d.ts.map +1 -1
- package/dist/config/cli-registry/patterns.js +13 -0
- package/dist/config/cli-registry/patterns.js.map +1 -1
- package/dist/config/cli-registry/schema.d.ts +15 -0
- package/dist/config/cli-registry/schema.d.ts.map +1 -1
- package/dist/config/cli-registry/schema.js +63 -2
- package/dist/config/cli-registry/schema.js.map +1 -1
- package/dist/config/cli-registry/stock.d.ts.map +1 -1
- package/dist/config/cli-registry/stock.js +180 -7
- package/dist/config/cli-registry/stock.js.map +1 -1
- package/dist/config/cli-registry/types.d.ts +105 -7
- package/dist/config/cli-registry/types.d.ts.map +1 -1
- package/dist/deepseek-route-config.d.ts +110 -0
- package/dist/deepseek-route-config.d.ts.map +1 -0
- package/dist/deepseek-route-config.js +477 -0
- package/dist/deepseek-route-config.js.map +1 -0
- package/dist/git-clone.d.ts.map +1 -1
- package/dist/git-clone.js +4 -0
- package/dist/git-clone.js.map +1 -1
- package/dist/git-workspace-status.d.ts +31 -5
- package/dist/git-workspace-status.d.ts.map +1 -1
- package/dist/git-workspace-status.js +49 -29
- package/dist/git-workspace-status.js.map +1 -1
- package/dist/image-watcher.d.ts.map +1 -1
- package/dist/image-watcher.js +6 -2
- package/dist/image-watcher.js.map +1 -1
- package/dist/mcp-sync-targets.d.ts +34 -0
- package/dist/mcp-sync-targets.d.ts.map +1 -0
- package/dist/mcp-sync-targets.js +55 -0
- package/dist/mcp-sync-targets.js.map +1 -0
- package/dist/mcp-sync.d.ts +2 -1
- package/dist/mcp-sync.d.ts.map +1 -1
- package/dist/mcp-sync.js +62 -1
- package/dist/mcp-sync.js.map +1 -1
- package/dist/model-config-resolvers.d.ts +29 -0
- package/dist/model-config-resolvers.d.ts.map +1 -0
- package/dist/model-config-resolvers.js +34 -0
- package/dist/model-config-resolvers.js.map +1 -0
- package/dist/session-display-model.d.ts +110 -0
- package/dist/session-display-model.d.ts.map +1 -0
- package/dist/session-display-model.js +154 -0
- package/dist/session-display-model.js.map +1 -0
- package/dist/session.d.ts +145 -8
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +290 -39
- package/dist/session.js.map +1 -1
- package/dist/subagent-watcher.d.ts.map +1 -1
- package/dist/subagent-watcher.js +29 -6
- package/dist/subagent-watcher.js.map +1 -1
- package/dist/templates/case-template.md +2 -0
- package/dist/tmux-manager.d.ts +5 -0
- package/dist/tmux-manager.d.ts.map +1 -1
- package/dist/tmux-manager.js +47 -22
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tui/tui-client.d.ts +3 -17
- package/dist/tui/tui-client.d.ts.map +1 -1
- package/dist/tui/tui-client.js +3 -44
- package/dist/tui/tui-client.js.map +1 -1
- package/dist/types/session.d.ts +28 -1
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js.map +1 -1
- package/dist/types/tools.d.ts +1 -1
- package/dist/types/tools.d.ts.map +1 -1
- package/dist/utils/deepseek-cli-resolver.d.ts +8 -0
- package/dist/utils/deepseek-cli-resolver.d.ts.map +1 -1
- package/dist/utils/deepseek-cli-resolver.js +18 -2
- package/dist/utils/deepseek-cli-resolver.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/process-exit-wait.d.ts +40 -0
- package/dist/utils/process-exit-wait.d.ts.map +1 -0
- package/dist/utils/process-exit-wait.js +68 -0
- package/dist/utils/process-exit-wait.js.map +1 -0
- package/dist/web/launch-defaults.d.ts +22 -0
- package/dist/web/launch-defaults.d.ts.map +1 -0
- package/dist/web/launch-defaults.js +46 -0
- package/dist/web/launch-defaults.js.map +1 -0
- package/dist/web/paste-image-gc.d.ts +46 -6
- package/dist/web/paste-image-gc.d.ts.map +1 -1
- package/dist/web/paste-image-gc.js +106 -32
- package/dist/web/paste-image-gc.js.map +1 -1
- package/dist/web/public/admin-ui.js.gz +0 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/app.6f8552e1.js +43 -0
- package/dist/web/public/app.6f8552e1.js.br +0 -0
- package/dist/web/public/app.6f8552e1.js.gz +0 -0
- package/dist/web/public/approvals-ui.js.gz +0 -0
- package/dist/web/public/{constants.d95fade9.js → constants.bc9c1f63.js} +1276 -127
- package/dist/web/public/constants.bc9c1f63.js.br +0 -0
- package/dist/web/public/constants.bc9c1f63.js.gz +0 -0
- package/dist/web/public/cron-ui.js.gz +0 -0
- package/dist/web/public/entrance-animations.js +491 -43
- package/dist/web/public/entrance-animations.js.br +0 -0
- package/dist/web/public/entrance-animations.js.gz +0 -0
- package/dist/web/public/git-status-ui.js +55 -9
- package/dist/web/public/git-status-ui.js.br +0 -0
- package/dist/web/public/git-status-ui.js.gz +0 -0
- package/dist/web/public/home-sessions.js +13 -9
- package/dist/web/public/home-sessions.js.br +0 -0
- package/dist/web/public/home-sessions.js.gz +0 -0
- package/dist/web/public/host-wake-ui.js.gz +0 -0
- package/dist/web/public/i18n.a9840ea2.js +2 -0
- package/dist/web/public/i18n.a9840ea2.js.br +0 -0
- package/dist/web/public/i18n.a9840ea2.js.gz +0 -0
- package/dist/web/public/{image-input.a216cf9e.js → image-input.e00471c6.js} +21 -9
- package/dist/web/public/image-input.e00471c6.js.br +0 -0
- package/dist/web/public/image-input.e00471c6.js.gz +0 -0
- package/dist/web/public/index.html +250 -59
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.c1e7c7b7.js.gz +0 -0
- package/dist/web/public/{mobile-handlers.23a85db1.js → mobile-handlers.0ef9c311.js} +20 -0
- package/dist/web/public/mobile-handlers.0ef9c311.js.br +0 -0
- package/dist/web/public/mobile-handlers.0ef9c311.js.gz +0 -0
- package/dist/web/public/mobile-ime-preview.2dbaf262.js.gz +0 -0
- package/dist/web/public/mobile-overview.js.gz +0 -0
- package/dist/web/public/mobile.111b187d.css +1 -0
- package/dist/web/public/mobile.111b187d.css.br +0 -0
- package/dist/web/public/mobile.111b187d.css.gz +0 -0
- package/dist/web/public/{notification-manager.50bb87d8.js → notification-manager.feb82c04.js} +19 -2
- package/dist/web/public/notification-manager.feb82c04.js.br +0 -0
- package/dist/web/public/notification-manager.feb82c04.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/{panels-ui.6a5898d9.js → panels-ui.71846fcb.js} +4 -4
- package/dist/web/public/panels-ui.71846fcb.js.br +0 -0
- package/dist/web/public/panels-ui.71846fcb.js.gz +0 -0
- package/dist/web/public/ralph-panel.b350e2ef.js.gz +0 -0
- package/dist/web/public/ralph-wizard.b6c0dd19.js.gz +0 -0
- package/dist/web/public/readmymind-ui.js.gz +0 -0
- package/dist/web/public/reboot-restore-ui.js.gz +0 -0
- package/dist/web/public/respawn-ui.ff0dae4c.js.gz +0 -0
- package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
- package/dist/web/public/session-lineage.js +229 -86
- package/dist/web/public/session-lineage.js.br +0 -0
- package/dist/web/public/session-lineage.js.gz +0 -0
- package/dist/web/public/session-ui.f731602c.js +100 -0
- package/dist/web/public/session-ui.f731602c.js.br +0 -0
- package/dist/web/public/session-ui.f731602c.js.gz +0 -0
- package/dist/web/public/settings-ui.4e33390f.js +97 -0
- package/dist/web/public/settings-ui.4e33390f.js.br +0 -0
- package/dist/web/public/settings-ui.4e33390f.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview-worker.js +290 -0
- package/dist/web/public/spreadsheet-preview-worker.js.br +0 -0
- package/dist/web/public/spreadsheet-preview-worker.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview.af82fa2f.js +555 -0
- package/dist/web/public/spreadsheet-preview.af82fa2f.js.br +0 -0
- package/dist/web/public/spreadsheet-preview.af82fa2f.js.gz +0 -0
- package/dist/web/public/spreadsheet-xlsx-core.js +1006 -0
- package/dist/web/public/spreadsheet-xlsx-core.js.br +0 -0
- package/dist/web/public/spreadsheet-xlsx-core.js.gz +0 -0
- package/dist/web/public/styles.81a72906.css +1 -0
- package/dist/web/public/styles.81a72906.css.br +0 -0
- package/dist/web/public/styles.81a72906.css.gz +0 -0
- package/dist/web/public/{subagent-windows.e6ca799f.js → subagent-windows.07277a58.js} +7 -5
- package/dist/web/public/subagent-windows.07277a58.js.br +0 -0
- package/dist/web/public/subagent-windows.07277a58.js.gz +0 -0
- package/dist/web/public/sw.js +2 -2
- package/dist/web/public/sw.js.br +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/tab-layout-browser.065fcba4.js.gz +0 -0
- package/dist/web/public/{tab-rail-resize.94cd59f0.js → tab-rail-resize.a5867793.js} +1 -1
- package/dist/web/public/tab-rail-resize.a5867793.js.br +0 -0
- package/dist/web/public/{tab-rail-resize.94cd59f0.js.gz → tab-rail-resize.a5867793.js.gz} +0 -0
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js +1 -0
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.br +0 -0
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.gz +0 -0
- package/dist/web/public/terminal-split.js +146 -649
- package/dist/web/public/terminal-split.js.br +0 -0
- package/dist/web/public/terminal-split.js.gz +0 -0
- package/dist/web/public/terminal-tile.js +1688 -0
- package/dist/web/public/terminal-tile.js.br +0 -0
- package/dist/web/public/terminal-tile.js.gz +0 -0
- package/dist/web/public/terminal-ui.b7267005.js +2 -0
- package/dist/web/public/terminal-ui.b7267005.js.br +0 -0
- package/dist/web/public/terminal-ui.b7267005.js.gz +0 -0
- package/dist/web/public/tile-grid.js +2895 -0
- package/dist/web/public/tile-grid.js.br +0 -0
- package/dist/web/public/tile-grid.js.gz +0 -0
- package/dist/web/public/ultracode-panel.js.gz +0 -0
- package/dist/web/public/ultracode-windows.js +9 -6
- package/dist/web/public/ultracode-windows.js.br +0 -0
- package/dist/web/public/ultracode-windows.js.gz +0 -0
- package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
- package/dist/web/public/vendor/exceljs.min.js +44 -0
- package/dist/web/public/vendor/exceljs.min.js.br +0 -0
- package/dist/web/public/vendor/exceljs.min.js.gz +0 -0
- package/dist/web/public/vendor/fflate.min.js +1 -0
- package/dist/web/public/vendor/fflate.min.js.br +0 -0
- package/dist/web/public/vendor/fflate.min.js.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.ae5e3d5d.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js +4 -0
- package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.br +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/{voice-input.c4b51eb6.js → voice-input.2342c37b.js} +64 -10
- package/dist/web/public/voice-input.2342c37b.js.br +0 -0
- package/dist/web/public/voice-input.2342c37b.js.gz +0 -0
- package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
- package/dist/web/public/webview-tabs.js +9 -1
- package/dist/web/public/webview-tabs.js.br +0 -0
- package/dist/web/public/webview-tabs.js.gz +0 -0
- package/dist/web/routes/cli-registry-routes.d.ts +23 -4
- package/dist/web/routes/cli-registry-routes.d.ts.map +1 -1
- package/dist/web/routes/cli-registry-routes.js +95 -8
- package/dist/web/routes/cli-registry-routes.js.map +1 -1
- package/dist/web/routes/file-routes.d.ts +7 -0
- package/dist/web/routes/file-routes.d.ts.map +1 -1
- package/dist/web/routes/file-routes.js +34 -4
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/routes/git-status-routes.d.ts.map +1 -1
- package/dist/web/routes/git-status-routes.js +33 -6
- package/dist/web/routes/git-status-routes.js.map +1 -1
- package/dist/web/routes/mcp-sync-routes.d.ts +7 -2
- package/dist/web/routes/mcp-sync-routes.d.ts.map +1 -1
- package/dist/web/routes/mcp-sync-routes.js +10 -3
- package/dist/web/routes/mcp-sync-routes.js.map +1 -1
- package/dist/web/routes/reboot-restore-routes.js +1 -1
- package/dist/web/routes/reboot-restore-routes.js.map +1 -1
- package/dist/web/routes/session-routes.d.ts +18 -0
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +154 -69
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/routes/status-telemetry-routes.d.ts +3 -0
- package/dist/web/routes/status-telemetry-routes.d.ts.map +1 -1
- package/dist/web/routes/status-telemetry-routes.js +12 -0
- package/dist/web/routes/status-telemetry-routes.js.map +1 -1
- package/dist/web/routes/system-routes.d.ts.map +1 -1
- package/dist/web/routes/system-routes.js +13 -0
- package/dist/web/routes/system-routes.js.map +1 -1
- package/dist/web/schemas.d.ts +30 -0
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +43 -0
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/server.d.ts +6 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +47 -21
- package/dist/web/server.js.map +1 -1
- package/dist/web/session-listener-wiring.d.ts +1 -0
- package/dist/web/session-listener-wiring.d.ts.map +1 -1
- package/dist/web/session-listener-wiring.js +11 -0
- package/dist/web/session-listener-wiring.js.map +1 -1
- package/package.json +6 -4
- package/scripts/postinstall.js +16 -0
- package/skills/codeman/SKILL.md +6 -0
- package/README.zh-CN.md +0 -1139
- package/dist/web/public/app.b9516c7b.js +0 -43
- package/dist/web/public/app.b9516c7b.js.br +0 -0
- package/dist/web/public/app.b9516c7b.js.gz +0 -0
- package/dist/web/public/constants.d95fade9.js.br +0 -0
- package/dist/web/public/constants.d95fade9.js.gz +0 -0
- package/dist/web/public/i18n.52f5b7cc.js +0 -1
- package/dist/web/public/i18n.52f5b7cc.js.br +0 -0
- package/dist/web/public/i18n.52f5b7cc.js.gz +0 -0
- package/dist/web/public/image-input.a216cf9e.js.br +0 -0
- package/dist/web/public/image-input.a216cf9e.js.gz +0 -0
- package/dist/web/public/mobile-handlers.23a85db1.js.br +0 -0
- package/dist/web/public/mobile-handlers.23a85db1.js.gz +0 -0
- package/dist/web/public/mobile.1aa4952d.css +0 -1
- package/dist/web/public/mobile.1aa4952d.css.br +0 -0
- package/dist/web/public/mobile.1aa4952d.css.gz +0 -0
- package/dist/web/public/notification-manager.50bb87d8.js.br +0 -0
- package/dist/web/public/notification-manager.50bb87d8.js.gz +0 -0
- package/dist/web/public/panels-ui.6a5898d9.js.br +0 -0
- package/dist/web/public/panels-ui.6a5898d9.js.gz +0 -0
- package/dist/web/public/session-ui.6bddf916.js +0 -89
- package/dist/web/public/session-ui.6bddf916.js.br +0 -0
- package/dist/web/public/session-ui.6bddf916.js.gz +0 -0
- package/dist/web/public/settings-ui.6e798b7b.js +0 -97
- package/dist/web/public/settings-ui.6e798b7b.js.br +0 -0
- package/dist/web/public/settings-ui.6e798b7b.js.gz +0 -0
- package/dist/web/public/styles.2d175c60.css +0 -1
- package/dist/web/public/styles.2d175c60.css.br +0 -0
- package/dist/web/public/styles.2d175c60.css.gz +0 -0
- package/dist/web/public/subagent-windows.e6ca799f.js.br +0 -0
- package/dist/web/public/subagent-windows.e6ca799f.js.gz +0 -0
- package/dist/web/public/tab-rail-resize.94cd59f0.js.br +0 -0
- package/dist/web/public/terminal-keycode229-recovery.fb91b25b.js +0 -1
- package/dist/web/public/terminal-keycode229-recovery.fb91b25b.js.br +0 -0
- package/dist/web/public/terminal-keycode229-recovery.fb91b25b.js.gz +0 -0
- package/dist/web/public/terminal-ui.a4535311.js +0 -2
- package/dist/web/public/terminal-ui.a4535311.js.br +0 -0
- package/dist/web/public/terminal-ui.a4535311.js.gz +0 -0
- package/dist/web/public/upload.html +0 -155
- package/dist/web/public/upload.html.br +0 -0
- package/dist/web/public/upload.html.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.bbb5f84c.js +0 -4
- package/dist/web/public/vendor/xterm-zerolag-input.bbb5f84c.js.br +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.bbb5f84c.js.gz +0 -0
- package/dist/web/public/voice-input.c4b51eb6.js.br +0 -0
- package/dist/web/public/voice-input.c4b51eb6.js.gz +0 -0
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
"use strict";const _crashDiag={_entries:[],_maxEntries:50,_pageId:Date.now().toString(36)+"-"+Math.random().toString(36).slice(2,8),log(S){const e=typeof CodemanDiag<"u"?CodemanDiag:null,t=e?.sanitizeDiagEntry?e.sanitizeDiagEntry(S):String(S??"").replace(/[\r\n\u2028\u2029]+/g," ").slice(0,e?.DIAG_ENTRY_MAX_CHARS??300),s=`${new Date().toISOString().slice(11,23)} ${t}`;this._entries.push(s),this._entries.length>this._maxEntries&&this._entries.shift();try{localStorage.setItem("codeman-crash-diag",this._entries.join(`
|
|
2
|
-
`))}catch{}}};try{const S=localStorage.getItem("codeman-crash-diag");S&&(console.log(`[CRASH-DIAG] Previous session breadcrumbs:
|
|
3
|
-
`+S),navigator.sendBeacon(CodemanBase.url("/api/crash-diag"),JSON.stringify({data:S,id:_crashDiag._pageId+"-prev"})))}catch{}_crashDiag.log("PAGE LOAD");function _crashDiagBeacon(){try{_crashDiag._entries.length>0&&navigator.sendBeacon(CodemanBase.url("/api/crash-diag"),JSON.stringify({data:_crashDiag._entries.join(`
|
|
4
|
-
`),id:_crashDiag._pageId}))}catch{}}if(setInterval(()=>{try{localStorage.setItem("codeman-crash-heartbeat",String(Date.now()))}catch{}_crashDiagBeacon()},2e3),document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&_crashDiagBeacon()}),window.addEventListener("error",S=>{_crashDiag.log(`ERROR: ${S.message} at ${S.filename}:${S.lineno}`),console.error("[CRASH-DIAG] Uncaught error:",S.message,`
|
|
5
|
-
File:`,S.filename,":",S.lineno,":",S.colno,`
|
|
6
|
-
Stack:`,S.error?.stack)}),window.addEventListener("unhandledrejection",S=>{_crashDiag.log(`UNHANDLED: ${S.reason?.message||S.reason}`),console.error("[CRASH-DIAG] Unhandled promise rejection:",S.reason?.message||S.reason,`
|
|
7
|
-
Stack:`,S.reason?.stack)}),typeof PerformanceObserver<"u")try{new PerformanceObserver(e=>{for(const t of e.getEntries())t.duration>200&&(_crashDiag.log(`LONG_TASK: ${t.duration.toFixed(0)}ms`),console.warn(`[CRASH-DIAG] Long task: ${t.duration.toFixed(0)}ms (type: ${t.entryType}, name: ${t.name})`))}).observe({type:"longtask",buffered:!0})}catch{}const _origGetContext=HTMLCanvasElement.prototype.getContext;HTMLCanvasElement.prototype.getContext=function(S,...e){const t=_origGetContext.call(this,S,...e);return(S==="webgl2"||S==="webgl")&&(this.addEventListener("webglcontextlost",s=>{_crashDiag.log(`WEBGL_LOST: ${this.width}x${this.height}`),console.error("[CRASH-DIAG] WebGL context LOST on canvas",this.width,"x",this.height,"\u2014 prevented:",s.defaultPrevented)}),this.addEventListener("webglcontextrestored",()=>{_crashDiag.log("WEBGL_RESTORED"),console.warn("[CRASH-DIAG] WebGL context restored")})),t};const _SSE_HANDLER_MAP=[[SSE_EVENTS.INIT,"_onInit"],[SSE_EVENTS.SESSION_CREATED,"_onSessionCreated"],[SSE_EVENTS.SESSION_UPDATED,"_onSessionUpdated"],[SSE_EVENTS.SESSION_DELETED,"_onSessionDeleted"],[SSE_EVENTS.SESSION_TERMINAL,"_onSSETerminal"],[SSE_EVENTS.SESSION_NEEDS_REFRESH,"_onSSENeedsRefresh"],[SSE_EVENTS.SESSION_CLEAR_TERMINAL,"_onSSEClearTerminal"],[SSE_EVENTS.SESSION_COMPLETION,"_onSessionCompletion"],[SSE_EVENTS.SESSION_ERROR,"_onSessionError"],[SSE_EVENTS.SESSION_EXIT,"_onSessionExit"],[SSE_EVENTS.SESSION_IDLE,"_onSessionIdle"],[SSE_EVENTS.SESSION_WORKING,"_onSessionWorking"],[SSE_EVENTS.SESSION_AUTO_CLEAR,"_onSessionAutoClear"],[SSE_EVENTS.SESSION_LIMIT_PAUSE_SCHEDULED,"_onSessionLimitPauseScheduled"],[SSE_EVENTS.SESSION_LIMIT_RESUME,"_onSessionLimitResume"],[SSE_EVENTS.SESSION_LIMIT_RESUME_CANCELLED,"_onSessionLimitResumeCancelled"],[SSE_EVENTS.SESSION_RESPAWN_BREAKER_TRIPPED,"_onSessionRespawnBreakerTripped"],[SSE_EVENTS.SESSION_CLI_INFO,"_onSessionCliInfo"],[SSE_EVENTS.SESSION_STATUS_TELEMETRY,"_onSessionStatusTelemetry"],[SSE_EVENTS.SCHEDULED_CREATED,"_onScheduledCreated"],[SSE_EVENTS.SCHEDULED_UPDATED,"_onScheduledUpdated"],[SSE_EVENTS.SCHEDULED_COMPLETED,"_onScheduledCompleted"],[SSE_EVENTS.SCHEDULED_STOPPED,"_onScheduledStopped"],[SSE_EVENTS.CRON_JOBS_CHANGED,"_onCronJobsChanged"],[SSE_EVENTS.CRON_JOB_DELETED,"_onCronJobsChanged"],[SSE_EVENTS.CRON_RUN_CREATED,"_onCronRunChanged"],[SSE_EVENTS.CRON_RUN_UPDATED,"_onCronRunChanged"],[SSE_EVENTS.RESPAWN_STARTED,"_onRespawnStarted"],[SSE_EVENTS.RESPAWN_STOPPED,"_onRespawnStopped"],[SSE_EVENTS.RESPAWN_STATE_CHANGED,"_onRespawnStateChanged"],[SSE_EVENTS.RESPAWN_CYCLE_STARTED,"_onRespawnCycleStarted"],[SSE_EVENTS.RESPAWN_BLOCKED,"_onRespawnBlocked"],[SSE_EVENTS.RESPAWN_AUTO_ACCEPT_SENT,"_onRespawnAutoAcceptSent"],[SSE_EVENTS.RESPAWN_DETECTION_UPDATE,"_onRespawnDetectionUpdate"],[SSE_EVENTS.RESPAWN_TIMER_STARTED,"_onRespawnTimerStarted"],[SSE_EVENTS.RESPAWN_TIMER_CANCELLED,"_onRespawnTimerCancelled"],[SSE_EVENTS.RESPAWN_TIMER_COMPLETED,"_onRespawnTimerCompleted"],[SSE_EVENTS.RESPAWN_ERROR,"_onRespawnError"],[SSE_EVENTS.RESPAWN_ACTION_LOG,"_onRespawnActionLog"],[SSE_EVENTS.TASK_CREATED,"_onTaskCreated"],[SSE_EVENTS.TASK_COMPLETED,"_onTaskCompleted"],[SSE_EVENTS.TASK_FAILED,"_onTaskFailed"],[SSE_EVENTS.TASK_UPDATED,"_onTaskUpdated"],[SSE_EVENTS.MUX_CREATED,"_onMuxCreated"],[SSE_EVENTS.MUX_KILLED,"_onMuxKilled"],[SSE_EVENTS.MUX_DIED,"_onMuxDied"],[SSE_EVENTS.MUX_STATS_UPDATED,"_onMuxStatsUpdated"],[SSE_EVENTS.REMOTE_SESSION_RECONNECTED,"_onRemoteSessionReconnected"],[SSE_EVENTS.REMOTE_RECONNECT_EXHAUSTED,"_onRemoteReconnectExhausted"],[SSE_EVENTS.REMOTE_HOST_WAKING,"_onRemoteHostWaking"],[SSE_EVENTS.REMOTE_HOST_WAKE_FAILED,"_onRemoteHostWakeFailed"],[SSE_EVENTS.SESSION_RALPH_LOOP_UPDATE,"_onRalphLoopUpdate"],[SSE_EVENTS.SESSION_RALPH_TODO_UPDATE,"_onRalphTodoUpdate"],[SSE_EVENTS.SESSION_RALPH_COMPLETION_DETECTED,"_onRalphCompletionDetected"],[SSE_EVENTS.SESSION_RALPH_STATUS_UPDATE,"_onRalphStatusUpdate"],[SSE_EVENTS.SESSION_CIRCUIT_BREAKER_UPDATE,"_onCircuitBreakerUpdate"],[SSE_EVENTS.SESSION_EXIT_GATE_MET,"_onExitGateMet"],[SSE_EVENTS.SESSION_BASH_TOOL_START,"_onBashToolStart"],[SSE_EVENTS.SESSION_BASH_TOOL_END,"_onBashToolEnd"],[SSE_EVENTS.SESSION_BASH_TOOLS_UPDATE,"_onBashToolsUpdate"],[SSE_EVENTS.HOOK_IDLE_PROMPT,"_onHookIdlePrompt"],[SSE_EVENTS.HOOK_PERMISSION_PROMPT,"_onHookPermissionPrompt"],[SSE_EVENTS.HOOK_ELICITATION_DIALOG,"_onHookElicitationDialog"],[SSE_EVENTS.HOOK_ELICITATION_COMPLETE,"_onHookElicitationComplete"],[SSE_EVENTS.HOOK_ELICITATION_RESPONSE,"_onHookElicitationResponse"],[SSE_EVENTS.HOOK_STOP,"_onHookStop"],[SSE_EVENTS.HOOK_AGENT_WORKING,"_onHookAgentWorking"],[SSE_EVENTS.HOOK_TEAMMATE_IDLE,"_onHookTeammateIdle"],[SSE_EVENTS.HOOK_TASK_COMPLETED,"_onHookTaskCompleted"],[SSE_EVENTS.APPROVAL_PENDING,"_onApprovalPending"],[SSE_EVENTS.APPROVAL_UPDATED,"_onApprovalUpdated"],[SSE_EVENTS.APPROVAL_RESOLVED,"_onApprovalResolved"],[SSE_EVENTS.SUBAGENT_DISCOVERED,"_onSubagentDiscovered"],[SSE_EVENTS.SUBAGENT_UPDATED,"_onSubagentUpdated"],[SSE_EVENTS.SUBAGENT_TOOL_CALL,"_onSubagentToolCall"],[SSE_EVENTS.SUBAGENT_PROGRESS,"_onSubagentProgress"],[SSE_EVENTS.SUBAGENT_MESSAGE,"_onSubagentMessage"],[SSE_EVENTS.SUBAGENT_TOOL_RESULT,"_onSubagentToolResult"],[SSE_EVENTS.SUBAGENT_COMPLETED,"_onSubagentCompleted"],[SSE_EVENTS.WORKFLOW_RUN_DISCOVERED,"_onWorkflowRunDiscovered"],[SSE_EVENTS.WORKFLOW_RUN_UPDATED,"_onWorkflowRunUpdated"],[SSE_EVENTS.WORKFLOW_RUN_REMOVED,"_onWorkflowRunRemoved"],[SSE_EVENTS.IMAGE_DETECTED,"_onImageDetected"],[SSE_EVENTS.ATTACHMENT_DETECTED,"_onAttachmentDetected"],[SSE_EVENTS.TUNNEL_STARTED,"_onTunnelStarted"],[SSE_EVENTS.TUNNEL_STOPPED,"_onTunnelStopped"],[SSE_EVENTS.TUNNEL_PROGRESS,"_onTunnelProgress"],[SSE_EVENTS.TUNNEL_ERROR,"_onTunnelError"],[SSE_EVENTS.TUNNEL_QR_ROTATED,"_onTunnelQrRotated"],[SSE_EVENTS.TUNNEL_QR_REGENERATED,"_onTunnelQrRegenerated"],[SSE_EVENTS.TUNNEL_QR_AUTH_USED,"_onTunnelQrAuthUsed"],[SSE_EVENTS.PLAN_SUBAGENT,"_onPlanSubagent"],[SSE_EVENTS.PLAN_PROGRESS,"_onPlanProgress"],[SSE_EVENTS.PLAN_STARTED,"_onPlanStarted"],[SSE_EVENTS.PLAN_CANCELLED,"_onPlanCancelled"],[SSE_EVENTS.PLAN_COMPLETED,"_onPlanCompleted"],[SSE_EVENTS.ORCHESTRATOR_STATE_CHANGED,"_onOrchestratorStateChanged"],[SSE_EVENTS.ORCHESTRATOR_PLAN_PROGRESS,"_onOrchestratorPlanProgress"],[SSE_EVENTS.ORCHESTRATOR_PLAN_READY,"_onOrchestratorPlanReady"],[SSE_EVENTS.ORCHESTRATOR_PHASE_STARTED,"_onOrchestratorPhaseStarted"],[SSE_EVENTS.ORCHESTRATOR_PHASE_COMPLETED,"_onOrchestratorPhaseCompleted"],[SSE_EVENTS.ORCHESTRATOR_PHASE_FAILED,"_onOrchestratorPhaseFailed"],[SSE_EVENTS.ORCHESTRATOR_VERIFICATION,"_onOrchestratorVerification"],[SSE_EVENTS.ORCHESTRATOR_TASK_ASSIGNED,"_onOrchestratorTaskAssigned"],[SSE_EVENTS.ORCHESTRATOR_TASK_COMPLETED,"_onOrchestratorTaskCompleted"],[SSE_EVENTS.ORCHESTRATOR_TASK_FAILED,"_onOrchestratorTaskFailed"],[SSE_EVENTS.ORCHESTRATOR_COMPLETED,"_onOrchestratorCompleted"],[SSE_EVENTS.ORCHESTRATOR_ERROR,"_onOrchestratorError"],[SSE_EVENTS.CLIPBOARD_WRITE,"_onClipboardWrite"],[SSE_EVENTS.SESSION_ORDER_CHANGED,"_onSessionOrderChanged"],[SSE_EVENTS.TAB_LAYOUT_CHANGED,"_onTabLayoutChanged"],[SSE_EVENTS.WEBVIEW_CHANGED,"_onWebviewChanged"]];function parseSessionPrefix(S){if(!S)return null;const e=S.match(/^(w\d+-[a-zA-Z0-9_-]+|s\d+-[a-zA-Z0-9_-]+)/);if(!e)return null;const t=e[1],s=S.slice(t.length);return s===""?{prefix:t,suffix:""}:s.startsWith(": ")?{prefix:t,suffix:s.slice(2)}:null}function paneExitLabel(S){return!S||typeof S!="object"?"":typeof S.signal=="number"&&S.signal>0?`exited (signal ${S.signal})`:typeof S.status=="number"?`exited (${S.status})`:"exited"}function paneExitAriaLabel(S,e){return e?`${S} session, agent ${e}`:`${S} session`}function applyPaneExitBadge(S,e){const t=paneExitLabel(e),s=S.querySelector(".tab-exited-badge");S.classList.toggle("tab-agent-exited",!!t);const i=S.querySelector(".tab-name")?.dataset?.fullName;if(i&&S.setAttribute("aria-label",paneExitAriaLabel(i,t)),!t){s?.remove();return}if(!s){const n=document.createElement("span");n.className="tab-exited-badge",n.setAttribute("aria-hidden","true"),n.setAttribute("data-i18n-skip",""),n.textContent=t,S.querySelector(".tab-name")?.insertAdjacentElement("afterend",n);return}s.textContent!==t&&(s.textContent=t)}const DEFAULT_SHORTCUTS=[{id:"show-shortcuts",group:"Panels",label:"Show Shortcuts",bindings:[{modifiers:["ctrl"],key:"?",code:"Slash"},{modifiers:["ctrl","shift"],key:"?"},{modifiers:["alt"],key:"?",code:"Slash"}],action:"showShortcutOverlay"},{id:"close-session",group:"Session",label:"Close Session",bindings:[{modifiers:["ctrl"],key:"w"}],action:"killActiveSession"},{id:"next-session",group:"Session",label:"Next Session",bindings:[{modifiers:["ctrl"],key:"Tab"}],action:"nextSession"},{id:"clear-terminal",group:"Terminal",label:"Clear Terminal",bindings:[{modifiers:["ctrl"],key:"l"}],action:"clearTerminal"},{id:"copy-selection",group:"Terminal",label:"Copy Selection",bindings:[{modifiers:["ctrl"],key:"c"},{modifiers:["ctrl","shift"],key:"C"}],action:"copyTerminalSelection"},{id:"increase-font",group:"Terminal",label:"Increase Font",bindings:[{modifiers:["ctrl"],key:"=",code:"Equal"},{modifiers:["ctrl"],key:"+",code:"Equal"}],action:"increaseFontSize"},{id:"decrease-font",group:"Terminal",label:"Decrease Font",bindings:[{modifiers:["ctrl"],key:"-",code:"Minus"}],action:"decreaseFontSize"},{id:"voice-input",group:"Terminal",label:"Voice Input",bindings:[{modifiers:["ctrl","shift"],key:"V"}],action:"toggleVoiceInput"},{id:"restore-terminal-size",group:"Terminal",label:"Restore Terminal Size",bindings:[{modifiers:["ctrl","shift"],key:"R"}],action:"restoreTerminalSize"},{id:"move-tab-left",group:"Tabs",label:"Move Active Tab Left",bindings:[{modifiers:["ctrl","shift"],key:"{",code:"BracketLeft"}],action:"moveActiveTabLeft"},{id:"move-tab-right",group:"Tabs",label:"Move Active Tab Right",bindings:[{modifiers:["ctrl","shift"],key:"}",code:"BracketRight"}],action:"moveActiveTabRight"},{id:"command-palette",group:"Session",label:"Find Open Session",bindings:[{modifiers:["ctrl"],key:"k",code:"KeyK"},{modifiers:["meta"],key:"k",code:"KeyK"},{modifiers:["alt"],key:"k",code:"KeyK"}],action:"openCommandPalette"},{id:"toggle-session-sidebar",group:"Session",label:"Toggle Session Sidebar",bindings:[{modifiers:["alt"],key:"b",code:"KeyB"}],action:"toggleSessionSidebar"},{id:"previous-next-session",group:"Session",label:"Previous / Next Session",displayBindings:["Alt/Option+[","Alt/Option+]"]},{id:"switch-tab-n",group:"Session",label:"Switch to Tab N",displayBindings:["Alt/Option+1-9"]},{id:"focus-tabs",group:"Tabs",label:"Focus Tabs",displayBindings:["ArrowLeft","ArrowRight","Home","End"]},{id:"activate-focused-tab",group:"Tabs",label:"Activate Focused Tab",displayBindings:["Enter","Space"]},{id:"insert-newline",group:"Terminal",label:"Insert Newline",displayBindings:["Shift+Enter","Ctrl+Enter"]},{id:"close-panels",group:"Panels",label:"Close Panels",displayBindings:["Escape"]}],SIDEBAR_RICH_CLOCK_MS=2e4,URL_SESSION_WAIT_MS=3e4,TAB_LAYOUT_PENDING_MAX_AGE_MS=6e4;class CodemanApp{constructor(){this.sessions=new Map,this._shortIdCache=new Map,this.sessionOrder=[],this.draggedTabId=null,this.tabLayout=null,this.collapsedTabGroupIds=new Set,this._hiddenTabGroupByRef=new Map,this._lastTabGroupStructureKey=null,this.cases=[],this.currentRun=null,this.totalTokens=0,this.globalStats=null,this.eventSource=null,this._clientId=typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"c-"+Math.random().toString(36).slice(2)+Date.now().toString(36),this._wsTabNonce=this._clientId,this.terminal=null,this.fitAddon=null,this.activeSessionId=null,this.soloSessionId=this._detectSoloSessionId(),this.isSoloWindow=!!this.soloSessionId,this._urlSessionId=this.isSoloWindow?null:this._takeUrlSession(),this._urlSessionWaitTimer=null,this.detachedSessions=new Set,this.detachedWindows=new Map,this._detachWatchTimers=new Map,this.windowChannel=null,this._redockGrace=new Map,this._detachPingPending=null,this._detachLivenessTimer=null,this._detachOrphanStrikes=new Map,this._initGeneration=0,this._initFallbackTimer=null,this._selectGeneration=0,this._fullHistoryLoaded=new Set,this._fullHistoryRepullAt=new Map,this._fullHistoryRepullInFlight=!1,this._fullHistoryRepullUseless=new Set,this._geometryRetryUseless=new Set,this.terminalLoadStates=new Map,this.respawnStatus={},this.respawnTimers={},this.respawnCountdownTimers={},this.respawnActionLogs={},this.timerCountdownInterval=null,this.terminalBuffers=new Map,this.editingSessionId=null,this.pendingCloseSessionId=null,this.muxSessions=[],this.ralphStates=new Map,this.subagents=new Map,this.subagentActivity=new Map,this.subagentToolResults=new Map,this.activeSubagentId=null,this.subagentPanelVisible=!1,this.workflowRuns=new Map,this.workflowRunDetails=new Map,this.activeWorkflowRunId=null,this.activeWorkflowPhaseIndex=null,this.ultracodeWindows=new Map,this.ultracodeWindowsClosed=new Set,this.ultracodeWindowCloseTimers=new Map,this.ultracodeWindowZIndex=1e3,this.subagentWindows=new Map,this.subagentWindowZIndex=ZINDEX_SUBAGENT_BASE,this.minimizedSubagents=new Map,this._subagentHideTimeout=null,this.subagentParentMap=new Map,this.teams=new Map,this.teamTasks=new Map,this.teammateMap=new Map,this.teammatePanesByName=new Map,this.teammateTerminals=new Map,this.terminalBufferCache=new Map,this.ralphStatePanelCollapsed=!0,this.ralphClosedSessions=new Set,this.planSubagents=new Map,this.planSubagentWindowZIndex=ZINDEX_PLAN_SUBAGENT_BASE,this.planGenerationStopped=!1,this.planAgentsMinimized=!1,this.wizardDragState=null,this.wizardDragListeners=null,this.wizardPosition=null,this.projectInsights=new Map,this.logViewerWindows=new Map,this.logViewerWindowZIndex=ZINDEX_LOG_VIEWER_BASE,this.projectInsightsPanelVisible=!1,this.orchestratorState=null,this.orchestratorPanelVisible=!1,this.currentSessionWorkingDir=null,this.imagePopups=new Map,this.imagePopupZIndex=ZINDEX_IMAGE_POPUP_BASE,this.attachmentCards=new Map,this.attachmentCardStack=null,this.attachmentHistoryCounts=new Map,this.attachmentHistoryItems=[],this.attachmentHistoryDrawerOpen=!1,this.fileBrowserData=null,this.fileBrowserExpandedDirs=new Set,this.fileBrowserFilter="",this.fileBrowserAllExpanded=!1,this.fileBrowserDragListeners=null,this.fileBrowserShowHidden=this._loadFileBrowserShowHidden?.()??!1,this.filePreviewContent="",this._toastContainer=null,this._tunnelUrl=null,this.tabAlerts=new Map,this.pendingHooks=new Map,this._closingSessions=new Set,this.approvals=new Map,this._ws=null,this._wsSessionId=null,this._wsReady=!1,this._wsState="disconnected",this._wsLastRecvAt=0,this._wsOutputGapSession=null,this.pendingWrites=[],this.writeFrameScheduled=!1,this._terminalWriteInFlight=!1,this._terminalWriteInFlightBytes=0,this._wasAtBottomBeforeWrite=!0,this.syncWaitTimeout=null,this._isLoadingBuffer=!1,this._loadBufferQueue=null,this._bufferLoadSeq=0,this._bufferLoadOwner=null,this._terminalRefreshOwner=null,this.flickerFilterBuffer="",this.flickerFilterActive=!1,this.flickerFilterTimeout=null,this._debounceTimers=Object.create(null),this.systemStatsInterval=null,this.sseReconnectTimeout=null,this._sseListenerCleanup=null,this.reconnectAttempts=0,this.maxReconnectAttempts=10,this.isOnline=navigator.onLine,this._sseLastMessageAt=0,this._sseStaleTimeoutMs=window.CodemanSseStale?.TIMEOUT_MS??45e3,this._sseStaleWatchdog=null,this._connDownSince=null,this._nextSseRetryAt=null,this._offlineOverlayDismissed=!1,this._offlineRetryPending=!1,this._offlineUiTicker=null,this._lastOfflineUiKey="",this._connectionStatus="connected",this._clientId="",this._seqCounters=new Map,this._pendingDeliveries=new Map,this._lastIndicatorDescriptor=null,this._postDraining=new Set,this._persistReliableTimer=null,this._reliableAckTimeoutMs=4e3,this._reliableMaxBytes=256*1024,this._loadReliableState(),this._reliableSweepTimer=setInterval(()=>this._redeliverSweep(),2e3),window.addEventListener("pagehide",()=>this._persistReliableNow()),window.addEventListener("pagehide",()=>this._persistPendingTabLayoutEdits()),document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"?this._persistReliableNow():this._checkSseStale()}),this._localEchoOverlay=null,this._localEchoEnabled=!1,this._predictiveEcho=null,this._localEchoPolicy="off",this._restoringFlushedState=!1,this.activeFocusTrap=null,this.notificationManager=new NotificationManager(this),this.idleTimers=new Map,this._elemCache={},this.init()}$(e){return this._elemCache[e]||(this._elemCache[e]=document.getElementById(e)),this._elemCache[e]}_clearTimer(e){this[e]&&(clearTimeout(this[e]),this[e]=null)}_isStaleSelect(e){return e!==this._selectGeneration?(this._isLoadingBuffer&&this._finishBufferLoad(e),this._restoringFlushedState=!1,!0):!1}formatTokens(e){if(e>=1e6){const t=e/1e6;return t>=10?`${t.toFixed(1)}m`:`${t.toFixed(2)}m`}else if(e>=1e3){const t=e/1e3;return t>=100?`${t.toFixed(0)}k`:`${t.toFixed(1)}k`}return String(e)}estimateCost(e,t){const s=e/1e6*15,i=t/1e6*75;return s+i}setPendingHook(e,t){this.pendingHooks.has(e)||this.pendingHooks.set(e,new Set),this.pendingHooks.get(e).add(t),this.updateTabAlertFromHooks(e)}clearPendingHooks(e,t=null){const s=this.pendingHooks.get(e);s&&(t?s.delete(t):s.clear(),s.size===0&&this.pendingHooks.delete(e),this.updateTabAlertFromHooks(e))}markIdleAlertSeen(e){this.pendingHooks?.get(e)?.has("idle_prompt")&&(this.clearPendingHooks(e,"idle_prompt"),this.acknowledgeIdleApprovalOnView?.(e))}updateTabAlertFromHooks(e){const t=this.pendingHooks.get(e);!t||t.size===0?this.tabAlerts.delete(e):t.has("permission_prompt")||t.has("elicitation_dialog")?this.tabAlerts.set(e,"action"):t.has("idle_prompt")&&this.tabAlerts.set(e,"idle"),this.renderSessionTabs()}init(){MobileDetection.init(),this._initWindowChannel(),this.isSoloWindow&&document.body.classList.add("solo-mode"),this.isSoloWindow||window.addEventListener("hashchange",()=>{const s=this._takeUrlSession();s&&(this._retireUrlSession(),this._urlSessionId=s,this._selectUrlSession())}),KeyboardHandler.init(),SwipeHandler.init(),VoiceInput.init(),KeyboardAccessoryBar.init();const e=this.loadAppSettingsFromStorage();KeyboardAccessoryBar.setMode(e.extendedKeyboardBar?"extended":"simple"),this.applyHeaderVisibilitySettings(),this.restorePlanUsageChip(),this.applySkin(),this.applyLocalization(),this.applySessionListLayout(),this.applyTabOrientation(),this.initTabRailResize?.(),this.applyMonitorVisibility(),this.applyLineageLineSettings?.(),this._installLineageStripScrollListener?.(),this._setupTabMiddleClickClose(),this.initEntranceAnimations?.(),document.documentElement.classList.remove("mobile-init"),requestAnimationFrame(()=>{this.initTerminal(),this.loadFontSize(),this.connectSSE(),this._initFallbackTimer=setTimeout(()=>{this._initGeneration===0&&this.loadState()},3e3)}),this.registerServiceWorker(),this.loadTunnelStatus(),this.initRebootRestoreBanner?.();const t=fetch("/api/settings").then(s=>s.ok?s.json():null).then(s=>s?.data??null).catch(()=>null);if(this.loadQuickStartCases(null,t),this._initRunMode(),this.initWebviews?.(),this.setupEventListeners(),MobileDetection.isTouchDevice()){const s=i=>{i&&i.addEventListener("touchstart",n=>{if(!KeyboardHandler.keyboardVisible)return;const o=n.target.closest("button");o&&(n.preventDefault(),o.click(),typeof app<"u"&&app.terminal&&app.terminal.focus())},{passive:!1})};s(document.querySelector(".toolbar")),s(document.querySelector(".welcome-overlay"))}this.setupOnlineDetection(),this.loadAppSettingsFromServer(t).then(()=>{this.applyHeaderVisibilitySettings(),this.applySkin(),this.applyLocalization(),this.applySessionListLayout(),this.applyTabOrientation?.(),this.applyMonitorVisibility(),this.applyLineageLineSettings?.(),typeof this.syncAllUltracodeFloatingWindows=="function"&&this.syncAllUltracodeFloatingWindows()}),document.body.classList.add("app-loaded")}_initWebGL(){if(!(typeof WebglAddon>"u"))try{this._webglAddon=new WebglAddon.WebglAddon,this._webglAddon.onContextLoss(()=>{console.error("[CRASH-DIAG] WebGL context LOST \u2014 falling back to canvas renderer"),_crashDiag.log("WEBGL_LOST"),this._disableWebGLSticky("context-lost"),this._disposeWebGLObserver(),this._webglAddon?.dispose(),this._webglAddon=null,this._scheduleTerminalRepaint()}),this.terminal.loadAddon(this._webglAddon),console.log("[CRASH-DIAG] WebGL renderer enabled"),this._installWebGLLongTaskGuard()}catch{}}_installWebGLLongTaskGuard(){if(typeof PerformanceObserver>"u"||this._webglLongTaskObserver)return;const e=performance.now(),t=[];try{this._webglLongTaskObserver=new PerformanceObserver(s=>{if(!this._webglAddon)return;const i=performance.now();i-e<WEBGL_FALLBACK.GRACE_MS||evaluateWebGLLongTaskTrip(t,s.getEntries(),i)&&(console.warn(`[CRASH-DIAG] WebGL long-task threshold (${t.length} stalls/${WEBGL_FALLBACK.WINDOW_MS}ms) \u2014 falling back to canvas renderer`),_crashDiag.log(`WEBGL_FALLBACK: ${t.length}`),this._disableWebGLSticky("long-tasks"),this._disposeWebGLObserver(),this._webglAddon?.dispose(),this._webglAddon=null,this._scheduleTerminalRepaint())}),this._webglLongTaskObserver.observe({type:"longtask",buffered:!1})}catch{}}_disposeWebGLObserver(){if(this._webglLongTaskObserver){try{this._webglLongTaskObserver.disconnect()}catch{}this._webglLongTaskObserver=null}}_scheduleTerminalRepaint(){if(this._terminalRepaintScheduled)return;this._terminalRepaintScheduled=!0,(typeof requestAnimationFrame=="function"?requestAnimationFrame:t=>setTimeout(t,0))(()=>{this._terminalRepaintScheduled=!1;try{this.terminal?.refresh(0,this.terminal.rows-1)}catch{}})}_disableWebGLSticky(e){try{localStorage.setItem("codeman-webgl-disabled",JSON.stringify({reason:e,at:Date.now()}))}catch{}}setupEventListeners(){const e={showShortcutOverlay:()=>this.showShortcutOverlay(),killActiveSession:()=>this.killActiveSession(),nextSession:()=>this.nextSession(),clearTerminal:()=>this.clearTerminal(),restoreTerminalSize:()=>this.restoreTerminalSize(),increaseFontSize:()=>this.increaseFontSize(),decreaseFontSize:()=>this.decreaseFontSize(),toggleVoiceInput:()=>VoiceInput.toggle(),moveActiveTabLeft:()=>this.moveActiveTabLeft(),moveActiveTabRight:()=>this.moveActiveTabRight(),toggleSessionSidebar:()=>this.toggleSessionSidebar()};document.addEventListener("keydown",s=>{if(!s.target?.closest?.("[data-raw-keys]")&&!(s.isComposing||s.keyCode===229)){if(this.shouldOpenCommandPaletteFromShortcut?.(s)){s.preventDefault(),this.openCommandPalette();return}if(s.key==="Escape"){if(this._tabGroupMenu&&this._tabGroupMenuKeydown){this._tabGroupMenuKeydown(s);return}if(this._tabLayoutDrag?.active&&this._tabLayoutDragKeydown){this._tabLayoutDragKeydown(s);return}this.closeAllPanels(),this.closeHelp(),this.attachmentHistoryDrawerOpen&&this.closeAttachmentHistory(),this.closeSessionManager(),this.closeCommandPalette?.(),this.closeShortcutOverlay?.(),this._isSessionSidebarOverlay()&&this.isSessionSidebarActive()&&!this.isSessionSidebarCollapsed()&&(this.toggleSessionSidebar(),document.getElementById("sidebarToggleBtn")?.focus())}if(s.altKey&&!s.ctrlKey&&!s.shiftKey){const n=(s.code||"").match(/^Digit([1-9])$/);if(n){const o=parseInt(n[1],10)-1,a=this.sessionOrder.filter(r=>this.sessions.has(r));if(o<a.length)s.preventDefault(),this.selectSession(a[o]);else{const r=o-a.length,c=(this.webviewOrder||[])[r];c&&(s.preventDefault(),this.openWebview(c))}return}if(s.code==="BracketLeft"){s.preventDefault(),this.prevSession();return}if(s.code==="BracketRight"){s.preventDefault(),this.nextSession();return}}if(!(!s.ctrlKey&&!s.metaKey&&!s.altKey))for(const i of this.getShortcutRegistry()){if(i.disabled||!i.action)continue;const n=e[i.action];if(n&&this.matchesShortcutEvent(s,i)){s.preventDefault(),n();return}}}},!0);const t=this.$("headerTokens");t&&!t._statsHandlerAttached&&(t.classList.add("clickable"),t._statsHandlerAttached=!0,t.addEventListener("click",()=>this.openTokenStats())),this.setupColorPicker()}_updateSseSubscription(e){try{const t=JSON.stringify({clientId:this._clientId,sessions:e?[e]:null});fetch("/api/events/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:t,keepalive:!0}).catch(()=>{})}catch{}}_detectSoloSessionId(){try{if(typeof window<"u"&&typeof window.__CODEMAN_SOLO__=="string"&&window.__CODEMAN_SOLO__)return window.__CODEMAN_SOLO__;const e=window.CodemanBase?.base||"";let t=location.pathname;e&&t.startsWith(e)&&(t=t.slice(e.length)||"/");const s=t.match(/^\/session\/([^/]+)\/?$/);return s?decodeURIComponent(s[1]):null}catch{return null}}_takeUrlSession(){const e=window.CodemanUrlSession?.sessionIdFromFragment(location.hash)??null;if(e)try{history.replaceState(history.state,"",location.pathname+location.search)}catch{}return e}_selectUrlSession(){const e=this._urlSessionId;return e?this.sessions.has(e)?(this._retireUrlSession(),this.selectSession(e,{auto:!0}),!0):(this._armUrlSessionWait(e),!1):!1}_armUrlSessionWait(e){this._urlSessionWaitTimer||(this._urlSessionWaitTimer=setTimeout(()=>{if(this._urlSessionWaitTimer=null,this._urlSessionId===e){if(this.sessions.has(e)){this._selectUrlSession();return}this._retireUrlSession(),this.showToast?.("Session not found","warning")}},URL_SESSION_WAIT_MS))}_retireUrlSession(){this._urlSessionId=null,this._urlSessionWaitTimer&&(clearTimeout(this._urlSessionWaitTimer),this._urlSessionWaitTimer=null)}detachSession(e){if(this.isSoloWindow||!this.sessions.has(e)||this.detachedSessions.has(e)&&this._raiseDetached(e))return;const t="width=960,height=680,menubar=no,toolbar=no,location=no,status=no";let s=null;try{s=window.open(CodemanBase.url("/session/"+encodeURIComponent(e)),"codeman-session-"+e,t)}catch{}if(!s){this.showToast?.("Pop-out blocked \u2014 allow popups for this site to detach a session","error");return}this.detachedWindows.set(e,s),this._markDetached(e,!0),this._watchDetachedWindow(e,s),this._postWindowMessage({type:"detached",id:e});try{s.focus()}catch{}}_raiseDetached(e){const t=this.detachedWindows.get(e);if(t&&!t.closed){try{t.focus()}catch{}return!0}return t&&t.closed?(this._redock(e),!1):(this._postWindowMessage({type:"focus-request",id:e}),!0)}redockSession(e){const t=this.detachedWindows.get(e);if(t&&!t.closed)try{t.close()}catch{}this._postWindowMessage({type:"close-request",id:e}),this._redock(e)}_redock(e){const t=this._detachWatchTimers.get(e);t&&(clearInterval(t),this._detachWatchTimers.delete(e)),this._cancelPendingRedock(e),this._detachOrphanStrikes.delete(e),this.detachedWindows.delete(e),this._markDetached(e,!1),this._lastResizeDims=null,this.sessions.has(e)&&e===this.activeSessionId&&this.sendResize(e,{force:!0})?.catch?.(()=>{})}_scheduleRedock(e){if(this._redockGrace.has(e))return;const t=setTimeout(()=>{this._redockGrace.delete(e),this._redock(e)},1500);this._redockGrace.set(e,t)}_cancelPendingRedock(e){const t=this._redockGrace.get(e);t&&(clearTimeout(t),this._redockGrace.delete(e))}_markDetached(e,t){t?this.detachedSessions.add(e):this.detachedSessions.delete(e);const s=this.$("sessionTabs"),i=s&&s.querySelector(`.session-tab[data-id="${e}"]`);i&&i.classList.toggle("detached",t)}_watchDetachedWindow(e,t){const s=this._detachWatchTimers.get(e);s&&clearInterval(s);const i=setInterval(()=>{(!t||t.closed)&&(clearInterval(i),this._detachWatchTimers.delete(e),this._redock(e))},800);this._detachWatchTimers.set(e,i)}_initWindowChannel(){if(!(typeof BroadcastChannel>"u")){try{this.windowChannel=new BroadcastChannel("codeman-windows")}catch{this.windowChannel=null;return}if(this.windowChannel.onmessage=e=>this._onWindowMessage(e.data),this.isSoloWindow){this._postWindowMessage({type:"detached",id:this.soloSessionId});const e=()=>this._postWindowMessage({type:"redocked",id:this.soloSessionId});window.addEventListener("pagehide",e),window.addEventListener("beforeunload",e)}else this._postWindowMessage({type:"roll-call"}),this._startDetachLiveness()}}_postWindowMessage(e){try{this.windowChannel&&this.windowChannel.postMessage(e)}catch{}}_onWindowMessage(e){if(!(!e||typeof e!="object")){if(this.isSoloWindow){if(e.type==="roll-call"){this._postWindowMessage({type:"detached",id:this.soloSessionId});return}if(e.id!==this.soloSessionId)return;if(e.type==="close-request")try{window.close()}catch{}else if(e.type==="focus-request")try{window.focus()}catch{}return}e.type==="detached"&&e.id?(this._cancelPendingRedock(e.id),this._detachPingPending?.delete(e.id),this._detachOrphanStrikes.delete(e.id),this._markDetached(e.id,!0)):e.type==="redocked"&&e.id?this._scheduleRedock(e.id):e.type==="detach-request"&&e.id&&this.detachSession(e.id)}}_startDetachLiveness(){this._detachLivenessTimer||(this._detachLivenessTimer=setInterval(()=>this._pingDetached(),5e3))}_pingDetached(){const e=[];for(const t of this.detachedSessions){const s=this.detachedWindows.get(t);s?s.closed&&this._redock(t):e.push(t)}e.length&&(this._detachPingPending=new Set(e),this._postWindowMessage({type:"roll-call"}),setTimeout(()=>{if(this._detachPingPending){for(const t of this._detachPingPending){const s=(this._detachOrphanStrikes.get(t)||0)+1;s>=2?(this._detachOrphanStrikes.delete(t),this._redock(t)):this._detachOrphanStrikes.set(t,s)}this._detachPingPending=null}},1200))}_applySoloMode(){document.body.classList.add("solo-mode");const e=this.sessions.get(this.soloSessionId);if(!e){this._showSoloSessionGone();return}this.activeSessionId=null,this.selectSession(this.soloSessionId,{auto:!0});const t=this.getSessionName(e)||"Session",s=document.getElementById("soloSessionTitle");s&&(s.textContent=t,s.style.display="");const i=document.getElementById("soloRedockBtn");i&&(i.style.display=""),document.title=t+" \u2014 "+(window.CodemanI18n?.displayName||"Codeman"),this.notificationManager&&(this.notificationManager.originalTitle=document.title);const n=document.querySelector(".header-brand .logo");n&&(n.onclick=o=>{o.preventDefault()})}_showSoloSessionGone(){if(document.body.classList.add("solo-mode"),document.querySelector(".solo-gone-overlay"))return;const e=document.createElement("div");e.className="solo-gone-overlay",e.innerHTML='<h2>Session unavailable</h2><p>This session has ended or is no longer available.</p><button class="btn-primary" onclick="window.close()">Close window</button>',document.body.appendChild(e),document.title=(window.codemanT?.("Session ended")||"Session ended")+" \u2014 "+(window.CodemanI18n?.displayName||"Codeman")}connectSSE(){if(!navigator.onLine){this.setConnectionStatus("offline");return}this._clearTimer("sseReconnectTimeout"),this._sseStaleWatchdog&&(clearInterval(this._sseStaleWatchdog),this._sseStaleWatchdog=null),this._sseListenerCleanup&&(this._sseListenerCleanup(),this._sseListenerCleanup=null),this.eventSource&&(this.eventSource.close(),this.eventSource=null),this.reconnectAttempts===0?this.setConnectionStatus("connecting"):this.setConnectionStatus("reconnecting");const e=new URLSearchParams({clientId:this._clientId});this.activeSessionId&&e.set("sessions",this.activeSessionId),this.eventSource=new EventSource(CodemanBase.url(`/api/events?${e.toString()}`));const t=[],s=(i,n)=>{const o=a=>{this._sseLastMessageAt=Date.now(),n(a)};this.eventSource.addEventListener(i,o),t.push({event:i,handler:o})};if(this._sseListenerCleanup=()=>{for(const{event:i,handler:n}of t)this.eventSource&&this.eventSource.removeEventListener(i,n);t.length=0},this.eventSource.onopen=()=>{this.reconnectAttempts=0,this._sseLastMessageAt=Date.now(),this.setConnectionStatus("connected")},this.eventSource.onerror=()=>{this.reconnectAttempts++,this.reconnectAttempts>=this.maxReconnectAttempts?this.setConnectionStatus("disconnected"):this.setConnectionStatus("reconnecting"),this.eventSource&&(this.eventSource.close(),this.eventSource=null),this._clearTimer("sseReconnectTimeout");const i=this.reconnectAttempts<=1?200:Math.min(500*Math.pow(2,this.reconnectAttempts-2),3e4);this._nextSseRetryAt=Date.now()+i,this._updateConnectionLossUi(),this.sseReconnectTimeout=setTimeout(()=>this.connectSSE(),i)},!this._sseHandlerWrappers){this._sseHandlerWrappers=new Map;for(const[i,n]of _SSE_HANDLER_MAP){const o=this[n],a=n==="_onSSETerminal"||n==="_onSSENeedsRefresh"||n==="_onSSEClearTerminal";this._sseHandlerWrappers.set(i,r=>{if(!(a&&this._wsReady))try{o.call(this,r.data?JSON.parse(r.data):{})}catch(c){console.error(`[SSE] Error handling ${i}:`,c)}})}}for(const[i]of _SSE_HANDLER_MAP)s(i,this._sseHandlerWrappers.get(i));for(const i of[SSE_EVENTS.SESSION_CREATED,SSE_EVENTS.SESSION_DELETED])s(i,()=>this._onSessionListMaybeChanged());s(SSE_EVENTS.DOCKER_EXPORT_COMPLETE,i=>{try{const n=i.data?JSON.parse(i.data):{};this.showToast(`Docker export ready: ${n.bundle} (${Math.round((n.sizeBytes||0)/1e6)} MB)`,"success"),this.refreshDockerExports?.()}catch(n){console.error("[SSE] docker export complete:",n)}}),s(SSE_EVENTS.DOCKER_EXPORT_FAILED,i=>{try{const n=i.data?JSON.parse(i.data):{};this.showToast(`Docker export failed: ${n.error||"unknown error"}`,"error")}catch(n){console.error("[SSE] docker export failed:",n)}}),s(SSE_EVENTS.DOCKER_IMPORT_COMPLETE,i=>{try{const n=i.data?JSON.parse(i.data):{};this.showToast(`Docker bundle imported as case "${n.name}"`,"success"),this.loadQuickStartCases?.(),this.refreshDockerExports?.()}catch(n){console.error("[SSE] docker import complete:",n)}}),s(SSE_EVENTS.DOCKER_CONTAINER_RECREATED,i=>{try{const n=i.data?JSON.parse(i.data):{};this.showToast(`Container for "${n.name}" removed \u2014 next launch recreates it with the new config`,"info")}catch(n){console.error("[SSE] docker container recreated:",n)}}),s(SSE_EVENTS.CUSTOM_MODEL_SWAPPED_OUT,i=>{try{const n=i.data?JSON.parse(i.data):{};this.showToast(`${n.sessionName||n.sessionId}'s model (${n.previousModel}) was swapped out on llama-swap by another session \u2014 currently loaded: ${n.currentlyLoadedModel}. Sending a message there will reload it.`,"warning",{duration:0})}catch(n){console.error("[SSE] custom model swapped out:",n)}}),s(SSE_EVENTS.ADMIN_USERS_CHANGED,()=>{window.codemanAdmin?.onUsersChanged?.()}),s(SSE_EVENTS.DOCKER_IMAGE_BUILD_STARTED,()=>{this.showToast("Building the Codeman agent image (first Docker case, a few minutes)...","info",{duration:8e3})}),s(SSE_EVENTS.DOCKER_IMAGE_BUILD_COMPLETE,i=>{try{const n=i.data?JSON.parse(i.data):{};n.error?this.showToast(`Agent image build failed: ${n.error}`,"error"):this.showToast("Agent image ready. Starting the container...","success")}catch(n){console.error("[SSE] docker image build complete:",n)}}),s(SSE_EVENTS.DOCKER_IMAGE_BUILD_FAILED,i=>{try{const n=i.data?JSON.parse(i.data):{};this.showToast(`Agent image build failed: ${n.error||"unknown error"}`,"error")}catch(n){console.error("[SSE] docker image build failed:",n)}}),s(SSE_EVENTS.SESSION_PINNED,i=>{let n=null;try{n=JSON.parse(i.data)}catch{}if(n&&n.id){const o=this.sessions.get(n.id);o&&(o.pinned=n.pinned===!0,o.pinnedAt=n.pinned?n.pinnedAt:void 0)}this._onSessionListMaybeChanged()}),s(SSE_EVENTS.HEARTBEAT,()=>{}),this._sseStaleWatchdog=setInterval(()=>this._checkSseStale(),5e3)}_checkSseStale(){const e=window.CodemanSseStale;if(!e)return;const t=Date.now();e.compute({lastMessageAt:this._sseLastMessageAt,now:t,status:this._connectionStatus,isOnline:this.isOnline,timeoutMs:this._sseStaleTimeoutMs})&&(console.log(`[SSE] stream stale: no frame for ${t-this._sseLastMessageAt}ms (threshold ${this._sseStaleTimeoutMs}ms), forcing reconnect`),this.connectSSE())}_onInit(e){_crashDiag.log(`INIT: ${e.sessions?.length||0} sessions`),this.handleInit(e),this._ensureHostWakePoller?.()}_onSessionCreated(e){this.sessions.set(e.id,e),this.sessionOrder.includes(e.id)||(this.sessionOrder.push(e.id),this.saveSessionOrder()),this.markSessionTabEntering?.(e.id),this.markTerminalEntering?.(e.id),e.parentSessionId&&this.markConnectionLineEntering?.("lineage:"+e.id),this.renderSessionTabs(),this.updateCost(),this.sessions.size===1&&this.startSystemStatsPolling(),this._urlSessionId===e.id&&this._selectUrlSession()}_onSessionUpdated(e){const t=e.session||e,s=this.sessions.get(t.id),i=t.claudeSessionId&&(!s||!s.claudeSessionId);this.sessions.set(t.id,t),this.renderSessionTabs(),this.updateCost(),t.id===this.activeSessionId&&t.tokens&&this.updateRespawnTokens(t.tokens),this.updateSubagentParentNames(t.id),i&&(this.recheckOrphanSubagents(),requestAnimationFrame(()=>{this.updateConnectionLines()}))}_onSessionDeleted(e){if(this._wsSessionId===e.id&&this._disconnectWs(),this.isSoloWindow&&e.id===this.soloSessionId&&this._showSoloSessionGone(),this.detachedSessions.has(e.id)&&this._redock(e.id),this._cleanupSessionData(e.id),this.activeSessionId===e.id&&!this._closingSessions.has(e.id)){this.activeSessionId=null;try{localStorage.removeItem("codeman-active-session")}catch{}this.terminal.clear(),this.showWelcome()}this.renderSessionTabs(),this.renderRalphStatePanel(),this.renderProjectInsightsPanel(),this.sessions.size===0&&this.stopSystemStatsPolling()}_onSSETerminal(e){this._wsReady||this._onSessionTerminal(e)}_onSSENeedsRefresh(e){this._wsReady||this._onSessionNeedsRefresh(e)}_onSSEClearTerminal(e){this._wsReady||this._onSessionClearTerminal(e)}_bufferLoadFinishOpts(e,t){return{flushQueued:e?.source==="mux-visible"||e?.source==="mux-full-history",since:t}}_onSessionTerminal(e){if(e.id===this.activeSessionId){e.data.length>32768&&_crashDiag.log(`TERMINAL: ${(e.data.length/1024).toFixed(0)}KB`);const t=(this.pendingWrites?.reduce((s,i)=>s+i.length,0)||0)+(this.flickerFilterBuffer?.length||0)+(this._loadBufferQueue?.reduce((s,i)=>s+i.data.length,0)||0)+(this._terminalWriteInFlightBytes||0);if(t+e.data.length>131072){this._scheduleDroppedOutputRecovery(e.id,0,t);return}this.batchTerminalWrite(e.data)}}_scheduleDroppedOutputRecovery(e,t=0,s){!e||this._clientDropRecoveryTimer||(Number.isFinite(s)&&_crashDiag.log(`TERMINAL DROP: ${(s/1024).toFixed(0)}KB queued`),this._clientDropRecoveryTimer=setTimeout(async()=>{this._clientDropRecoveryTimer=null;let i=!1,n=!1;try{const a=await this._onSessionNeedsRefresh({id:e});i=a===!0,n=a==="deadline"}catch{}window.CodemanDroppedOutput.shouldRetryDroppedOutputRecovery({repainted:i,timedOut:n,attempt:t,stillActive:this.activeSessionId===e})&&(_crashDiag.log(`DROP RECOVERY: attempt ${t+1} did not repaint, retrying`),this._scheduleDroppedOutputRecovery(e,t+1))},window.CodemanDroppedOutput.DROP_RECOVERY_DELAY_MS))}_sanitizeHtml(e){return typeof window<"u"&&typeof window.sanitizeMarkdownHtml=="function"?window.sanitizeMarkdownHtml(e):String(e??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}_cleanTerminalBuffer(e){const t=e.replace(/\x1b\[[\x30-\x3F]*[\x20-\x2F]*[\x40-\x7E]/g,"").replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g,"").replace(/\x1b[PX^_][^\x1b]*\x1b\\/g,"").replace(/\x1b[NO()][A-Z0-9]?/g,"").replace(/\x1b[>=<78cDEHM]/g,"").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g,"").replace(/\r\n/g,`
|
|
8
|
-
`).replace(/\r/g,`
|
|
9
|
-
`),s=[/^\s*❯\s*/,/^\s*[⏵⏺⏸⏹]+\s*/,/^\s*✻\s*(Crunching|Crunched|Thinking)/i,/bypass permissions/i,/\bshift\+tab to cycle\b/i,/^\s*focus\s*$/,/^\s*new task\?/i,/\/clear to save/i,/^\s*─{5,}\s*$/,/\[(Opus|Sonnet|Haiku|GPT|Claude)[\s\S]*(tokens?|\$|¥|%|↑|↓)/i,/^\s*\[\d+[km]?\/\d+[km]?\]/i,/[█░▓▒]{3,}/,/^\s*\(.*\s*(tokens?|context).*\)\s*$/i];return t.split(`
|
|
10
|
-
`).filter(o=>o.trim()?!s.some(r=>r.test(o)):!0).join(`
|
|
11
|
-
`).replace(/[ \t]+$/gm,"").replace(/\n{4,}/g,`
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
`).trim()}_preprocessAsciiArt(e){const t=/[─-╿▀-▟]/,s=/```[\s\S]*?```/g,i=[];return e.replace(s,a=>(i.push(a),`__CODEMAN_FENCE_${i.length-1}__`)).split(/(\n{2,})/).map(a=>/^\n{2,}$/.test(a)||!a.trim()||a.includes("__CODEMAN_FENCE_")?a:t.test(a)?"\n```\n"+a+"\n```\n":a).join("").replace(/__CODEMAN_FENCE_(\d+)__/g,(a,r)=>i[Number(r)])}_renderMarkdown(e,{breaks:t=!0}={}){const s=e||"";if(typeof marked<"u"&&marked.parse)try{const n=this._preprocessAsciiArt(s);let o=this._sanitizeHtml(marked.parse(n,{breaks:t,gfm:!0}));o=o.replace(/<table>/g,'<div class="rv-table-wrap"><table>').replace(/<\/table>/g,"</table></div>");const a=/[─-╿▀-▟]/,r=document.createElement("template");return r.innerHTML=o,r.content.querySelectorAll("pre > code").forEach(c=>{const l=c.parentElement,d=a.test(c.textContent||""),h=document.createElement("div");h.className=d?"rv-code-wrap rv-diagram-wrap":"rv-code-wrap";const f=document.createElement("div");f.className="rv-code-actions";const u=document.createElement("button");if(u.className="rv-copy-btn",u.type="button",u.setAttribute("aria-label","Copy code"),u.setAttribute("title","Copy code"),f.appendChild(u),d){l.classList.add("rv-diagram");const p=document.createElement("button");p.className="rv-wrap-toggle",p.type="button",p.setAttribute("aria-label","Toggle line wrapping"),p.setAttribute("title","Toggle line wrapping"),f.appendChild(p)}l.parentNode.insertBefore(h,l),h.appendChild(f),h.appendChild(l)}),r.content.querySelectorAll("a[href]").forEach(c=>{const l=c.getAttribute("href")||"";!l||l.startsWith("#")||/^(?:mailto|tel):/i.test(l)||(c.setAttribute("target","_blank"),c.setAttribute("rel","noopener noreferrer"))}),r.innerHTML}catch{}return`<pre style="white-space:pre-wrap;word-break:break-word">${s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}</pre>`}_bindResponseViewerInteractions(e){!e||e.dataset.rvBound==="1"||(e.dataset.rvBound="1",e.addEventListener("click",async t=>{const s=t.target.closest("a.rv-path");if(s){t.preventDefault(),t.stopPropagation();const l=s.dataset.path;l&&this.openFilePreview(l,s.dataset.sessionId||this.activeSessionId);return}const i=t.target.closest("a[href]");if(i&&this.openLinkThroughWebTabIfLoopback?.(i.href)){t.preventDefault(),t.stopPropagation();return}const n=t.target.closest(".rv-copy-btn");if(n){t.preventDefault(),t.stopPropagation();const l=n.closest(".rv-code-wrap")?.querySelector("pre code"),d=l?await this._copyText(l.textContent||""):!1;n.classList.remove("rv-copied","rv-copy-failed"),n.classList.add(d?"rv-copied":"rv-copy-failed"),clearTimeout(n._resetTimer),n._resetTimer=setTimeout(()=>{n.classList.remove("rv-copied","rv-copy-failed")},1500);return}const o=t.target.closest(".rv-wrap-toggle");if(!o)return;t.preventDefault(),t.stopPropagation();const a=o.closest(".rv-diagram-wrap"),r=a?.querySelector("pre.rv-diagram");if(!r||!a)return;const c=r.classList.toggle("rv-nowrap");a.classList.toggle("rv-wrap-nowrap",c)}))}async _copyText(e){if(!e)return!1;try{if(navigator.clipboard?.writeText)return await navigator.clipboard.writeText(e),!0}catch{}try{const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly",""),t.style.cssText="position:fixed;top:0;left:0;opacity:0;pointer-events:none",document.body.appendChild(t),t.select();const s=document.execCommand("copy");return document.body.removeChild(t),s}catch{return!1}}_buildResponseViewerMessage(e,t,s,i){const n=document.createElement("div"),o=t==="user";n.className="rv-message "+(o?"rv-msg-user":"rv-msg-assistant");const a=!!(i&&i.continuation);if(a&&n.classList.add("rv-msg-cont"),i&&i.kind&&(n.dataset.kind=i.kind),i&&i.queued&&(n.dataset.queued="1"),!a){const c=document.createElement("div");c.className="rv-role "+(o?"rv-role-user":"rv-role-assistant"),c.textContent=o?"You":s,n.appendChild(c)}const r=document.createElement("div");return r.className="rv-text",r.innerHTML=this._renderMarkdown(e),this._linkifyFilePaths(r),n.appendChild(r),n}_linkifyFilePaths(e){if(!e||typeof document>"u"||typeof absoluteFilePathPattern!="function")return;const t=absoluteFilePathPattern(),s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT),i=[];for(let n=s.nextNode();n;n=s.nextNode())n.parentElement?.closest("a")||(t.lastIndex=0,t.test(n.nodeValue||"")&&i.push(n));for(const n of i){const o=n.nodeValue,a=document.createDocumentFragment();let r=0,c;for(t.lastIndex=0;(c=t.exec(o))!==null;){const l=c[1];c.index>r&&a.appendChild(document.createTextNode(o.slice(r,c.index)));const d=document.createElement("a");d.className="rv-path",d.href="#",d.dataset.path=l,d.title=l,d.textContent=l,a.appendChild(d),r=c.index+l.length}r<o.length&&a.appendChild(document.createTextNode(o.slice(r))),n.parentNode?.replaceChild(a,n)}}_getResponseViewerAgentLabel(){const e=this.sessions.get(this.activeSessionId)?.mode;return e==="codex"?"Codex":e==="gemini"?"Gemini":e==="antigravity"?"Antigravity":e==="pi"?"Pi":e==="grok"?"Grok":e==="deepseek"?"DeepSeek":e==="omp"?"OMP":e==="opencode"?"OpenCode":"Claude"}async toggleResponseViewer(){const e=document.getElementById("responseViewer"),t=document.getElementById("responseViewerBackdrop");if(!e)return;if(e.classList.contains("visible")){e.classList.remove("visible"),t.classList.remove("visible");return}if(this.activeSessionId)try{const n=(await(await fetch(`/api/sessions/${this.activeSessionId}/last-response?context=turn`)).json())?.data??{};let o=n.text||"";const a=(Array.isArray(n.messages)?n.messages:[]).filter(h=>h&&h.role==="assistant"&&typeof h.text=="string"&&h.text.trim()),r=this.sessions.get(this.activeSessionId)?.mode||"claude";if(!o&&(r==="claude"||r==="shell")){const f=(await this._fetchTerminalCapture(`/api/sessions/${this.activeSessionId}/terminal`,{full:!0})).json?.data??{};f.terminalBuffer&&(o=this._cleanTerminalBuffer(f.terminalBuffer))}const c=document.getElementById("responseViewerBody");if(a.length>0){const h=this._getResponseViewerAgentLabel();c.innerHTML="";let f=null;for(const u of a){const p=!!f&&typeof u.turn=="number"&&f.turn===u.turn;c.appendChild(this._buildResponseViewerMessage(u.text,"assistant",h,{...u,continuation:p})),f=u}this._bindResponseViewerInteractions(c)}else o?(c.innerHTML="",c.appendChild(this._buildResponseViewerMessage(o,"assistant",this._getResponseViewerAgentLabel())),this._bindResponseViewerInteractions(c)):c.textContent=window.codemanT?.("No response yet \u2014 send a message in this session first.")||"No response yet \u2014 send a message in this session first.";const l=document.getElementById("responseViewerTitle"),d=document.getElementById("responseViewerMore");l&&(l.textContent="Last Response"),d&&(d.style.display="",d.textContent="More"),e.classList.add("visible"),t.classList.add("visible"),c.scrollTop=a.length>1?c.scrollHeight:0}catch(i){console.error("Failed to load response:",i)}}async loadFullContext(){if(!this.activeSessionId)return;const e=document.getElementById("responseViewerMore");e&&(e.textContent="...");try{const i=((await(await fetch(`/api/sessions/${this.activeSessionId}/last-response?context=full`)).json())?.data??{}).messages||[],n=document.getElementById("responseViewerBody"),o=document.getElementById("responseViewerTitle");if(!n)return;if(i.length===0){let l=n.querySelector(":scope > .rv-notice");l||(l=document.createElement("div"),l.className="rv-notice",n.appendChild(l));const d="No full conversation history available for this session";l.textContent=window.codemanT?.(d)||d;return}const a=this._getResponseViewerAgentLabel();n.innerHTML="";let r=null;for(const l of i){const d=!!r&&r.role===l.role&&typeof l.turn=="number"&&r.turn===l.turn;n.appendChild(this._buildResponseViewerMessage(l.text,l.role,a,{...l,continuation:d})),r=l}this._bindResponseViewerInteractions(n);const c=new Set(i.filter(l=>typeof l.turn=="number").map(l=>l.turn)).size;o&&(o.textContent=c?`Conversation (${i.length} messages, ${c} turns)`:`Conversation (${i.length} messages)`),e&&(e.style.display="none"),n.scrollTop=n.scrollHeight}catch(t){console.error("Failed to load context:",t)}finally{e&&(e.textContent="More")}}async _fetchTerminalCapture(e,t={}){const s=typeof CodemanFetchDeadline<"u"?CodemanFetchDeadline.terminalFetchDeadlineMs({full:!!t.full,inflight:this._terminalCaptureInflight||0}):45e3,n=typeof AbortController=="function"?new AbortController:null,o=n?setTimeout(()=>n.abort(),s):null;this._terminalCaptureInflight=(this._terminalCaptureInflight||0)+1;try{const a=await(n?fetch(e,{signal:n.signal}):fetch(e)),r=performance.now();return{json:await a.json(),headers:a.headers,headersAt:r}}catch(a){throw a?.name==="AbortError"&&_crashDiag.log(`TERMINAL FETCH TIMEOUT after ${s}ms`),a}finally{o!==null&&clearTimeout(o),this._terminalCaptureInflight=Math.max(0,(this._terminalCaptureInflight||1)-1)}}async _onSessionNeedsRefresh(e={}){const t=this.activeSessionId;if(e?.id&&e.id!==t||!t||!this.terminal||this._isLoadingBuffer||this._terminalRefreshOwner?.sessionId===t)return!1;const s={sessionId:t};this._terminalRefreshOwner=s;try{const i=this.sessions.get(t)?.mode!=="shell";let n=await this._fetchTerminalCapture(i?`/api/sessions/${t}/terminal?full=1`:`/api/sessions/${t}/terminal?tail=${TERMINAL_TAIL_SIZE}`,{full:i}),o=n.headersAt,a=n.json?.data??{};if(i&&a.terminalBuffer&&this._replayWouldShrinkBuffer(a.terminalBuffer)&&(n=await this._fetchTerminalCapture(`/api/sessions/${t}/terminal?tail=${TERMINAL_TAIL_SIZE}`),o=n.headersAt,a=n.json?.data??{}),this.activeSessionId!==t||this._terminalRefreshOwner!==s)return!1;if(a.terminalBuffer){const r=this.terminal.buffer?.active,c=r?Math.max(0,(r.baseY||0)-(r.viewportY||0)):0;this._resetTerminalForReplay(),await this.chunkedTerminalWrite(a.terminalBuffer,TERMINAL_CHUNK_SIZE,void 0,this._bufferLoadFinishOpts(a,o)),this._setHistoryTruncation(t,a);const l=computeRewriteScrollLine({linesFromBottom:c,baseY:this.terminal.buffer?.active?.baseY??0});l===null||typeof this.terminal.scrollToLine!="function"?this.terminal.scrollToBottom():this.terminal.scrollToLine(l),this._syncStickyScrollBaseline(),this._localEchoOverlay?.rerender(),this.activeSessionId&&this.sendResize(this.activeSessionId)}return this._markTerminalBufferReconciled(t),!0}catch(i){return console.error("needsRefresh reload failed:",i),i?.name==="AbortError"?"deadline":!1}finally{this._terminalRefreshOwner===s&&(this._terminalRefreshOwner=null)}}_markTerminalBufferReconciled(e){e&&this._wsOutputGapSession===e&&(this._wsOutputGapSession=null)}async _onSessionClearTerminal(e){if(e.id===this.activeSessionId){if(this._isLoadingBuffer)return;try{const t=await this._fetchTerminalCapture(`/api/sessions/${e.id}/terminal`,{full:!0}),s=t.headersAt,i=t.json?.data??{};if(this._resetTerminalForReplay(),i.terminalBuffer){const n=i.terminalBuffer.replace(DEC_SYNC_STRIP_RE,"");await this.chunkedTerminalWrite(n,TERMINAL_CHUNK_SIZE,void 0,this._bufferLoadFinishOpts(i,s))}this.sendResize(e.id),this._localEchoOverlay?.rerender()}catch(t){console.error("clearTerminal refresh failed:",t)}}}_onSessionCompletion(e){this.totalCost+=e.cost||0,this.updateCost(),e.id===this.activeSessionId&&(this.terminal.writeln(""),this.terminal.writeln(`\x1B[1;32m Done (Cost: $${(e.cost||0).toFixed(4)})\x1B[0m`))}_onSessionError(e){e.id===this.activeSessionId&&this.terminal.writeln(`\x1B[1;31m Error: ${e.error}\x1B[0m`),this._notifySession(e.id,"critical","session-error","Session Error",e.error||"Unknown error")}_onSessionExit(e){this._wsSessionId===e.id&&this._disconnectWs();const t=this.sessions.get(e.id);t&&(t.status="stopped",this.renderSessionTabs(),e.id===this.activeSessionId&&this._updateLocalEchoState()),e.code&&e.code!==0&&this._notifySession(e.id,"critical","session-crash","Session Crashed",`Exited with code ${e.code}`)}_onSessionIdle(e){const t=this.sessions.get(e.id);if(t&&(t.status="idle",this.renderSessionTabs(),this.sendPendingCtrlL(e.id),e.id===this.activeSessionId&&this._updateLocalEchoState()),!this.respawnStatus[e.id]?.enabled){const s=this.notificationManager?.preferences?.stuckThresholdMs||6e5;clearTimeout(this.idleTimers.get(e.id)),this.idleTimers.set(e.id,setTimeout(()=>{this._notifySession(e.id,"warning","session-stuck","Session Idle",`Idle for ${Math.round(s/6e4)}+ minutes`),this.idleTimers.delete(e.id)},s))}}_onSessionWorking(e){const t=this.sessions.get(e.id);t&&(t.status="busy",this.pendingHooks.has(e.id)||this.tabAlerts.delete(e.id),this.renderSessionTabs(),this.sendPendingCtrlL(e.id),e.id===this.activeSessionId&&this._updateLocalEchoState());const s=this.idleTimers.get(e.id);s&&(clearTimeout(s),this.idleTimers.delete(e.id))}_onSessionAutoClear(e){e.sessionId===this.activeSessionId&&(this.showToast(`Auto-cleared at ${e.tokens.toLocaleString()} tokens`,"info"),this.updateRespawnTokens(0)),this._notifySession(e.sessionId,"info","auto-clear","Auto-Cleared",`Context reset at ${(e.tokens||0).toLocaleString()} tokens`)}_onSessionLimitPauseScheduled(e){const t=this.sessions.get(e.sessionId);t&&(t.autoResumeAt=e.resumeAt);const s=new Date(e.resumeAt).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});e.sessionId===this.activeSessionId&&this.showToast(`Usage limit reached \u2014 auto-resume at ${s}`,"warning"),this._notifySession(e.sessionId,"warning","limit-pause","Usage Limit Reached",`Auto-resume scheduled for ${s}`),this.updateAutoResumeStatus(e.sessionId)}_onSessionLimitResume(e){const t=this.sessions.get(e.sessionId);t&&(t.autoResumeAt=void 0),e.sessionId===this.activeSessionId&&this.showToast("Usage limit reset \u2014 work resumed automatically","success"),this._notifySession(e.sessionId,"info","limit-resume","Auto-Resumed","Usage limit reset \u2014 continuing work"),this.updateAutoResumeStatus(e.sessionId)}_onSessionLimitResumeCancelled(e){const t=this.sessions.get(e.sessionId);t&&(t.autoResumeAt=void 0),this.updateAutoResumeStatus(e.sessionId)}_onSessionRespawnBreakerTripped(e){const s=this.sessions.get(e.sessionId)?.name||"Session";this.showToast?.(`${s} stopped: repeated crashes detected. Restart to retry.`,"error")}_onSessionCliInfo(e){const t=this.sessions.get(e.sessionId);t&&(e.version&&(t.cliVersion=e.version),e.model&&(t.cliModel=e.model),e.accountType&&(t.cliAccountType=e.accountType),e.latestVersion&&(t.cliLatestVersion=e.latestVersion)),e.sessionId===this.activeSessionId&&this.updateCliInfoDisplay()}_onSessionStatusTelemetry(e){this.updatePlanUsageChip(e);try{localStorage.setItem("codeman:planUsage",JSON.stringify({t:Date.now(),data:e}))}catch{}}restorePlanUsageChip(){try{const e=localStorage.getItem("codeman:planUsage");if(!e)return;const t=JSON.parse(e);t?.data&&Date.now()-(t.t||0)<12*3600*1e3&&this.updatePlanUsageChip(t.data)}catch{}}updatePlanUsageChip(e){const t=document.getElementById("planUsageChip");if(!t||!e)return;const s=h=>h&&typeof h.usedPercentage=="number"?Math.round(h.usedPercentage):null,i=h=>h>=85?"pu-red":h>=60?"pu-yellow":"pu-green",n=(h,f,u)=>{if(f===null)return u?`<span class="pu-win pu-win-idle"><span class="pu-label">${h}</span><span class="pu-val">\u2014</span></span>`:"";const p=Math.round(Number(f));return Number.isFinite(p)?`<span class="pu-win"><span class="pu-label">${h}</span><span class="pu-val ${i(p)}">${p}%</span></span>`:""},o=h=>s(h?.fiveHour)!==null||s(h?.sevenDay)!==null,a=o(e)&&o(e.codex),r=(h,f,u)=>{if(!o(f))return"";const p=[n("5h",s(f?.fiveHour),u),n("7d",s(f?.sevenDay),u)].filter(Boolean);return p.length?`<span class="pu-row">${a?`<span class="pu-provider">${h}</span>`:""}<span class="pu-windows">${p.join('<span class="pu-sep">\xB7</span>')}</span></span>`:""},c=[r("Claude",e,!0),r("Codex",e.codex,!1)].filter(Boolean);t.innerHTML=c.length?c.join(""):"\u2014";const l=h=>h&&h.resetAt?new Date(h.resetAt).toLocaleString():"\u2014",d=(h,f,u)=>{const p=[],m=s(f?.fiveHour),T=s(f?.sevenDay);return m!==null?p.push(`5-hour limit: ${m}% used (resets ${l(f.fiveHour)})`):u&&T!==null&&p.push("5-hour limit: no active session window"),T!==null&&p.push(`Weekly limit: ${T}% used (resets ${l(f.sevenDay)})`),p.length?`${h} plan usage
|
|
15
|
-
${p.join(`
|
|
16
|
-
`)}`:""};t.title=[d("Claude",e,!0),d("Codex",e.codex,!1)].filter(Boolean).join(`
|
|
17
|
-
|
|
18
|
-
`)||"Plan usage limits"}_onScheduledCreated(e){this.currentRun=e,this.showTimer()}_onScheduledUpdated(e){this.currentRun=e,this.updateTimer()}_onScheduledCompleted(e){this.currentRun=e,this.hideTimer(),this.showToast("Scheduled run completed!","success")}_onScheduledStopped(){this.currentRun=null,this.hideTimer()}setConnectionStatus(e){this._connectionStatus=e,e==="connected"?(this._connDownSince=null,this._nextSseRetryAt=null,this._offlineOverlayDismissed=!1):this._connDownSince===null&&(this._connDownSince=Date.now()),this._updateConnectionIndicator(),this._updateConnectionLossUi(),e==="connected"&&this._redeliverSweep()}_connectWs(e){this._disconnectWs(),this._wsState="connecting",this._updateConnectionIndicator();const t=location.protocol==="https:"?"wss:":"ws:",s=this._clientId?`${this._clientId}:${this._wsTabNonce}`:"",i=s?`?cid=${encodeURIComponent(s)}`:"",n=`${t}//${location.host}${CodemanBase.base}/ws/sessions/${e}/terminal${i}`,o=new WebSocket(n);this._ws=o,this._wsSessionId=e,o.onopen=()=>{this._ws===o&&(this._wsReady=!0,this._wsState="connected",this._wsReconnectAttempts=0,this._updateConnectionIndicator(),this.sendResize(e)?.catch?.(()=>{}),this._startMobileResizeRetry(e),this._onWsReady(e),this._wsOutputGapSession===e&&(_crashDiag.log(`WS REOPEN: reconciling output gap for ${e}`),this._onSessionNeedsRefresh({id:e})))},o.onmessage=a=>{if(this._ws===o){this._wsLastRecvAt=Date.now();try{const r=JSON.parse(a.data);r.t==="o"?this._onSessionTerminal({id:e,data:r.d}):r.t==="c"?this._onSessionClearTerminal({id:e}):r.t==="r"?this._onSessionNeedsRefresh({id:e}):r.t==="ia"?this._onWsInputAck(r.seq,r):r.t==="zc"&&this._onPtyGeometryReport(e,r.c,r.r)}catch{}}},o.onclose=a=>{if(this._ws!==o)return;this._ws=null,this._wsSessionId=null,this._wsReady=!1,this._stopMobileResizeRetry();const r=window.CodemanWsReconnect.plan(a.code,this._wsReconnectAttempts||0);_crashDiag.log(`WS CLOSE code=${a.code} reason=${a.reason||""} action=${r.action} attempts=${this._wsReconnectAttempts||0}`),this._wsOutputGapSession=e;const c=this.activeSessionId===e;if(r.action==="give-up")this._wsState=c?"fallback":"disconnected",this._updateConnectionIndicator();else if(r.action==="reconnect")if(c){this._wsState="reconnecting",this._updateConnectionIndicator();const l=r.delayMs+Math.floor(Math.random()*250);this._wsReconnectAttempts=(this._wsReconnectAttempts||0)+1,this._wsReconnectTimer=setTimeout(()=>{this._wsReconnectTimer=null,this.activeSessionId===e&&this._connectWs(e)},l)}else this._wsState="disconnected",this._updateConnectionIndicator();else this._wsState=c?"fallback":"disconnected",this._updateConnectionIndicator(),c&&(this._wsReconnectAttempts=(this._wsReconnectAttempts||0)+1,this._wsReconnectTimer=setTimeout(()=>{this._wsReconnectTimer=null,this.activeSessionId===e&&this._connectWs(e)},r.delayMs))},o.onerror=()=>{}}_disconnectWs(){this._clearTimer("_wsReconnectTimer"),this._wsState="disconnected",this._stopMobileResizeRetry(),this._ws&&(this._ws.onclose=null,this._ws.close(),this._ws=null,this._wsSessionId=null,this._wsReady=!1)}_startMobileResizeRetry(e){this._stopMobileResizeRetry(),(typeof MobileDetection<"u"&&MobileDetection.getDeviceType?MobileDetection.getDeviceType():"desktop")!=="desktop"&&(this._mobileResizeRetryTimer=setInterval(()=>{document.visibilityState==="visible"&&(!this._wsReady||this._wsSessionId!==e||typeof KeyboardHandler<"u"&&KeyboardHandler.keyboardVisible||this.sendResize(e)?.catch?.(()=>{}))},MOBILE_RESIZE_RETRY_MS))}_stopMobileResizeRetry(){this._mobileResizeRetryTimer&&(clearInterval(this._mobileResizeRetryTimer),this._mobileResizeRetryTimer=null)}_sendInputAsync(e,t,s){if(!e||!t)return;const i=s?.useMux===!0,n=window.CodemanInputLimit;if(n&&t.length>n.FRAME_MAX_CHARS){if(i||t.length>n.PASTE_MAX_CHARS){const o=i?n.FRAME_MAX_CHARS:n.PASTE_MAX_CHARS;this.showToast?.(`Input too large (${Math.ceil(t.length/1024)} KB, limit ${Math.floor(o/1024)} KB); not sent`,"error");return}for(const o of n.split(t))this._reliableSend(e,o,!1);return}this._reliableSend(e,t,i)}_sendInputEphemeral(e,t){if(!(!e||!t)){if(this._ws&&this._ws.readyState===WebSocket.OPEN&&this._wsSessionId===e)try{this._ws.send(JSON.stringify({t:"i",d:t}));return}catch{}try{fetch(`/api/sessions/${e}/input`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({input:t}),keepalive:!0}).catch(()=>{})}catch{}}}_reliableSend(e,t,s){const n={seq:this._nextSeq(e),data:t,useMux:!!s,ts:Date.now(),tries:0,sentAt:0};let o=this._pendingDeliveries.get(e);o||(o=[],this._pendingDeliveries.set(e,o)),o.push(n),this._persistReliableNow(),this._updateConnectionIndicator(),this._drainSession(e)}_nextSeq(e){const t=(this._seqCounters.get(e)||0)+1;return this._seqCounters.set(e,t),t}_drainSession(e){const t=this._pendingDeliveries.get(e);if(!(!t||t.length===0)){if(this._ws&&this._ws.readyState===WebSocket.OPEN&&this._wsSessionId===e){for(const s of t)if(s.sentAt===0)try{this._ws.send(JSON.stringify({t:"i",d:s.data,seq:s.seq,cid:this._clientId})),s.sentAt=Date.now(),s.tries++}catch{break}return}this._postDraining.has(e)||(this._postDraining.add(e),(async()=>{try{for(;;){const s=this._pendingDeliveries.get(e);if(!s||s.length===0||this._ws&&this._ws.readyState===WebSocket.OPEN&&this._wsSessionId===e)break;const i=s[0];i.tries++,i.sentAt=Date.now();let n=null;try{const o={input:i.data,seq:i.seq,clientId:this._clientId};i.useMux&&(o.useMux=!0),n=await fetch(`/api/sessions/${e}/input`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o),keepalive:i.data.length<65536})}catch{n=null}if(n&&n.ok)this._ackDelivery(e,i.seq);else if(n&&(n.status===404||n.status===410))this._ackDelivery(e,i.seq);else if(n&&(n.status===400||n.status===413))this._dropRejectedInput(e,i);else break}}finally{this._postDraining.delete(e)}})())}}_dropRejectedInput(e,t){this._ackDelivery(e,t.seq),this.showToast?.(`Input refused by the server (${Math.ceil(t.data.length/1024)} KB); not sent`,"error")}_ackDelivery(e,t){const s=this._pendingDeliveries.get(e);if(s){const i=s.findIndex(n=>n.seq===t);i!==-1&&(s.splice(i,1),s.length===0&&this._pendingDeliveries.delete(e),this._pendingDeliveries.size===0?this._persistReliableNow():this._persistReliableState(),this._updateConnectionIndicator())}this.markIdleAlertSeen?.(e)}_onWsInputAck(e,t){const s=this._wsSessionId;if(!(!s||!Number.isInteger(e))){if(t&&t.err){const i=(this._pendingDeliveries.get(s)||[]).find(n=>n.seq===e);i?this._dropRejectedInput(s,i):this._ackDelivery(s,e);return}if(t&&t.dup){const i=this._pendingDeliveries.get(s),n=i&&i.find(r=>r.seq===e),o=Number.isInteger(t.last)?t.last:e;(this._seqCounters.get(s)||0)<=o&&(this._seqCounters.set(s,o),this._persistReliableNow());const a=n&&n.tries<=1?n.data:null;this._ackDelivery(s,e),a!==null&&this._reliableSend(s,a,n.useMux);return}this._ackDelivery(s,e)}}_onWsReady(e){const t=this._pendingDeliveries.get(e);if(t)for(const s of t)s.sentAt=0;this._drainSession(e)}_redeliverSweep(){if(this._pendingDeliveries.size!==0)for(const e of[...this._pendingDeliveries.keys()]){const t=this._pendingDeliveries.get(e);if(!t||t.length===0)continue;if(this._ws&&this._ws.readyState===WebSocket.OPEN&&this._wsSessionId===e){const i=t[0],n=i&&i.sentAt&&Date.now()-i.sentAt>this._reliableAckTimeoutMs,o=Date.now()-this._wsLastRecvAt>this._reliableAckTimeoutMs;if(n&&o){try{this._ws.close()}catch{}continue}if(n)for(const a of t)a.sentAt&&Date.now()-a.sentAt>this._reliableAckTimeoutMs&&(a.sentAt=0)}this._drainSession(e)}}_pendingBytes(){let e=0,t=0;for(const s of this._pendingDeliveries.values())for(const i of s)e+=i.data.length,t++;return{bytes:e,count:t}}_loadReliableState(){try{this._clientId=localStorage.getItem("codeman:clientId")||""}catch{this._clientId=""}if(!this._clientId){this._clientId="c-"+Math.random().toString(36).slice(2)+"-"+Date.now().toString(36);try{localStorage.setItem("codeman:clientId",this._clientId)}catch{}}try{const e=localStorage.getItem("codeman:pendingInput");if(!e)return;const t=JSON.parse(e);if(t&&t.seqs)for(const[s,i]of Object.entries(t.seqs))Number.isFinite(i)&&this._seqCounters.set(s,i);if(t&&t.pending){for(const[s,i]of Object.entries(t.pending))if(Array.isArray(i)&&i.length){const n=window.CodemanInputLimit?.FRAME_MAX_CHARS??1/0,o=i.filter(a=>a&&typeof a.data=="string"&&Number.isInteger(a.seq)).filter(a=>a.data.length<=n).map(a=>({seq:a.seq,data:a.data,useMux:!!a.useMux,ts:a.ts||Date.now(),tries:0,sentAt:0}));o.length&&this._pendingDeliveries.set(s,o)}}}catch{}}_persistReliableState(){this._persistReliableTimer||(this._persistReliableTimer=setTimeout(()=>{this._persistReliableTimer=null,this._persistReliableNow()},250))}_persistReliableNow(){this._persistReliableTimer&&(clearTimeout(this._persistReliableTimer),this._persistReliableTimer=null);try{const e={};for(const[n,o]of this._seqCounters)e[n]=o;const t={};let s=0;for(const[n,o]of this._pendingDeliveries)if(o.length){t[n]=o.map(a=>({seq:a.seq,data:a.data,useMux:a.useMux,ts:a.ts,tries:a.tries}));for(const a of o)s+=a.data.length}const i=s>this._reliableMaxBytes?{seqs:e}:{seqs:e,pending:t};localStorage.setItem("codeman:pendingInput",JSON.stringify(i))}catch{}}_computeConnectionDescriptor(){const{bytes:e,count:t}=this._pendingBytes(),s=t>0,n=e>4,o=r=>r<1024?`${r}B`:`${(r/1024).toFixed(1)}KB`,a=n?` \xB7 ${o(e)} queued`:"";if(!this.isOnline||this._connectionStatus==="offline")return{display:"flex",dotClass:"connection-dot offline",text:n?`Offline (${o(e)} queued)`:"Offline",title:"No network connection"};if(this.activeSessionId){let r,c,l;switch(this._wsState){case"connected":r="connected",c="WS",l="Terminal connected over WebSocket";break;case"fallback":r="fallback",c="HTTP",l="WebSocket unavailable \u2014 input sent over HTTP";break;case"reconnecting":r="reconnecting",c="WS\u2026",l="Reconnecting WebSocket";break;default:r="reconnecting",c="WS\u2026",l="Connecting WebSocket";break}return{display:"flex",dotClass:`connection-dot ${r}`,text:`${c}${a}`,title:l}}return this._connectionStatus==="reconnecting"||this._connectionStatus==="disconnected"?{display:"flex",dotClass:"connection-dot reconnecting",text:n?`Reconnecting (${o(e)} queued)`:"Reconnecting...",title:"Reconnecting to server"}:s?{display:"flex",dotClass:"connection-dot draining",text:n?`Sending ${o(e)}...`:"Sending...",title:"Delivering queued input"}:{display:"none",dotClass:"",text:"",title:""}}_updateConnectionIndicator(){const e=this.$("connectionIndicator"),t=this.$("connectionDot"),s=this.$("connectionText");if(!e||!t||!s)return;const i=this._computeConnectionDescriptor(),n=this._lastIndicatorDescriptor;n&&n.display===i.display&&n.dotClass===i.dotClass&&n.text===i.text&&n.title===i.title||(this._lastIndicatorDescriptor=i,e.style.display=i.display,i.display!=="none"&&(t.className=i.dotClass,s.textContent=i.text,e.title=i.title))}setupOnlineDetection(){window.addEventListener("online",()=>{this.isOnline=!0,this.reconnectAttempts=0,this._connDownSince=Date.now(),this.connectSSE(),this._redeliverSweep()}),window.addEventListener("offline",()=>{this.isOnline=!1,this.setConnectionStatus("offline")})}_updateConnectionLossUi(){const e=window.CodemanConnectionLoss,t=this.$("offlineBanner"),s=this.$("offlineOverlay");if(!e||!t||!s)return;const i=e.compute({isOnline:this.isOnline,status:this._connectionStatus,everLoaded:this._initGeneration>0,downSince:this._connDownSince,now:Date.now(),nextRetryAt:this._nextSseRetryAt,overlayDismissed:this._offlineOverlayDismissed,retryPending:this._offlineRetryPending});this._connDownSince===null?this._stopOfflineTicker():this._startOfflineTicker();const n=this._offlineRetryPending?"Reconnecting\u2026":i.retryInSec!=null&&i.retryInSec>0?`Retrying in ${i.retryInSec}s`:"Retrying\u2026",o=`${i.mode}|${i.kind}|${n}`;if(o!==this._lastOfflineUiKey){if(this._lastOfflineUiKey=o,t.hidden=i.mode!=="banner",s.hidden=i.mode!=="overlay",document.body.classList.toggle("connection-lost",i.mode!=="hidden"),i.mode==="banner"){const a=this.$("offlineBannerText"),r=this.$("offlineBannerDetail");a&&(a.textContent=i.title),r&&(r.textContent=n)}else if(i.mode==="overlay"){const a=this.$("offlineOverlayTitle"),r=this.$("offlineOverlayBody"),c=this.$("offlineOverlayHost"),l=this.$("offlineOverlayStatus");a&&(a.textContent=i.title),r&&(r.textContent=i.detail),c&&(c.textContent=location.host),l&&(l.textContent=n)}}}_startOfflineTicker(){this._offlineUiTicker||(this._offlineUiTicker=setInterval(()=>this._updateConnectionLossUi(),1e3))}_stopOfflineTicker(){this._offlineUiTicker&&(clearInterval(this._offlineUiTicker),this._offlineUiTicker=null)}retryConnection(){this._offlineRetryPending=!0,this._nextSseRetryAt=null,this.reconnectAttempts=0,this._clearTimer("sseReconnectTimeout"),this.isOnline=navigator.onLine,this._lastOfflineUiKey="",this._updateConnectionLossUi(),this.connectSSE(),this.activeSessionId&&this._wsState!=="connected"&&(this._wsReconnectAttempts=0,this._connectWs(this.activeSessionId)),this._clearTimer("_offlineRetryTimer"),this._offlineRetryTimer=setTimeout(()=>{this._offlineRetryPending=!1,this._lastOfflineUiKey="",this._updateConnectionLossUi()},1500)}dismissOfflineOverlay(){this._offlineOverlayDismissed=!0,this._lastOfflineUiKey="",this._updateConnectionLossUi()}_updateCjkInputState(){const e=document.getElementById("cjkInput");if(!e)return;const t=this.loadAppSettingsFromStorage(),s=this.getDefaultSettings?.()||{},n=(this._serverCjkOverride||(t.cjkInputEnabled??s.cjkInputEnabled??!1))&&!!this.activeSessionId;e.classList.toggle("cjk-input-visible",!!n),document.body.classList.toggle("cjk-input-visible",!!n),e.style.display=n?"block":"none",e.setAttribute("aria-hidden",n?"false":"true"),n||(window.cjkActive=!1),typeof KeyboardHandler<"u"&&KeyboardHandler.updateLayoutForKeyboard()}_resetAllAppState(e=!1){this.sessions.clear(),this.ralphStates.clear(),e||(this.terminalBuffers.clear(),this.terminalBufferCache.clear(),this._xtermSnapshots?.clear()),this.projectInsights.clear(),this.teams.clear(),this.teamTasks.clear();for(const t of this.idleTimers.values())clearTimeout(t);if(this.idleTimers.clear(),this._clearTimer("flickerFilterTimeout"),this.flickerFilterBuffer="",this.flickerFilterActive=!1,this._clearTimer("syncWaitTimeout"),this._clearTimer("_clientDropRecoveryTimer"),this.pendingWrites=[],this.writeFrameScheduled=!1,this._terminalWriteInFlight=!1,this._terminalWriteInFlightBytes=0,this._isLoadingBuffer=!1,this._loadBufferQueue=null,this._bufferLoadOwner=null,this._terminalRefreshOwner=null,this._chunkedWriteGen=(this._chunkedWriteGen||0)+1,this._localEchoOverlay?.rerender(),this._predictiveEcho?.clearPredictions(),this.pendingHooks.clear(),this.approvals?.clear(),this._parentNameCache&&this._parentNameCache.clear(),this.subagentActivity.clear(),this.subagentToolResults.clear(),this.workflowRuns&&this.workflowRuns.clear(),this.workflowRunDetails&&this.workflowRunDetails.clear(),this.activeWorkflowRunId=null,this.activeWorkflowPhaseIndex=null,MobileDetection.cleanup(),KeyboardHandler.cleanup(),MobileDetection.init(),KeyboardHandler.init(),this.tabAlerts.clear(),this.attachmentHistoryCounts.clear(),this._shownCompletions&&this._shownCompletions.clear(),this.notificationManager?.titleFlashInterval&&(clearInterval(this.notificationManager.titleFlashInterval),this.notificationManager.titleFlashInterval=null),this.notificationManager?.groupingMap){for(const{timeout:t}of this.notificationManager.groupingMap.values())clearTimeout(t);this.notificationManager.groupingMap.clear()}this.terminalResizeObserver&&(this.terminalResizeObserver.disconnect(),this.terminalResizeObserver=null),this.planLoadingTimer&&(clearInterval(this.planLoadingTimer),this.planLoadingTimer=null),this.timerCountdownInterval&&(clearInterval(this.timerCountdownInterval),this.timerCountdownInterval=null),this.runSummaryAutoRefreshTimer&&(clearInterval(this.runSummaryAutoRefreshTimer),this.runSummaryAutoRefreshTimer=null)}handleInit(e){this._clearTimer("_initFallbackTimer");const t=++this._initGeneration;if(this._serverCjkOverride=e.inputCjkForm||!1,this._updateCjkInputState(),e.planUsage&&this.updatePlanUsageChip(e.planUsage),this.refreshRebootRestoreBanner?.(),e.version){const a=this.$("versionDisplay"),r=this.$("headerVersion");a&&(a.textContent=`v${e.version}`,a.title=`Codeman v${e.version}`),r&&(r.textContent=`v${e.version}`,r.title=`Codeman v${e.version}`)}VoiceInput.cleanup();const s=this.activeSessionId,i=t>1&&!!s&&Array.isArray(e.sessions)&&e.sessions.some(a=>a.id===s);this._resetAllAppState(i),e.sessions.forEach(a=>{this.sessions.set(a.id,a),(a.ralphLoop||a.ralphTodos)&&!this.ralphClosedSessions.has(a.id)&&this.ralphStates.set(a.id,{loop:a.ralphLoop||null,todos:a.ralphTodos||[]})});try{localStorage.removeItem("codeman-tab-meta")}catch{}if(Array.isArray(e.sessionOrder)&&e.sessionOrder.length)try{localStorage.setItem("codeman-session-order",JSON.stringify(e.sessionOrder))}catch{}this.syncSessionOrder(),this._loadTabLayout(),e.respawnStatus?this.respawnStatus=e.respawnStatus:this.respawnStatus={},this.respawnTimers={},this.respawnCountdownTimers={},this.respawnActionLogs={},e.globalStats&&(this.globalStats=e.globalStats),this.totalCost=e.sessions.reduce((a,r)=>a+(r.totalCost||0),0),this.totalCost+=e.scheduledRuns.reduce((a,r)=>a+(r.totalCost||0),0);const n=e.scheduledRuns.find(a=>a.status==="running");if(n&&(this.currentRun=n,this.showTimer()),this.updateCost(),this.renderSessionTabs(),this.seedApprovals?.(),this.sessions.size>0?this.startSystemStatsPolling():this.stopSystemStatsPolling(),this.cleanupAllFloatingWindows(),e.subagents&&(this.subagents.clear(),this.subagentActivity.clear(),this.subagentToolResults.clear(),e.subagents.forEach(a=>{this.subagents.set(a.agentId,a)}),this.renderSubagentPanel(),this.subagentParentMap.clear(),this.loadSubagentParentMap().then(()=>{for(const[a,r]of this.subagentParentMap){const c=this.subagents.get(a);if(c&&this.sessions.has(r)){c.parentSessionId=r;const l=this.sessions.get(r);l&&(c.parentSessionName=this.getSessionName(l)),this.subagents.set(a,c)}}for(const[a]of this.subagents)this.subagentParentMap.has(a)||this.findParentSessionForSubagent(a);this.restoreSubagentWindowStates()})),e.workflowRuns&&this.seedWorkflowRuns(e.workflowRuns),t!==this._initGeneration)return;if(this.isSoloWindow){this._applySoloMode();return}if(this._urlSessionId&&this.sessions.has(this._urlSessionId)){this.activeSessionId=null,this._selectUrlSession();return}this._urlSessionId&&this._armUrlSessionWait(this._urlSessionId);const o=this.activeSessionId;if(this.sessionOrder.length===0)this.activeSessionId=null;else{let a=o;if(!a||!this.sessions.has(a))try{a=localStorage.getItem("codeman-active-session")}catch{}i&&a===o&&this.sessions.has(a)?(this._wsSessionId!==a&&this._connectWs(a),this._onSessionNeedsRefresh({id:a})):(this.activeSessionId=null,a&&this.sessions.has(a)?this.selectSession(a,{auto:!0}):this.selectSession(this.sessionOrder[0],{auto:!0}))}}async loadState(){try{const t=await(await fetch("/api/status")).json();this.handleInit(t?.data??{})}catch(e){console.error("Failed to load state:",e)}}_debouncedCall(e,t,s=100){this._debounceTimers[e]&&clearTimeout(this._debounceTimers[e]),this._debounceTimers[e]=setTimeout(()=>{this._debounceTimers[e]=null,t.call(this)},s)}getSessionListLayout(){if(this.soloSessionId)return"header";const e=this.loadAppSettingsFromStorage(),t=this.getDefaultSettings(),s=e.sessionListLayout??t.sessionListLayout??"header";return s==="sidebar"||s==="sidebar-rich"?s:"header"}resolveSessionSidebarFontSize(e){const t=Number(e);return Number.isInteger(t)&&t>=11&&t<=18?t:12}applySessionSidebarFontSize(e=null){const t=e??this.loadAppSettingsFromStorage(),s=this.resolveSessionSidebarFontSize(t?.sessionSidebarFontSize);return document.documentElement.style.setProperty("--session-sidebar-name-font-size",`${s}px`),s}isSessionSidebarActive(){return document.documentElement.dataset.sessionList==="sidebar"}_tabOrientation(){return document.documentElement.getAttribute("data-tab-orientation")==="vertical"?"vertical":"horizontal"}_isVerticalTabList(){return this.isSessionSidebarActive()||this._tabOrientation()==="vertical"}shouldInlineSessionActions(){return this.isSessionSidebarActive()?!this.isSessionSidebarCollapsed():this._tabOrientation()==="vertical"&&!document.documentElement.classList.contains("tab-rail-compact")}isSessionSidebarRich(){const e=document.documentElement;return e.dataset.sessionList==="sidebar"&&e.dataset.sidebarDetail==="rich"}isTabRailRich(){const e=document.documentElement;return e.getAttribute("data-tab-orientation")==="vertical"&&e.dataset.tabRailDetail==="rich"&&!e.classList.contains("tab-rail-compact")}isRichTabRows(){return this.isSessionSidebarRich()||this.isTabRailRich()}isTabRailSorted(){const e=document.documentElement;return e.getAttribute("data-tab-orientation")==="vertical"&&e.dataset.tabRailSort==="activity"}_tabRailSortOrder(e){if(!this.isTabRailSorted()||!window.CodemanSessionOrder||typeof this._mobileOverviewState!="function")return null;const t=[];for(let n=0;n<e.length;n++){const o=this.sessions.get(e[n]);o&&t.push({id:e[n],state:this._mobileOverviewState(o,this.pendingHooks?.get(e[n])),lastActivityAt:Number(o.lastActivityAt)||0,lastSubmitAt:Number(o.lastSubmitAt)||0,orderIndex:n})}const s=window.CodemanSessionOrder.sort(t),i=new Map;for(let n=0;n<s.length;n++)i.set(s[n].id,n);return i}_isSessionSidebarOverlay(){return window.innerWidth<1024}isSessionSidebarCollapsed(){if(this._sidebarCollapsedOverride!==void 0)return this._sidebarCollapsedOverride;let e=null;try{e=localStorage.getItem("codeman-sidebar-collapsed")}catch{}return e===null?this._isSessionSidebarOverlay():e==="1"}shouldToggleSessionSidebarFromShortcut(e){if(!e||!e.ctrlKey&&!e.metaKey&&!e.altKey||!this.isSessionSidebarActive()||typeof this.getShortcutRegistry!="function"||typeof this.matchesShortcutEvent!="function")return!1;const t=this.getShortcutRegistry().find(s=>s.id==="toggle-session-sidebar");return!t||t.disabled?!1:this.matchesShortcutEvent(e,t)}applySessionListLayout(){const e=this.getSessionListLayout();this.applySessionSidebarFontSize();const t=e==="sidebar"||e==="sidebar-rich",s=this.isSessionSidebarCollapsed(),i=document.documentElement.dataset.sessionList,n=document.documentElement.dataset.sidebarDetail,o=document.documentElement.dataset.sidebar,a=document.getElementById("sessionTabs"),r=document.getElementById("sessionTabsHost"),c=document.getElementById("sessionSidebarList");if(!a||!r||!c)return;const l=document.getElementById("tabRail"),d=!t&&document.documentElement.getAttribute("data-tab-orientation")==="vertical",h=t?c:d&&l?l:r;a.parentElement!==h&&h.appendChild(a),document.documentElement.dataset.sessionList=t?"sidebar":"header",document.documentElement.dataset.sidebarDetail=e==="sidebar-rich"?"rich":"simple",document.documentElement.dataset.sidebar=s?"collapsed":"expanded",a.setAttribute("aria-orientation",h===r?"horizontal":"vertical");const f=document.getElementById("sidebarToggleBtn");if(f){f.classList.toggle("btn-sidebar-toggle--hidden",!t);const y=s?"Expand session sidebar":"Collapse session sidebar";f.setAttribute("aria-expanded",s?"false":"true"),f.setAttribute("aria-label",y),f.setAttribute("title",y)}const u=document.getElementById("sessionSidebar");if(u){u.classList.toggle("open",t&&!s);const y=t&&s&&this._isSessionSidebarOverlay();u.toggleAttribute("inert",y),y?u.setAttribute("aria-hidden","true"):u.removeAttribute("aria-hidden")}if(!t){this._sidebarFilter="";const y=document.getElementById("sessionSidebarFilter");y&&(y.value="")}const p=this._tallTabsEnabled;this.applyTabWrapSettings();const m=i!==document.documentElement.dataset.sessionList||n!==document.documentElement.dataset.sidebarDetail,T=o!==document.documentElement.dataset.sidebar;(m||T)&&p===this._tallTabsEnabled&&this._fullRenderSessionTabs(),t&&a.classList.remove("tabs-auto-wrap"),this.applySidebarFilter(this._sidebarFilter),this.updateConnectionLines(),document.getElementById("welcomeOverlay")?.classList.contains("visible")&&this.showHomeSessions?.(),this.isRichTabRows()?this._startSidebarRichClock():this._stopSidebarRichClock()}toggleSessionSidebar(){if(!this.isSessionSidebarActive())return;const e=!this.isSessionSidebarCollapsed();this._sidebarCollapsedOverride=e;try{localStorage.setItem("codeman-sidebar-collapsed",e?"1":"0")}catch{}e&&this.$("sessionSidebar")?.contains(document.activeElement)&&document.getElementById("sidebarToggleBtn")?.focus(),this.applySessionListLayout(),!e&&this._isSessionSidebarOverlay()&&this.$("sessionTabs")?.querySelector(".session-tab.active")?.focus()}closeSessionSidebarOnHandheld(){this._isSessionSidebarOverlay()&&(!this.isSessionSidebarActive()||this.isSessionSidebarCollapsed()||this.toggleSessionSidebar())}updateSidebarCount(){const e=document.getElementById("sessionSidebarCount");if(!e)return;const t=this.$("sessionTabs"),s=t?t.querySelectorAll(".session-tab:not(.tab-filtered-out)").length:this.sessions?.size??0;e.textContent=String(s)}applySidebarFilter(e){this._sidebarFilter=(e??"").trim().toLowerCase();const t=this.$("sessionTabs");if(!t)return;const i=this.isSessionSidebarActive()&&document.documentElement.dataset.sidebar!=="collapsed"?this._sidebarFilter:"";for(const n of t.querySelectorAll(".session-tab")){if(!i){n.classList.remove("tab-filtered-out");continue}const o=`${n.getAttribute("aria-label")||""} ${n.getAttribute("title")||""}`.toLowerCase();n.classList.toggle("tab-filtered-out",!o.includes(i))}this.updateSidebarCount()}_sidebarRichPillLabel(e){return{needs:"needs you",error:"error",waiting:"waiting",working:"working",idle:"idle",done:"done"}[e]||e}_sidebarRichRow(e,t){if(typeof this._mobileOverviewState!="function")return null;const s=this._mobileOverviewState(t,this.pendingHooks?.get(e)),i=this._mobileOverviewExit?this._mobileOverviewExit(s,t):null,n=!!i;return{state:s,exited:n,pill:n?"exited":this._sidebarRichPillLabel(s),watching:typeof t.watching=="string"?t.watching:"",createdAt:Number(t.createdAt)||0,since:i?i.since:this._mobileOverviewSince?this._mobileOverviewSince(s,t):null}}_sidebarRichMetaHTML(e){if(!e)return"";const t=(a,r,c,l)=>{const d=this._sidebarRichStampText(r,c),h=r?` title="${escapeHtml(`${a==="created"?"First created":a}: ${new Date(r).toLocaleString()}`)}"`:"";return`<span class="tab-meta-item ${l}"${h}><span class="tab-meta-key">${escapeHtml(a)}</span><span data-tab-ts="${r||0}" data-tab-fmt="${c}">${escapeHtml(d)}</span></span>`},s=[t("created",e.createdAt,"ago","tab-meta-created")];e.since&&(s.push('<span class="tab-meta-sep" aria-hidden="true">\xB7</span>'),s.push(t(e.since.key,e.since.at,"for","tab-meta-since")));const i=e.exited?"exited":e.state;if(s.push(`<span class="tab-pill tab-pill--${escapeHtml(i)}">${escapeHtml(e.pill)}</span>`),e.watching){const a=escapeHtml(`Still running in the background: ${e.watching}`);s.push(`<span class="tab-pill tab-pill--watching" title="${a}">watching</span>`)}const n=[e.createdAt?`First created: ${new Date(e.createdAt).toLocaleString()}`:"",e.since&&e.since.at?`${e.since.key}: ${new Date(e.since.at).toLocaleString()}`:""].filter(Boolean).join(" \xB7 ");return`<span class="tab-meta"${n?` title="${escapeHtml(n)}"`:""} data-i18n-skip>${s.join("")}</span>`}_sidebarRichStampText(e,t){return this._mobileOverviewStampText?this._mobileOverviewStampText(e,t):"\u2014"}_updateSidebarRichRow(e,t,s){const i=this._sidebarRichRow(t,s);if(!i)return;const n=e.dataset.tabState,o=`${i.state}${i.exited?"+exited":""}:${i.since?i.since.at:0}:${i.createdAt}:${i.watching}`;if(e.dataset.tabMetaSig===o)return;e.dataset.tabMetaSig=o,e.dataset.tabState=i.state,n&&e.classList.remove(`tab-state-${n}`),e.classList.add(`tab-state-${i.state}`);const a=e.querySelector(".tab-info");if(!a)return;const r=this._sidebarRichMetaHTML(i),c=a.querySelector(".tab-meta");c?c.outerHTML=r:a.insertAdjacentHTML("beforeend",r)}_startSidebarRichClock(){this._sidebarRichClock||(this._sidebarRichClock=setInterval(()=>{if(!this.isRichTabRows()){this._stopSidebarRichClock();return}this._tickSidebarRichTimes()},SIDEBAR_RICH_CLOCK_MS))}_stopSidebarRichClock(){this._sidebarRichClock&&(clearInterval(this._sidebarRichClock),this._sidebarRichClock=null)}_tickSidebarRichTimes(){const e=this.$("sessionTabs");if(e)for(const t of e.querySelectorAll("[data-tab-ts]")){const s=this._sidebarRichStampText(Number(t.dataset.tabTs)||0,t.dataset.tabFmt);t.textContent!==s&&(t.textContent=s)}}renderSessionTabs(){this._inlineRenameActive||this._debouncedCall("sessionTabs",this._renderSessionTabsImmediate)}_updateActiveTabImmediate(e){const t=this.$("sessionTabs");if(!t)return;if(this._isTabGroupStructureStale()){this._fullRenderSessionTabs();return}const s=t.querySelectorAll(".session-tab[data-id]");for(const i of s)i.dataset.id===e?i.classList.add("active"):i.classList.remove("active");this._syncTabTreeSelection(t),this._scrollActiveTabIntoView(e)}_scrollActiveTabIntoView(e,t="smooth"){const s=this.$("sessionTabs");if(!s)return;const i=e&&s.querySelector(`.session-tab[data-id="${e}"]`)||s.querySelector(".session-tab.active");if(!i)return;if(this._isVerticalTabList()){i.scrollIntoView({block:"nearest"});return}const n=window.CodemanTabOverflow?.computeTabScrollLeft;if(!n)return;const o=s.getBoundingClientRect(),a=i.getBoundingClientRect(),r=n({scrollLeft:s.scrollLeft,clientWidth:s.clientWidth,scrollWidth:s.scrollWidth,tabLeft:a.left-o.left+s.scrollLeft,tabWidth:a.width});if(Math.abs(r-s.scrollLeft)<1)return;const c=window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches;typeof s.scrollTo=="function"?s.scrollTo({left:r,behavior:c?"auto":t}):s.scrollLeft=r}_tabAnchor(e){return this._isVerticalTabList()?{x:e.right,y:e.top+e.height/2,spawnLeft:e.right+14,spawnTop:e.top,vertical:!1}:{x:e.left+e.width/2,y:e.bottom,spawnLeft:e.left,spawnTop:e.bottom,vertical:!0}}_tabConnectorPath(e,t){if(e.vertical){const o=t.left+t.width/2,a=t.top,r=(e.y+a)/2;return`M ${e.x} ${e.y} C ${e.x} ${r}, ${o} ${r}, ${o} ${a}`}const s=t.left,i=t.top+t.height/2,n=(e.x+s)/2;return`M ${e.x} ${e.y} C ${n} ${e.y}, ${n} ${i}, ${s} ${i}`}_setTerminalLoadState(e,t,s){this.terminalLoadStates.set(e,{generation:t,phase:s}),this._updateTerminalLoadTab(e)}_clearTerminalLoadState(e,t){const s=this.terminalLoadStates.get(e);s&&s.generation!==t||(this.terminalLoadStates.delete(e),this._updateTerminalLoadTab(e))}_updateTerminalLoadTab(e){const t=this.$("sessionTabs")?.querySelector(`.session-tab[data-id="${e}"]`);if(!t)return;const s=this.terminalLoadStates.get(e);if(t.classList.toggle("tab-loading",!!s),s){if(t.setAttribute("aria-busy","true"),t.dataset.loadPhase=s.phase,!t.querySelector(".tab-load-spinner")){const i=document.createElement("span");i.className="tab-load-spinner",i.setAttribute("aria-hidden","true");const n=t.querySelector(".tab-number");n?n.insertAdjacentElement("afterend",i):t.insertBefore(i,t.firstChild)}}else t.setAttribute("aria-busy","false"),delete t.dataset.loadPhase,t.querySelector(".tab-load-spinner")?.remove()}_renderSessionTabsImmediate(){if(this._inlineRenameActive)return;const e=this.$("sessionTabs"),t=e.querySelectorAll(".session-tab[data-id]"),s=new Set([...t].map(l=>l.dataset.id)),i=this._projectTabGroups(),n=i?new Set(i.visibleRefs.filter(l=>l.kind==="session").map(l=>l.id)):new Set(this.sessions.keys()),o=[...e.querySelectorAll(".session-tab[data-webview-id]")].map(l=>l.dataset.webviewId),a=i?i.visibleRefs.filter(l=>l.kind==="webview").map(l=>l.id):(this.webviewOrder||[]).filter(l=>this.webviews?.has(l)),r=o.length===a.length&&o.every((l,d)=>l===a[d]);if(s.size===n.size&&[...s].every(l=>n.has(l))&&r&&!this._isTabGroupStructureStale(i)){const l=this.isRichTabRows(),d=this._tabRailSortOrder(this.sessionOrder.filter(h=>this.sessions.has(h)));for(const[h,f]of this.sessions){const u=e.querySelector(`.session-tab[data-id="${h}"]`);if(!u)continue;const p=d?.has(h)?String(d.get(h)):"";u.style.order!==p&&(u.style.order=p);const m=h===this.activeSessionId&&!this.activeWebviewId,T=f.status||"idle",y=this.getSessionName(f),D=f.taskStats||{running:0,total:0},L=D.running>0,w=this.terminalLoadStates.get(h);if(m&&!u.classList.contains("active")?u.classList.add("active"):!m&&u.classList.contains("active")&&u.classList.remove("active"),u.classList.toggle("tab-loading",!!w),w){if(u.setAttribute("aria-busy","true"),u.dataset.loadPhase=w.phase,!u.querySelector(".tab-load-spinner")){const b=document.createElement("span");b.className="tab-load-spinner",b.setAttribute("aria-hidden","true");const E=u.querySelector(".tab-number");E?E.insertAdjacentElement("afterend",b):u.insertBefore(b,u.firstChild)}}else u.setAttribute("aria-busy","false"),delete u.dataset.loadPhase,u.querySelector(".tab-load-spinner")?.remove();const P=this.tabAlerts.get(h),N=P==="action",$=P==="idle",B=u.classList.contains("tab-alert-action"),_=u.classList.contains("tab-alert-idle");if(N&&!B?(u.classList.add("tab-alert-action"),u.classList.remove("tab-alert-idle")):$&&!_?(u.classList.add("tab-alert-idle"),u.classList.remove("tab-alert-action")):!P&&(B||_)&&u.classList.remove("tab-alert-action","tab-alert-idle"),!u.querySelector(".tab-number")){const b=this.sessionOrder.indexOf(h);if(b>=0&&b<9){const E=document.createElement("span");E.className="tab-number",E.textContent=String(b+1),u.insertBefore(E,u.firstChild)}}const x=u.querySelector(".tab-status");x&&!x.classList.contains(T)&&(x.className=`tab-status ${T}`),applyPaneExitBadge(u,f.paneExit),l?this._updateSidebarRichRow(u,h,f):u.dataset.tabState&&(u.querySelector(".tab-meta")?.remove(),u.classList.remove(`tab-state-${u.dataset.tabState}`),delete u.dataset.tabState,delete u.dataset.tabMetaSig);const O=u.querySelector(".tab-name");if(O){const b=parseSessionPrefix(y);if(O.dataset.fullName!==y){if(O.replaceChildren(),b&&b.suffix){const E=document.createElement("span");E.className="tab-name-prefix",E.textContent=`${b.prefix}: `,O.append(E,document.createTextNode(b.suffix))}else O.textContent=y;O.dataset.fullName=y,u.title=b&&b.suffix?f.workingDir?`${b.prefix} (${f.workingDir})`:b.prefix:f.workingDir||""}}const H=u.querySelector(".tab-badge");if(L)if(H)H.textContent!==String(D.running)&&(H.textContent=D.running);else{this._fullRenderSessionTabs();return}else if(H){this._fullRenderSessionTabs();return}const M=u.querySelector(".tab-subagent-badge"),k=this.minimizedSubagents.get(h),A=k?.size||0;if(A>0&&M){const b=M.querySelector(".subagent-label"),E=A===1?"AGENT":`AGENTS (${A})`;b&&b.textContent!==E&&(b.textContent=E);const R=M.querySelector(".subagent-dropdown");if(R){const V=this.renderSubagentTabBadge(h,k),G=document.createElement("div");G.innerHTML=V;const v=G.querySelector(".subagent-dropdown");v&&(R.innerHTML=v.innerHTML)}}else if(A>0&&!M){const b=this.renderSubagentTabBadge(h,k),E=u.querySelector(":scope > .tab-actions");E?E.insertAdjacentHTML("beforebegin",b):u.insertAdjacentHTML("beforeend",b)}else A===0&&M&&M.remove()}i&&e.getAttribute("role")==="tree"&&(this._syncTabTreeSelection(e),this._applyTabTreePositions(e),this._syncTabGroupHeaderAlerts(e,i))}else this._fullRenderSessionTabs();this._lastRenderedActiveTabId=this.activeSessionId,this.updateTabOverflowMode(),this._applyTabEntrances?.(),this._refreshMobileOverviewIfVisible?.(),this._refreshHomeSessionsIfVisible?.(),(this._lineageEdgeCount>0||this._isVerticalTabList())&&this.updateConnectionLines(),this.applySidebarFilter(this._sidebarFilter)}updateTabOverflowMode(){const e=this.$("sessionTabs");if(!e)return;if(this.isSessionSidebarActive()){e.classList.remove("tabs-auto-wrap");return}const t=MobileDetection.getDeviceType(),s=this.loadAppSettingsFromStorage(),i=this.getDefaultSettings(),n=t==="desktop"?s.tabTwoRows??i.tabTwoRows??!1:!1;if((window.CodemanTabOverflow?.resolveTabOrientation?window.CodemanTabOverflow.resolveTabOrientation({deviceType:t,setting:s.tabOrientation??i.tabOrientation??"horizontal"}):"horizontal")==="vertical"){e.classList.remove("tabs-auto-wrap");return}if(n||t!=="desktop"){e.classList.remove("tabs-auto-wrap");return}e.classList.remove("tabs-auto-wrap");const a=window.CodemanTabOverflow?.shouldAutoWrapTabs?window.CodemanTabOverflow.shouldAutoWrapTabs({deviceType:t,manualTwoRows:n,tabCount:this.sessions.size,scrollWidth:e.scrollWidth,clientWidth:e.clientWidth}):e.scrollWidth>e.clientWidth+1;e.classList.toggle("tabs-auto-wrap",a)}_setupTabMiddleClickClose(){const e=this.$("sessionTabs");!e||this._tabAuxClickBound||(this._tabAuxClickBound=!0,e.addEventListener("auxclick",t=>{if(t.button!==1)return;const s=t.target.closest?.(".session-tab");s&&(t.preventDefault(),t.stopPropagation(),s.dataset.id?this.requestCloseSession(s.dataset.id):s.dataset.webviewId&&this.closeWebviewTab?.(s.dataset.webviewId))}))}_fullRenderSessionTabs(){if(this.closeTabRailActionMenu?.(),this._inlineRenameActive)return;this.closeTabGroupMenu();const e=this.$("sessionTabs");this.isSessionSidebarActive()&&(this._tallTabsEnabled=!0,e.classList.add("tabs-show-folder"),e.classList.remove("tabs-two-rows","tabs-auto-wrap")),document.querySelectorAll("body > .subagent-dropdown").forEach(p=>p.remove()),this.cancelHideSubagentDropdown();const t=e.scrollLeft,s=e.scrollTop,i=this._lastRenderedActiveTabId,n=!e.querySelector(".session-tab"),o=e.contains(document.activeElement)||this._tabRefocusAfterEdit===!0,a=this._tabFocusIdentity||(o?this._tabTreeIdentity(document.activeElement):null);this._tabFocusIdentity=null,this._tabRefocusAfterEdit=!1;const r=[],c=this.sessionOrder,l=this.isRichTabRows(),d=this._tabRailSortOrder(c.filter(p=>this.sessions.has(p))),h=new Map;let f=0;for(const p of c){const m=this.sessions.get(p);if(!m)continue;const T=d?.has(p)?` style="order:${d.get(p)}"`:"",y=p===this.activeSessionId&&!this.activeWebviewId,D=m.status||"idle",L=this.getSessionName(m),w=m.mode||"claude",P=m.color||"default",N=m.taskStats||{running:0,total:0},$=N.running>0,B=this.tabAlerts.get(p),_=B==="action"?" tab-alert-action":B==="idle"?" tab-alert-idle":"",x=this.terminalLoadStates.get(p),O=this.minimizedSubagents.get(p),M=(O?.size||0)>0?this.renderSubagentTabBadge(p,O):"",k=this.renderUltracodeTabBadge?this.renderUltracodeTabBadge(p):"",A=m.workingDir&&m.workingDir.split("/").pop()||"",E=(this._tallTabsEnabled??!1)&&m.name&&A&&A!==L,R=parseSessionPrefix(L),V=R&&R.suffix?`<span class="tab-name-prefix">${escapeHtml(R.prefix)}: </span>${escapeHtml(R.suffix)}`:escapeHtml(L),G=R&&R.suffix?m.workingDir?`${R.prefix} (${m.workingDir})`:R.prefix:m.workingDir||"",v=l?this._sidebarRichRow(p,m):null,K=this._sidebarRichMetaHTML(v),g=v?` tab-state-${v.state}`:"",C=v?` data-tab-state="${v.state}" data-tab-meta-sig="${v.state}${v.exited?"+exited":""}:${v.since?v.since.at:0}:${v.createdAt}:${escapeHtml(v.watching)}"`:"",W=paneExitLabel(m.paneExit),I=this.shouldInlineSessionActions(),F=`<span class="tab-actions"><span class="tab-gear" onclick="event.stopPropagation(); app.openSessionOptions(${escapeHtml(JSON.stringify(p))})" title="Session options" aria-label="Session options" tabindex="0">⚙</span><span class="tab-detach" onclick="event.stopPropagation(); app.detachSession(${escapeHtml(JSON.stringify(p))})" title="Open in a new window" aria-label="Open session in a new window" tabindex="0">⧉</span><span class="tab-close" onclick="event.stopPropagation(); app.requestCloseSession(${escapeHtml(JSON.stringify(p))})" title="Close session" aria-label="Close session" tabindex="0">×</span><button type="button" class="tab-more" onclick="event.stopPropagation(); app.openTabRailActionMenu(event, ${escapeHtml(JSON.stringify(p))})" title="Session actions" aria-label="Session actions">⋯</button></span>`;h.set(p,`<div class="session-tab ${y?"active":""}${_}${g}${W?" tab-agent-exited":""}${x?" tab-loading":""}${this.hasTabDetachOverride(p)?" tab-show-detach":""}"${C}${T} data-id="${p}" data-color="${P}" ${x?`data-load-phase="${escapeHtml(x.phase)}"`:""} onclick="app.handleSessionTabClick(event, ${escapeHtml(JSON.stringify(p))})" oncontextmenu="event.preventDefault(); app.startInlineRename(${escapeHtml(JSON.stringify(p))})" tabindex="0" role="tab" aria-selected="${y?"true":"false"}" aria-busy="${x?"true":"false"}" aria-label="${escapeHtml(paneExitAriaLabel(L,W))}" ${G?`title="${escapeHtml(G)}"`:""}>
|
|
19
|
-
${f<9?'<span class="tab-number">'+(f+1)+"</span>":""}
|
|
20
|
-
${x?'<span class="tab-load-spinner" aria-hidden="true"></span>':""}
|
|
21
|
-
<span class="tab-status ${D}" aria-hidden="true"></span>
|
|
22
|
-
<span class="tab-info">
|
|
23
|
-
<span class="tab-name-row">
|
|
24
|
-
${w==="shell"?'<span class="tab-mode shell" aria-hidden="true">sh</span>':w==="opencode"?'<span class="tab-mode opencode" aria-hidden="true">oc</span>':w==="codex"?'<span class="tab-mode codex" aria-hidden="true">cx</span>':w==="gemini"?'<span class="tab-mode gemini" aria-hidden="true">gm</span>':w==="antigravity"?'<span class="tab-mode antigravity" aria-hidden="true">ag</span>':w==="pi"?'<span class="tab-mode pi" aria-hidden="true">pi</span>':w==="grok"?'<span class="tab-mode grok" aria-hidden="true">gk</span>':w==="deepseek"?'<span class="tab-mode deepseek" aria-hidden="true">ds</span>':w==="omp"?'<span class="tab-mode omp" aria-hidden="true">om</span>':""}
|
|
25
|
-
<span class="tab-name" data-session-id="${p}" data-full-name="${escapeHtml(L)}">${V}</span>
|
|
26
|
-
${W?`<span class="tab-exited-badge" data-i18n-skip aria-hidden="true">${escapeHtml(W)}</span>`:""}
|
|
27
|
-
${I?F:""}
|
|
28
|
-
<span class="tab-detached-badge" aria-hidden="true">detached</span>
|
|
29
|
-
</span>
|
|
30
|
-
${E?`<span class="tab-folder">\u{1F4C1} ${escapeHtml(A)}</span>`:""}
|
|
31
|
-
${K}
|
|
32
|
-
</span>
|
|
33
|
-
${$?`<span class="tab-badge" onclick="event.stopPropagation(); app.toggleTaskPanel()" aria-label="${N.running} running tasks">${N.running}</span>`:""}
|
|
34
|
-
${M}
|
|
35
|
-
${k}
|
|
36
|
-
${I?"":F}
|
|
37
|
-
</div>`),f++}const u=this._projectTabGroups();if(u){const p=new Map((this.webviewOrder||[]).filter(m=>this.webviews?.has(m)).map((m,T)=>[m,f+T]));r.push(window.CodemanTabLayout.renderProjection(u,m=>m.kind==="session"?h.get(m.id)||"":this.renderWebviewTab?.(m.id,p.get(m.id)??1/0)||"",escapeHtml)),this._hiddenTabGroupByRef=new Map(Object.entries(u.hiddenTabGroupByRef))}else r.push(...h.values()),r.push(this.renderWebviewTabs?this.renderWebviewTabs(f):""),this._hiddenTabGroupByRef=new Map;this._lastTabGroupStructureKey=this._tabGroupStructureKey(u),e.innerHTML=r.join(""),e.classList.toggle("session-tabs--grouped",!!u),this._applyTabListRole(e,!!u),u&&(this._applyTabTreeSemantics(e,{identity:a,refocus:o}),this._syncTabGroupHeaderAlerts(e,u)),e.scrollLeft=t,e.scrollTop=s,this._lastRenderedActiveTabId=this.activeSessionId,(n||i!==this.activeSessionId)&&this._scrollActiveTabIntoView(this.activeSessionId,n?"auto":"smooth"),this.setupTabDragHandlers(),this._bindTabLayoutPointerDrag(e),this.setupTabKeyboardNavigation(e),this.updateConnectionLines(),this.updateTabOverflowMode(),this._applyTabEntrances?.(),this.applySidebarFilter(this._sidebarFilter),l?this._startSidebarRichClock():this._stopSidebarRichClock()}setupTabKeyboardNavigation(e){this._tabKeydownHandler&&e.removeEventListener("keydown",this._tabKeydownHandler),this._tabKeydownHandler=t=>{if(e.getAttribute("role")==="tree"){this._handleTabTreeKeydown(t,e);return}if(!["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Home","End","Enter"," "].includes(t.key))return;const s=[...e.querySelectorAll(".session-tab:not(.tab-filtered-out)")];if(this.isTabRailSorted()){const o=a=>Number(getComputedStyle(a).order)||0;s.sort((a,r)=>o(a)-o(r))}const i=s.indexOf(document.activeElement);if((t.key==="Enter"||t.key===" ")&&i>=0){t.preventDefault(),this._activateTabRow(s[i]);return}if(i<0)return;let n;switch(t.key){case"ArrowLeft":case"ArrowUp":n=i>0?i-1:s.length-1;break;case"ArrowRight":case"ArrowDown":n=i<s.length-1?i+1:0;break;case"Home":n=0;break;case"End":n=s.length-1;break;default:return}t.preventDefault(),s[n]?.focus()},e.addEventListener("keydown",this._tabKeydownHandler),this._tabTreeFocusinHandler||(this._tabTreeFocusinHandler=t=>{if(e.getAttribute("role")!=="tree")return;const s=t.target?.closest?.('[role="treeitem"]');s&&e.contains(s)&&this._setTabTreeStop(e,s)},e.addEventListener("focusin",this._tabTreeFocusinHandler))}_activateTabRow(e){if(e?.dataset.webviewId)return this.openWebview(e.dataset.webviewId);if(e?.dataset.id)return this.selectSession(e.dataset.id,{forceReload:!0})}_applyTabListRole(e,t){t?(e.setAttribute("role","tree"),e.setAttribute("aria-label","Sessions")):e.getAttribute("role")==="tree"&&(e.setAttribute("role","tablist"),e.setAttribute("aria-label","Session tabs"))}_tabTreeIdentity(e){const t=e?.closest?.("[data-tab-group-header], .session-tab");return t?t.dataset.tabGroupHeader?`group:${t.dataset.tabGroupHeader}`:t.dataset.webviewId?`webview:${t.dataset.webviewId}`:t.dataset.id?`session:${t.dataset.id}`:null:null}_tabTreeItems(e){const t=this.isTabRailSorted(),s=n=>Number(getComputedStyle(n).order)||0,i=[];for(const n of e.querySelectorAll(".tab-layout-group")){const o=n.querySelector(':scope > [role="treeitem"]');o&&i.push(o);const a=[...n.querySelectorAll('.session-tab[role="treeitem"]:not(.tab-filtered-out)')];t&&a.sort((r,c)=>s(r)-s(c)),i.push(...a)}return i}_setTabTreeStop(e,t){for(const s of e.querySelectorAll('[role="treeitem"]'))s.tabIndex=s===t?0:-1}_applyTabTreeSemantics(e,{identity:t=null,refocus:s=!1}={}){for(const r of e.querySelectorAll(".session-tab")){r.setAttribute("role","treeitem"),r.setAttribute("aria-selected",r.classList.contains("active")?"true":"false"),r.setAttribute("aria-level",r.closest('[role="group"]')?"2":"1");for(const c of r.querySelectorAll("[tabindex], button, a[href], input, select, textarea"))c.tabIndex=-1}for(const r of e.querySelectorAll("[data-tab-group-header]"))r.setAttribute("aria-level","1");const i=this._applyTabTreePositions(e),n=r=>r?i.find(c=>this._tabTreeIdentity(c)===r):null,o=t?this._hiddenTabGroupByRef?.get(t):null,a=n(t)||(o?n(`group:${o}`):null)||i.find(r=>r.getAttribute("aria-selected")==="true")||i[0];a&&(this._setTabTreeStop(e,a),s&&document.activeElement!==a&&a.focus())}_applyTabTreePositions(e){const t=this._tabTreeItems(e),s=new Map;for(const i of t){const n=i.getAttribute("aria-level")==="2"?i.closest('[role="group"]'):e;s.has(n)||s.set(n,[]),s.get(n).push(i)}for(const i of s.values())i.forEach((n,o)=>{const a=String(i.length),r=String(o+1);n.getAttribute("aria-setsize")!==a&&n.setAttribute("aria-setsize",a),n.getAttribute("aria-posinset")!==r&&n.setAttribute("aria-posinset",r)});return t}_syncTabGroupHeaderAlerts(e,t){const s=window.CodemanTabLayout?.hiddenGroupAlerts(t,i=>this.tabAlerts?.get(i))||{};for(const i of e.querySelectorAll("[data-tab-group-header]")){const n=s[i.dataset.tabGroupHeader];i.classList.toggle("tab-alert-action",n==="action"),i.classList.toggle("tab-alert-idle",n==="idle")}}_syncTabTreeSelection(e){if(e?.getAttribute("role")==="tree")for(const t of e.querySelectorAll(".session-tab"))t.setAttribute("aria-selected",t.classList.contains("active")?"true":"false")}_handleTabTreeKeydown(e,t){if(e.target?.closest?.('input, textarea, select, [contenteditable="true"]'))return;const s=this._tabTreeItems(t),i=e.target?.closest?.('[role="treeitem"]');if(!i||i!==e.target)return;const n=s.indexOf(i);if(n<0)return;const o=i.dataset.tabGroupHeader||null,a=i.getAttribute("aria-expanded")==="true",r=i.hasAttribute("aria-expanded"),c=d=>{d&&(this._setTabTreeStop(t,d),d.focus())},l=d=>{this._tabFocusIdentity=`group:${o}`,this.toggleTabGroupCollapsed(o,d)};switch(e.key){case"ArrowDown":case"ArrowUp":{const d=e.key==="ArrowDown"?1:-1;c(s[(n+d+s.length)%s.length]);break}case"Home":c(s[0]);break;case"End":c(s[s.length-1]);break;case"ArrowRight":if(!o||!r)return;if(!a)l(!1);else{const d=s.find(h=>h.closest('[role="group"]')?.id===i.getAttribute("aria-owns"));if(!d)return;c(d)}break;case"ArrowLeft":if(o){if(!r||!a)return;l(!0)}else{const d=i.closest('[role="group"]'),h=d?t.querySelector(`[aria-owns="${CSS.escape(d.id)}"]`):null;if(!h)return;c(h)}break;case"Enter":case" ":o?l():this._activateTabRow(i);break;case"F2":if(!o||!this.startTabGroupRename(o))return;break;case"F10":case"ContextMenu":{if(e.key==="F10"&&!e.shiftKey)return;const d={preventDefault(){},stopPropagation(){},currentTarget:i};if(o)this.openTabGroupMenu(d,o);else if(i.dataset.id)this.openTabRailActionMenu?.(d,i.dataset.id);else if(i.dataset.webviewId)this.openTabWebviewMenu(d,i.dataset.webviewId);else return;break}default:return}e.preventDefault()}handleSessionTabClick(e,t){return e?.preventDefault?.(),!(typeof KeyboardHandler<"u"&&KeyboardHandler.keyboardVisible===!0)&&MobileDetection.isTouchDevice()&&document.activeElement?.blur?.(),this.selectSession(t,{forceReload:!0})}syncSessionOrder(){const e=new Set(this.sessions.keys()),s=this.loadSessionOrder().filter(o=>e.has(o)),i=new Set(s),n=[...e].filter(o=>!i.has(o));this.sessionOrder=[...s,...n]}loadSessionOrder(){try{const e=localStorage.getItem("codeman-session-order");return e?JSON.parse(e):[]}catch{return[]}}saveSessionOrder(){try{localStorage.setItem("codeman-session-order",JSON.stringify(this.sessionOrder))}catch{}const e=[...this.sessionOrder];this._debouncedCall("saveSessionOrderServer",()=>{fetch("/api/session-order",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({order:e})}).catch(()=>{})},400)}_onSessionOrderChanged(e){if(!e||!Array.isArray(e.order))return;try{localStorage.setItem("codeman-session-order",JSON.stringify(e.order))}catch{}const t=JSON.stringify(this.sessionOrder);this.syncSessionOrder(),JSON.stringify(this.sessionOrder)!==t&&this._fullRenderSessionTabs()}_ensureTabLayoutCoordinator(){return this._tabLayoutCoordinator?this._tabLayoutCoordinator:window.CodemanTabLayout?(this._tabLayoutCoordinator=window.CodemanTabLayout.createLoadCoordinator({fetchLayout:async()=>{const e=await this._apiJson("/api/tab-layout");if(!e?.layout)throw new Error("Tab layout unavailable");return e.layout},applyLayout:e=>this._applyTabLayout(e),applyFallback:()=>this._applyTabLayout(null),retryDelayMs:5e3,maxRetryDelayMs:6e4,maxRetries:4,scheduleRetry:(e,t)=>setTimeout(e,t),cancelRetry:e=>clearTimeout(e)}),this._tabLayoutCoordinator):null}_loadTabLayout(){return this._ensureTabLayoutCoordinator()?.load()??Promise.resolve(!1)}_onTabLayoutChanged(e){const t=window.__codemanUser;if(!(t?.multiUser&&typeof e?.owner=="string"&&e.owner!==t.username)&&!(Number.isSafeInteger(e?.version)&&this.tabLayout&&e.version<=this.tabLayout.version)){if(this._tabLayoutEditor?.hasPending()){this._tabLayoutReloadPending=!0;return}this._loadTabLayout()}}_applyTabLayout(e){let t=null;if(e)try{t=window.CodemanTabLayout.normalizeLayout(e)}catch{t=null}if(t&&this.tabLayout&&t.version<this.tabLayout.version)return;const s=this._tabLayoutEditor;if(s){if(!t&&s.hasPending()){this._tabLayoutReloadPending=!0;return}if(t&&s.isWriting()){this._tabLayoutReloadPending=!0;return}if(t&&s.hasPending()&&s.adoptExternal(t))return;s.hasPending()&&this.showToast?.("Your tab group edit was not saved.","error"),s.dispose(),this._tabLayoutEditor=null}this.tabLayout=t;const i=this._getTabCollapseStorage(),n=i&&t?window.CodemanTabLayout.loadCollapsedGroupIds(i,t.groups.map(o=>o.id)):{ids:[],ok:!t};n.ok||(this._tabCollapseStorageFailed=!0),this.collapsedTabGroupIds=new Set(n.ids),this._isTabGroupStructureStale()&&this._fullRenderSessionTabs(),t&&!this._tabLayoutRestoreChecked&&(this._tabLayoutRestoreChecked=!0,this._restorePendingTabLayoutEdits())}_getTabCollapseStorage(){if(this._tabCollapseStorageFailed)return null;try{return window.localStorage}catch{return this._tabCollapseStorageFailed=!0,null}}_projectTabGroups(){return!this.tabLayout||this._tabOrientation()!=="vertical"||!window.CodemanTabLayout?null:window.CodemanTabLayout.project(this.tabLayout,{liveSessionIds:this.sessionOrder.filter(e=>this.sessions.has(e)),openWebviewIds:(this.webviewOrder||[]).filter(e=>this.webviews?.has(e)),collapsedGroupIds:[...this.collapsedTabGroupIds],activeSessionId:this.activeSessionId,activeWebviewId:this.activeWebviewId})}_tabGroupStructureKey(e){return window.CodemanTabLayout?.structureKey(this.tabLayout,e,[...this.collapsedTabGroupIds])??null}_isTabGroupStructureStale(e=this._projectTabGroups()){return this._tabGroupStructureKey(e)!==this._lastTabGroupStructureKey}toggleTabGroupCollapsed(e,t){if(!this.tabLayout?.groups?.some(a=>a.id===e))return!1;const s=new Set(this.collapsedTabGroupIds),i=t===void 0?!s.has(e):t===!0;i?s.add(e):s.delete(e);const n=this._getTabCollapseStorage(),o=n?window.CodemanTabLayout.saveCollapsedGroupIds(n,[...s]):{ids:[],ok:!1};return o.ok||(this._tabCollapseStorageFailed=!0),this.collapsedTabGroupIds=new Set(o.ids),this._fullRenderSessionTabs(),this.collapsedTabGroupIds.has(e)===i}_tabLayoutEditable(){return!!(this.tabLayout&&window.CodemanTabLayout&&this._tabOrientation()==="vertical")}_tabLayoutParents(){const e={};for(const t of this.sessions.values())t?.parentSessionId&&t.parentSessionId!==t.id&&(e[t.id]=t.parentSessionId);return e}async _putTabLayout({baseVersion:e,layout:t}){const s={baseVersion:e,layout:{...t,updatedAt:t.updatedAt||new Date().toISOString()}},i=await this._api("/api/tab-layout",{method:"PUT",body:s});if(!i)return{ok:!1,status:0,layout:null};let n=null;try{n=await i.json()}catch{}return{ok:i.ok,status:i.status,layout:n?.data?.layout||null}}_ensureTabLayoutEditor(){return this._tabLayoutEditor||!this.tabLayout?this._tabLayoutEditor||null:(this._tabLayoutEditor=window.CodemanTabLayout.createEditCoordinator({initialLayout:this.tabLayout,put:e=>this._putTabLayout(e),fetchLayout:async()=>{const e=await this._apiJson("/api/tab-layout");if(!e?.layout)throw new Error("Tab layout unavailable");return e.layout},applyLayout:e=>this._adoptEditedTabLayout(e),reportError:e=>this.showToast?.(e,"error"),onFailure:()=>{this._tabLayoutReloadPending=!0},onSettled:()=>{this._tabLayoutReloadPending&&(this._tabLayoutReloadPending=!1,this._loadTabLayout())}}),this._tabLayoutEditor)}_adoptEditedTabLayout(e){this.tabLayout=e;const t=this._getTabCollapseStorage();if(t){const s=window.CodemanTabLayout.loadCollapsedGroupIds(t,e.groups.map(i=>i.id));s.ok&&(this.collapsedTabGroupIds=new Set(s.ids))}this._fullRenderSessionTabs()}editTabLayout(e,t){if(!this._tabLayoutEditable())return!1;const s=document.activeElement,i=this.$("sessionTabs");t&&(!s||s===document.body||i?.contains(s))&&(this._tabFocusIdentity=t,this._tabRefocusAfterEdit=!0);try{return this._ensureTabLayoutEditor().enqueue(e),!0}catch(n){return this._tabRefocusAfterEdit=!1,this.showToast?.(n?.message||"Could not save tab groups.","error"),!1}}_newTabGroupId(){return globalThis.crypto?.randomUUID?.()||`group-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}createTabGroup({ref:e=null,index:t}={}){if(!this._tabLayoutEditable())return!1;const s=this._newTabGroupId(),i=window.CodemanI18n?.t?.("New group")||"New group";return this.editTabLayout({type:"createGroup",id:s,name:i,...Number.isInteger(t)?{index:t}:{}},`group:${s}`)?(e&&this.editTabLayout({type:"moveRef",ref:e,groupId:s,index:0,parents:this._tabLayoutParents()}),this.startTabGroupRename(s),!0):!1}deleteTabGroup(e){const t=this.tabLayout?.groups||[],s=t.findIndex(n=>n.id===e);if(s<0)return!1;if(!window.confirm(`Delete group "${t[s].name}"? Its tabs move to Ungrouped.`))return this.$("sessionTabs")?.querySelector(`[data-tab-group-header="${CSS.escape(e)}"]`)?.focus(),!1;const i=t[s+1]||t[s-1];return this.editTabLayout({type:"deleteGroup",groupId:e},i?`group:${i.id}`:null)}moveTabGroup(e,t){const s=this.tabLayout?.groups||[],i=s.findIndex(o=>o.id===e),n=i+t;return i<0||n<0||n>=s.length?!1:this.editTabLayout({type:"reorderGroup",groupId:e,index:n},`group:${e}`)}_tabRefLocation(e){const t=i=>i.kind===e.kind&&i.id===e.id;for(const i of this.tabLayout?.groups||[]){const n=i.refs.findIndex(t);if(n>=0)return{groupId:i.id,refs:i.refs,index:n}}const s=this.tabLayout?.ungrouped?.findIndex(t)??-1;return s>=0?{groupId:null,refs:this.tabLayout.ungrouped,index:s}:null}moveTabRef(e,t,s=null,i="before"){const n=this._tabLayoutParents();let o;try{o=window.CodemanTabLayout.moveDestination(this.tabLayout,e,t,s,i,n)}catch{return!1}return this.editTabLayout({type:"moveRef",ref:e,...o,parents:n},`${e.kind}:${e.id}`)}_tabRefMoveActions(e){if(!this._tabLayoutEditable())return[];const t=this._tabRefLocation(e);if(!t)return[];const s=[];if(this.tabLayout.groups.length>0&&!this.isTabRailSorted()){const n=new Set(window.CodemanTabLayout.movingRefKeys(this.tabLayout,e,this._tabLayoutParents())),o=t.refs[t.index-1],a=t.refs.slice(t.index+1).find(r=>!n.has(`${r.kind}:${r.id}`));o&&s.push({label:"Move up",run:()=>this.moveTabRef(e,t.groupId,o,"before")}),a&&s.push({label:"Move down",run:()=>this.moveTabRef(e,t.groupId,a,"after")})}for(const n of this.tabLayout.groups)n.id!==t.groupId&&s.push({label:`Move to "${n.name}"`,run:()=>this.moveTabRef(e,n.id)});return t.groupId!==null&&s.push({label:"Move to Ungrouped",run:()=>this.moveTabRef(e,null)}),this._canCreateTabGroup()&&s.push({label:"Move to new group",run:()=>this.createTabGroup({ref:e})}),s}closeTabGroupMenu({restoreFocus:e=!1}={}){const t=this._tabGroupMenu;if(!t)return;const s=this._tabGroupMenuTrigger,i=this._tabGroupMenuKey;if(this._tabGroupMenu=null,this._tabGroupMenuTrigger=null,this._tabGroupMenuKey=null,document.removeEventListener("pointerdown",this._tabGroupMenuOutside,!0),document.removeEventListener("keydown",this._tabGroupMenuKeydown,!0),window.removeEventListener("resize",this._tabGroupMenuResize),this._tabGroupMenuOutside=this._tabGroupMenuKeydown=this._tabGroupMenuResize=null,t.remove(),!e)return;const n=this.$("sessionTabs");(s?.isConnected&&s.closest('[role="treeitem"]')||[...n?.querySelectorAll('[role="treeitem"]')||[]].find(a=>this._tabTreeIdentity(a)===i))?.focus()}_canCreateTabGroup(){const e=window.CodemanTabLayout?.MAX_GROUPS;return!e||(this.tabLayout?.groups?.length||0)<e}openTabGroupMenu(e,t){const s=this.tabLayout?.groups||[],i=s.findIndex(n=>n.id===t);return i<0?!1:this._openTabLayoutMenu(e,`group:${t}`,"Group actions",[{label:"Rename group",run:()=>this.startTabGroupRename(t)},...this._canCreateTabGroup()?[{label:"New group",run:()=>this.createTabGroup({index:i+1})}]:[],...i>0?[{label:"Move group up",run:()=>this.moveTabGroup(t,-1)}]:[],...i<s.length-1?[{label:"Move group down",run:()=>this.moveTabGroup(t,1)}]:[],{label:"Delete group",className:"danger",run:()=>this.deleteTabGroup(t)}])}openTabWebviewMenu(e,t){const s=this._tabRefMoveActions({kind:"webview",id:t});return s.length?this._openTabLayoutMenu(e,`webview:${t}`,"Web tab actions",[{label:"Web tab settings",run:()=>this.showWebviewModal?.(t)},...s]):(this.showWebviewModal?.(t),!1)}_openTabLayoutMenu(e,t,s,i){e?.preventDefault?.(),e?.stopPropagation?.();const n=e?.currentTarget||null;if(this._tabGroupMenu&&this._tabGroupMenuKey===t)return this.closeTabGroupMenu(),!1;if(this.closeTabGroupMenu(),this.closeTabRailActionMenu?.(),!this._tabLayoutEditable())return!1;const o=document.createElement("div");o.className="tab-rail-action-menu tab-layout-group-action-menu",o.setAttribute("role","menu"),o.setAttribute("aria-label",s);for(const d of i){const h=document.createElement("button");h.type="button",h.setAttribute("role","menuitem"),h.textContent=d.label,d.className&&(h.className=d.className),h.addEventListener("click",()=>{this.closeTabGroupMenu(),d.run()}),o.appendChild(h)}document.body.appendChild(o);const r=((n?.getBoundingClientRect?n:null)||this.$("sessionTabs"))?.getBoundingClientRect?.()||{left:8,bottom:8,right:8},c=o.getBoundingClientRect(),l=e?.clientX&&e.type==="contextmenu"?e.clientX:r.left;return o.style.left=`${Math.max(8,Math.min(l,window.innerWidth-c.width-8))}px`,o.style.top=`${Math.max(8,Math.min(r.bottom+4,window.innerHeight-c.height-8))}px`,this._tabGroupMenu=o,this._tabGroupMenuTrigger=n,this._tabGroupMenuKey=t,this._tabGroupMenuOutside=d=>{o.contains(d.target)||n&&n.contains?.(d.target)||this.closeTabGroupMenu()},this._tabGroupMenuKeydown=d=>{d.key==="Escape"&&(d.preventDefault(),d.stopImmediatePropagation(),this.closeTabGroupMenu({restoreFocus:!0}))},this._tabGroupMenuResize=()=>this.closeTabGroupMenu(),document.addEventListener("pointerdown",this._tabGroupMenuOutside,!0),document.addEventListener("keydown",this._tabGroupMenuKeydown,!0),window.addEventListener("resize",this._tabGroupMenuResize),o.addEventListener("keydown",d=>{const h=[...o.querySelectorAll("button")],f=h.indexOf(document.activeElement);d.key==="ArrowDown"||d.key==="ArrowUp"?(d.preventDefault(),h[(f+(d.key==="ArrowDown"?1:-1)+h.length)%h.length]?.focus()):d.key==="Home"||d.key==="End"?(d.preventDefault(),h[d.key==="Home"?0:h.length-1]?.focus()):d.key==="Tab"&&(d.preventDefault(),this.closeTabGroupMenu({restoreFocus:!0}))}),o.addEventListener("focusout",d=>{d.relatedTarget&&o.contains(d.relatedTarget)||this._tabGroupMenu===o&&this.closeTabGroupMenu()}),o.querySelector("button")?.focus(),!0}startTabGroupRename(e){if(!this.tabLayout?.groups?.some(c=>c.id===e))return!1;this._activeRename?.cancel();const t=this.tabLayout?.groups?.find(c=>c.id===e),i=this.$("sessionTabs")?.querySelector(`[data-tab-group-header="${CSS.escape(e)}"]`)?.querySelector(".tab-layout-group-name");if(!t||!i)return!1;this._inlineRenameActive=!0;const n=document.createElement("input");n.type="text",n.className="tab-layout-group-rename-input",n.value=t.name,n.maxLength=60,n.setAttribute("aria-label","Group name"),i.classList.add("tab-layout-group-name--renaming"),i.replaceChildren(n);for(const c of["click","contextmenu","pointerdown"])n.addEventListener(c,l=>l.stopPropagation());let o=!1;const a={groupId:e,cancel:()=>r(!1)},r=(c,{fromBlur:l=!1}={})=>{if(o)return;o=!0;const d=n.value.trim();if(this._activeRename!==a)return;this._activeRename=null,this._inlineRenameActive=!1;const h=this.tabLayout?.groups?.find(u=>u.id===e),f=l?null:`group:${e}`;c&&h&&d&&d!==h.name&&this.editTabLayout({type:"renameGroup",groupId:e,name:d},f)||(f&&(this._tabFocusIdentity=f,this._tabRefocusAfterEdit=!0),this._fullRenderSessionTabs())};return this._activeRename=a,n.addEventListener("keydown",c=>{c.stopPropagation(),!(c.isComposing||c.keyCode===229)&&(c.key==="Enter"?(c.preventDefault(),r(!0)):c.key==="Escape"&&(c.preventDefault(),r(!1)))}),n.addEventListener("blur",()=>r(!0,{fromBlur:!0})),n.focus(),n.select(),!0}_bindTabLayoutPointerDrag(e){!e||e._tabLayoutDragBound||(e._tabLayoutDragBound=!0,e.addEventListener("pointerdown",t=>this._onTabLayoutPointerDown(t,e)),e.addEventListener("pointermove",t=>this._onTabLayoutPointerMove(t,e)),e.addEventListener("pointerup",t=>this._finishTabLayoutPointerDrag(t,e)),e.addEventListener("pointercancel",()=>this._cancelTabLayoutPointerDrag(e)),e.addEventListener("lostpointercapture",()=>this._cancelTabLayoutPointerDrag(e)))}_onTabLayoutPointerDown(e,t){if(this._tabLayoutDrag&&this._cancelTabLayoutPointerDrag(t),e.button!==0||e.pointerType==="touch"||!t.classList.contains("session-tabs--grouped")||this._inlineRenameActive||!this._tabLayoutEditable()||e.target.closest('.tab-actions, .tab-badge, .tab-layout-group-menu, button, input, [onclick*="stopPropagation"]'))return;const s=e.target.closest("[data-tab-group-header]"),i=s?null:e.target.closest(".session-tab");let n=null;if(s?n={type:"group",groupId:s.dataset.tabGroupHeader}:i?.dataset.webviewId?n={type:"ref",ref:{kind:"webview",id:i.dataset.webviewId}}:i?.dataset.id&&(n={type:"ref",ref:{kind:"session",id:i.dataset.id}}),!n)return;const o={pointerId:e.pointerId,x:e.clientX,y:e.clientY,source:n,origin:s||i,active:!1,target:null};o.windowUp=a=>this._finishTabLayoutPointerDrag(a,t),o.windowCancel=()=>this._cancelTabLayoutPointerDrag(t),window.addEventListener("pointerup",o.windowUp,!0),window.addEventListener("pointercancel",o.windowCancel,!0),this._tabLayoutDrag=o}_tabLayoutDropTarget(e,t,s){const i=document.elementFromPoint(e,t);if(!i||!s.contains(i))return null;const n=i.closest(".session-tab"),o=i.closest(".tab-layout-group"),a=o?o.dataset.tabGroupId||null:void 0;if(n&&o&&!this.isTabRailSorted()){const c=n.dataset.webviewId?{kind:"webview",id:n.dataset.webviewId}:{kind:"session",id:n.dataset.id},l=n.getBoundingClientRect();return{type:"ref",ref:c,groupId:a,placement:t>=l.top+l.height/2?"after":"before",element:n}}if(a===void 0)return null;const r=o.querySelector(":scope > .tab-layout-group-header");return a===null?{type:"ungrouped",element:r}:{type:"group",groupId:a,element:r}}_clearTabLayoutDropMarks(e){e.querySelectorAll(".tab-layout-drop-before, .tab-layout-drop-after, .tab-layout-drop-into").forEach(t=>t.classList.remove("tab-layout-drop-before","tab-layout-drop-after","tab-layout-drop-into"))}_onTabLayoutPointerMove(e,t){const s=this._tabLayoutDrag;if(!s||s.pointerId!==e.pointerId)return;if((e.buttons&1)===0){this._cancelTabLayoutPointerDrag(t);return}if(!s.active){if(Math.hypot(e.clientX-s.x,e.clientY-s.y)<6)return;s.active=!0,s.origin.classList.add("tab-layout-dragging"),t.classList.add("tab-layout-drag-active"),this.closeTabGroupMenu(),this.closeTabRailActionMenu?.();try{t.setPointerCapture(e.pointerId)}catch{}this._tabLayoutDragKeydown&&document.removeEventListener("keydown",this._tabLayoutDragKeydown,!0),this._tabLayoutDragKeydown=o=>{o.key==="Escape"&&(o.preventDefault(),o.stopImmediatePropagation(),this._cancelTabLayoutPointerDrag(t))},document.addEventListener("keydown",this._tabLayoutDragKeydown,!0)}e.preventDefault();const i=this._tabLayoutDropTarget(e.clientX,e.clientY,t);if(this._clearTabLayoutDropMarks(t),s.target=i,!i?.element)return;const n=i.type==="ref"&&s.source.type==="ref"?`tab-layout-drop-${i.placement}`:"tab-layout-drop-into";i.element.classList.add(n)}_cancelTabLayoutPointerDrag(e){const t=this._tabLayoutDrag;if(t&&(this._tabLayoutDrag=null,t.windowUp&&window.removeEventListener("pointerup",t.windowUp,!0),t.windowCancel&&window.removeEventListener("pointercancel",t.windowCancel,!0),t.origin?.classList.remove("tab-layout-dragging"),e?.classList.remove("tab-layout-drag-active"),e&&this._clearTabLayoutDropMarks(e),this._tabLayoutDragKeydown&&document.removeEventListener("keydown",this._tabLayoutDragKeydown,!0),this._tabLayoutDragKeydown=null,t.active)){const s=i=>{i.stopPropagation(),i.preventDefault()};window.addEventListener("click",s,{capture:!0,once:!0}),setTimeout(()=>window.removeEventListener("click",s,{capture:!0}),0)}}_finishTabLayoutPointerDrag(e,t){const s=this._tabLayoutDrag;if(!s||s.pointerId!==e.pointerId)return;const i=s.active?this._tabLayoutDropTarget(e.clientX,e.clientY,t)||s.target:null;if(this._cancelTabLayoutPointerDrag(t),!i)return;const n=window.CodemanTabLayout.dropOperation(this.tabLayout,s.source,i,this._tabLayoutParents());if(!n)return;const o=s.source.type==="group"?`group:${s.source.groupId}`:`${s.source.ref.kind}:${s.source.ref.id}`;this.editTabLayout(n,o)}_persistPendingTabLayoutEdits(){const e=this._tabLayoutEditor,t=e?.pendingOperations?.()||[];if(!t.length)return!1;try{sessionStorage.setItem("codeman:tab-layout-pending",JSON.stringify({owner:this._tabLayoutOwnerKey(),baseVersion:e.baseVersion(),savedAt:Date.now(),operations:t}))}catch{}try{const s=e.getLayout();fetch("/api/tab-layout",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({baseVersion:e.baseVersion(),layout:{...s,updatedAt:s.updatedAt||new Date().toISOString()}}),keepalive:!0}).catch(()=>{})}catch{}return!0}_tabLayoutOwnerKey(){const e=window.__codemanUser;return e?e.multiUser?e.username:"@single":null}_restorePendingTabLayoutEdits(){let e;try{const n=sessionStorage.getItem("codeman:tab-layout-pending");if(!n)return!1;e=JSON.parse(n)}catch{return!1}const t=this._tabLayoutOwnerKey();if(t===null)return this._tabLayoutRestoreWaiting||(this._tabLayoutRestoreWaiting=!0,document.addEventListener("codeman:me",()=>{this._tabLayoutRestoreWaiting=!1,this._restorePendingTabLayoutEdits()},{once:!0})),!1;try{sessionStorage.removeItem("codeman:tab-layout-pending")}catch{}const s=e?.operations;if(!Array.isArray(s)||!s.length||!this.tabLayout||!window.CodemanTabLayout||e.owner!==t)return!1;const i=Date.now()-e.savedAt;return!Number.isFinite(i)||i<0||i>TAB_LAYOUT_PENDING_MAX_AGE_MS||!Number.isSafeInteger(e.baseVersion)||e.baseVersion>this.tabLayout.version?!1:this._ensureTabLayoutEditor().restore(s)}setupTabDragHandlers(){const e=this.$("sessionTabs"),t=e.querySelectorAll(".session-tab[data-id]");if(this.isTabRailSorted()||e.classList.contains("session-tabs--grouped")){t.forEach(s=>s.setAttribute("draggable","false"));return}t.forEach(s=>{s.setAttribute("draggable","true"),s.addEventListener("dragstart",i=>{this.draggedTabId=s.dataset.id,s.classList.add("dragging"),i.dataTransfer.effectAllowed="move",i.dataTransfer.setData("text/plain",s.dataset.id)}),s.addEventListener("dragend",()=>{s.classList.remove("dragging"),this.draggedTabId=null,e.querySelectorAll(".session-tab").forEach(i=>{i.classList.remove("drag-over-left","drag-over-right")})}),s.addEventListener("dragover",i=>{if(i.preventDefault(),!this.draggedTabId||this.draggedTabId===s.dataset.id)return;i.dataTransfer.dropEffect="move";const n=s.getBoundingClientRect(),o=this._isVerticalTabList()?i.clientY<n.top+n.height/2:i.clientX<n.left+n.width/2;s.classList.toggle("drag-over-left",o),s.classList.toggle("drag-over-right",!o)}),s.addEventListener("dragleave",()=>{s.classList.remove("drag-over-left","drag-over-right")}),s.addEventListener("drop",i=>{if(i.preventDefault(),s.classList.remove("drag-over-left","drag-over-right"),!this.draggedTabId||this.draggedTabId===s.dataset.id)return;const n=s.dataset.id,o=this.draggedTabId,a=s.getBoundingClientRect(),r=this._isVerticalTabList()?i.clientY<a.top+a.height/2:i.clientX<a.left+a.width/2,c=this.sessionOrder.indexOf(o);let l=this.sessionOrder.indexOf(n);c===-1||l===-1||(this.sessionOrder.splice(c,1),l=this.sessionOrder.indexOf(n),l!==-1&&(r?this.sessionOrder.splice(l,0,o):this.sessionOrder.splice(l+1,0,o),this.saveSessionOrder(),this._fullRenderSessionTabs()))})})}_canSwapActiveTabWith(e){const t=this._projectTabGroups();if(!t)return!0;const s=i=>t.sectionByRef[`session:${i}`];return s(this.activeSessionId)===s(e)}moveActiveTabLeft(){if(!this.activeSessionId)return;const e=this.sessionOrder.indexOf(this.activeSessionId);e<=0||this._canSwapActiveTabWith(this.sessionOrder[e-1])&&([this.sessionOrder[e-1],this.sessionOrder[e]]=[this.sessionOrder[e],this.sessionOrder[e-1]],this.saveSessionOrder(),this._fullRenderSessionTabs())}moveActiveTabRight(){if(!this.activeSessionId)return;const e=this.sessionOrder.indexOf(this.activeSessionId);e===-1||e>=this.sessionOrder.length-1||this._canSwapActiveTabWith(this.sessionOrder[e+1])&&([this.sessionOrder[e],this.sessionOrder[e+1]]=[this.sessionOrder[e+1],this.sessionOrder[e]],this.saveSessionOrder(),this._fullRenderSessionTabs())}getShortId(e){if(!e)return"";let t=this._shortIdCache.get(e);return t||(t=e.slice(0,8),this._shortIdCache.set(e,t)),t}getSessionName(e){return e.name?e.name:e.workingDir?e.workingDir.split("/").pop()||e.workingDir:this.getShortId(e.id)}_notifySession(e,t,s,i,n){const o=this.sessions.get(e);this.notificationManager?.notify({urgency:t,category:s,sessionId:e,sessionName:o?.name||this.getShortId(e),title:i,message:n})}_isUsableXtermSnapshot(e){return!e||typeof e!="string"||e.length<8?!1:e.replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g,"").replace(/\x1b\[[0-9;?]*[ -/]*[@-~]/g,"").replace(/\x1b[()][0-2A-Z]/g,"").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g,"").trim().length>=3}_persistXtermSnapshot(e,t){const s="codeman-xs-",n=()=>Object.keys(localStorage).filter(o=>o.startsWith(s)&&o!==e);try{if(localStorage.getItem(e)===null){const o=new Set(Array.from(this.sessions?.keys?.()||[])),a=n().sort((r,c)=>Number(o.has(r.slice(s.length)))-Number(o.has(c.slice(s.length))));for(;a.length>=10;)localStorage.removeItem(a.shift())}try{localStorage.setItem(e,t)}catch{for(const a of n()){localStorage.removeItem(a);try{localStorage.setItem(e,t);return}catch{}}try{localStorage.removeItem(e)}catch{}}}catch{}}_cleanupPreviousSession(e){const t=this.activeSessionId?this.sessions?.get?.(this.activeSessionId):null;if(this.activeSessionId&&t?.mode!=="shell"&&this._serializeAddon&&this._xtermSnapshots)try{const s=this._serializeAddon.serialize({scrollback:1e3});if(this._isUsableXtermSnapshot(s)){if(this._xtermSnapshots.delete(this.activeSessionId),this._xtermSnapshots.set(this.activeSessionId,s),this._xtermSnapshots.size>20){const i=this._xtermSnapshots.keys().next().value;this._xtermSnapshots.delete(i)}s.length<256*1024&&this._persistXtermSnapshot(`codeman-xs-${this.activeSessionId}`,s)}else{this._xtermSnapshots.delete(this.activeSessionId);try{localStorage.removeItem(`codeman-xs-${this.activeSessionId}`)}catch{}}}catch{}if(this._disconnectWs(),typeof CjkInput<"u")CjkInput.clear();else{const s=document.getElementById("cjkInput");s&&(s.value="")}this._clearTimer("flickerFilterTimeout"),this.flickerFilterBuffer="",this.flickerFilterActive=!1,this._tabCompletionSessionId=null,this._tabCompletionRetries=0,this._tabCompletionBaseText=null,this._clearTimer("_tabCompletionFallback"),this._clearTimer("_clientDropRecoveryTimer"),this._terminalRefreshOwner=null,this._clearTimer("syncWaitTimeout"),this.pendingWrites=[],this.writeFrameScheduled=!1,this._terminalWriteInFlight=!1,this._terminalWriteInFlightBytes=0,this._isLoadingBuffer=!1,this._loadBufferQueue=null,this._bufferLoadOwner=null,this._chunkedWriteGen=(this._chunkedWriteGen||0)+1;try{const s=this.terminal?._core?._compositionHelper;if(s?._isComposing){s._isComposing=!1;const i=this.terminal?.element?.querySelector(".xterm-helper-textarea");i&&i.dispatchEvent(new CompositionEvent("compositionend",{data:""}))}}catch{}this._flushLocalEchoTo(this.activeSessionId),this._localEchoOverlay?.clear(),this._predictiveEcho?.clearPredictions(),this._localEchoOverlay&&!this._flushedOffsets?.has(e)&&this._localEchoOverlay.suppressBufferDetection()}_flushLocalEchoTo(e){if(!e)return;const t=this._localEchoOverlay?.pendingText||"",s=this._localEchoOverlay?.getFlushed()?.count||0,i=this._localEchoOverlay?.getFlushed()?.text||"";t&&this._sendInputAsync(e,t);const n=s+t.length;n>0&&(this._flushedOffsets||(this._flushedOffsets=new Map),this._flushedTexts||(this._flushedTexts=new Map),this._flushedOffsets.set(e,n),this._flushedTexts.set(e,i+t))}_resetTerminalForReplay(){this.terminal.write("\x1Bc")}_recordTerminalLoadTiming(e){this._lastTerminalLoadTiming=e,console.info("[TERMINAL-PERF]",e);const t=(e.cacheResetAndParseMs||0)+(e.freshResetAndParseMs||0)+(e.resetAndParseMs||0),s=e.selectDoneMs??e.totalMs??e.selectToReplayCompleteMs??0;_crashDiag.log(`TERMINAL_LOAD: ${e.trigger} ${e.full?"full":"tail"} ${e.chars} chars ttfb=${e.ttfbMs.toFixed(0)}ms body+json=${e.bodyAndJsonMs.toFixed(0)}ms reset+parse=${t.toFixed(0)}ms total=${s.toFixed(0)}ms server="${e.serverTiming}"${e.refused?" refused-downgrade":""}`)}async _maybeRefetchFullHistory({force:e=!1}={}){const t=this.activeSessionId;if(!t||this._fullHistoryRepullInFlight||this._isLoadingBuffer||this.detachedSessions?.has(t))return;const s=this.sessions.get(t),i=!e&&s?.mode==="shell",n=Date.now(),o=this._fullHistoryRepullUseless?.has(t)?6e4:4e3;if(!(!e&&n-(this._fullHistoryRepullAt.get(t)||0)<o)){this._fullHistoryRepullAt.set(t,n),this._fullHistoryRepullInFlight=!0;try{const a=performance.now(),r=await this._fetchTerminalCapture(i?`/api/sessions/${t}/terminal?full=1&tail=${TERMINAL_TAIL_SIZE}`:`/api/sessions/${t}/terminal?full=1`,{full:!0}),c=r.headersAt,l=r.json?.data??{},d=performance.now(),h=l.terminalBuffer,f={trigger:e?"full-history-button":"full-history-scroll",mode:s?.mode||"unknown",full:!0,source:l.source||"unknown",chars:h?.length||0,ttfbMs:c-a,bodyAndJsonMs:d-c,resetAndParseMs:0,totalMs:0,serverTiming:r.headers?.get?.("server-timing")||"",refused:!1};if(!h||this.activeSessionId!==t)return;const u=this._estimateReplayRows(h,this.terminal.cols),p=this.terminal.buffer.active.length,m=this.terminal.options?.scrollback||0,T=m>0&&p>=m+this.terminal.rows;if(i&&(u<=p||T)){(l.truncated||T)&&(this._fullHistoryRepullUseless||=new Set).add(t),this._logScrollRouting?.("repull-skipped-bounded");return}if(this._replayWouldShrinkBuffer(h,u)){f.refused=!0,f.totalMs=performance.now()-a,this._recordTerminalLoadTiming(f),(this._fullHistoryRepullUseless||=new Set).add(t),this._logScrollRouting?.("repull-refused-downgrade"),this._setHistoryTruncation(t,{...l,exhausted:!0});return}this._setHistoryTruncation(t,i&&l.truncated?{...l,truncationReason:"tail"}:l),this._fullHistoryRepullUseless?.delete(t);const y=this.terminal.buffer.active.length,D=performance.now();this._resetTerminalForReplay();const{parsedAt:L,bufferLength:w,completed:P}=await this.chunkedTerminalWrite(h,TERMINAL_CHUNK_SIZE,t,this._bufferLoadFinishOpts(l,c));if(f.resetAndParseMs=L-D,!P||this.activeSessionId!==t)return;this.sessions.get(t)?.mode!=="shell"?this.terminalBufferCache.set(t,h):this.terminalBufferCache.delete(t);const N=w-y;N>0?this.terminal.scrollToLine(N):this.terminal.scrollToTop(),this._syncStickyScrollBaseline(),f.totalMs=performance.now()-a,this._recordTerminalLoadTiming(f)}catch{}finally{this._fullHistoryRepullInFlight=!1}}}_setHistoryTruncation(e,t={}){e&&((this._historyTruncation||=new Map).set(e,{truncated:!!t.truncated,reason:t.truncationReason??null,source:t.source??null,fullSize:t.fullSize??0,retainedBytes:t.retainedBytes??0,exhausted:!!t.exhausted}),e===this.activeSessionId&&this._renderHistoryTruncationBanner())}_clearHistoryTruncation(e){this._historyTruncation?.delete(e),e===this.activeSessionId&&this._renderHistoryTruncationBanner()}_renderHistoryTruncationBanner(){const e=document.getElementById("historyTruncationBar");if(!e)return;const t=this.activeSessionId?this._historyTruncation?.get(this.activeSessionId):null,s=computeHistoryTruncationNotice(t||{});if(!s.visible){e.hidden=!0;return}e.textContent="";const i=document.createElement("span");if(i.className="history-trunc-text",i.textContent=s.message,e.appendChild(i),s.canLoadMore){const o=document.createElement("button");o.type="button",o.className="history-trunc-load",o.textContent="Load full history",o.onclick=()=>{o.disabled=!0,o.textContent="Loading\u2026",this._maybeRefetchFullHistory({force:!0}).finally(()=>{this._renderHistoryTruncationBanner()})},e.appendChild(o)}const n=document.createElement("button");n.type="button",n.className="history-trunc-dismiss",n.setAttribute("aria-label","Dismiss history notice"),n.textContent="\xD7",n.onclick=()=>{e.hidden=!0},e.appendChild(n),e.hidden=!1}_shouldFocusTerminalForTabSwitch(){return typeof MobileDetection>"u"||!MobileDetection.isTouchDevice()?!0:typeof KeyboardHandler<"u"&&KeyboardHandler.keyboardVisible}async selectSession(e,t={}){if(t?.auto!==!0&&this._urlSessionId&&this._urlSessionId!==e&&this._retireUrlSession(),!this.isSoloWindow&&this.detachedSessions.has(e)&&this._raiseDetached(e))return;const s=t?.forceReload===!0,i=t?.auto!==!0;if(this.activeSessionId===e&&!s){i&&this.markIdleAlertSeen(e);return}if(this.activeSessionId===e&&s){this.terminalBufferCache?.delete(e),this._xtermSnapshots?.delete(e);try{localStorage.removeItem(`codeman-xs-${e}`)}catch{}this._clearTimer("syncWaitTimeout"),this.pendingWrites=[],this.writeFrameScheduled=!1,this._terminalWriteInFlight=!1,this._terminalWriteInFlightBytes=0,this._isLoadingBuffer=!1,this._loadBufferQueue=null,this._terminalRefreshOwner=null,this._chunkedWriteGen=(this._chunkedWriteGen||0)+1,this._flushLocalEchoTo(e),this.activeSessionId=null}const n=this._shouldFocusTerminalForTabSwitch();n&&this.terminal&&this.terminal.focus();const o=performance.now(),a=this.sessions.get(e)?.name||e.slice(0,8);_crashDiag.log(`SELECT: ${a}`),console.log(`[CRASH-DIAG] selectSession START: ${e.slice(0,8)}`);const r=++this._selectGeneration;if(this._setTerminalLoadState(e,r,"resizing"),r!==this._selectGeneration){this._clearTerminalLoadState(e,r);return}this._hideWebviewLayer?.(),this._cleanupPreviousSession(e),this.activeSessionId=e,this._activateFileBrowserSession?.(e),this._renderHistoryTruncationBanner();try{localStorage.setItem("codeman-active-session",e)}catch{}this._updateSseSubscription(e),this.hideWelcome(),this.playTerminalEntrance?.(e),i&&this.markIdleAlertSeen(e),this._updateActiveTabImmediate(e),this.closeSessionSidebarOnHandheld(),this.renderSessionTabs(),this.updateAttachmentHistoryBadge?.(),this.attachmentHistoryDrawerOpen&&this.loadAttachmentHistory?.(e),this._updateLocalEchoState(),typeof KeyboardAccessoryBar<"u"&&KeyboardAccessoryBar.refreshForActiveSession(),this.refreshHostWakeBanner?.(e),this._flushedOffsets?.has(e)&&this._localEchoOverlay&&this._localEchoOverlay.setFlushed(this._flushedOffsets.get(e),this._flushedTexts?.get(e)||"",!1);const c=document.querySelector(`.session-tab.active[data-id="${e}"]`);c&&(c.classList.add("tab-glow"),c.addEventListener("animationend",()=>c.classList.remove("tab-glow"),{once:!0}));const l=this.sessions.get(e);if(this.currentSessionWorkingDir=l?.workingDir||null,l&&l.pid===null)if(l.respawnBlocked){const p=l.name||"Session";if(window.confirm(`${p} was stopped after crashing repeatedly. Restart it?`))try{await fetch(`/api/sessions/${e}/interactive`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({clearBreaker:!0})}),l.respawnBlocked=!1,l.status="busy"}catch(m){console.error("Failed to restart crash-looped session:",m)}}else try{const p=l.mode==="shell"?`/api/sessions/${e}/shell`:`/api/sessions/${e}/interactive`;await fetch(p,{method:"POST"}),l.status="busy"}catch(p){console.error("Failed to attach to restored session:",p)}if(this._terminalFontReady&&(await this._terminalFontReady,this._isStaleSelect(r))){this._clearTerminalLoadState(e,r);return}this._restoringFlushedState=!0;const d=this._beginBufferLoad(r);let h=!1,f=0,u=!1;try{this._paneWidthRefused=!1,this.syncTerminalGeometry();const p=await this.sendResize(e,{forceHttp:!0}).catch(()=>!1),m=this.getTerminalDimensions?.();if(this._isStaleSelect(r)){this._clearTerminalLoadState(e,r);return}let T=this._xtermSnapshots?.get(e);if(T&&!this._isUsableXtermSnapshot(T)&&(this._xtermSnapshots?.delete(e),T=null),!T)try{const g=localStorage.getItem(`codeman-xs-${e}`);g&&this._isUsableXtermSnapshot(g)?(T=g,this._xtermSnapshots?.delete(e),this._xtermSnapshots?.set(e,g)):g&&localStorage.removeItem(`codeman-xs-${e}`)}catch{}const y=l&&(l.status==="busy"||l.status==="working");let D=!1;if(T&&!y&&l?.mode!=="shell"){if(_crashDiag.log(`SNAPSHOT_RESTORE: ${(T.length/1024).toFixed(0)}KB`),this._setTerminalLoadState(e,r,"replaying"),this._resetTerminalForReplay(),await new Promise(g=>this.terminal.write(T,g)),this._isStaleSelect(r)){this._clearTerminalLoadState(e,r);return}this.scrollToLastNonEmptyLine(),_crashDiag.log("SNAPSHOT_RESTORE_DONE"),D=!0}const L=this.terminalBufferCache.get(e);if(L&&!y&&!D&&l?.mode!=="shell"){_crashDiag.log(`CACHE_WRITE: ${(L.length/1024).toFixed(0)}KB`),this._setTerminalLoadState(e,r,"replaying");const g=performance.now();this._resetTerminalForReplay();const{parsedAt:C}=await this.chunkedTerminalWrite(L,TERMINAL_CHUNK_SIZE,d);if(f=C-g,this._isStaleSelect(r)){this._clearTerminalLoadState(e,r);return}this.terminal.scrollToBottom(),_crashDiag.log("CACHE_DONE")}else(y||l?.mode==="shell")&&(this._resetTerminalForReplay(),u=!0,_crashDiag.log(l?.mode==="shell"?"CACHE_SKIP_SHELL":"CACHE_SKIP_BUSY"));if(l?.mode!=="shell"&&p&&(await new Promise(g=>setTimeout(g,TUI_REDRAW_SETTLE_MS)),this._isStaleSelect(r))){this._clearTerminalLoadState(e,r);return}this._setTerminalLoadState(e,r,"fetching"),_crashDiag.log("FETCH_START");const w=l?.mode!=="shell"&&!this._fullHistoryLoaded.has(e);w&&this._fullHistoryLoaded.add(e);const P=performance.now(),N=`/api/sessions/${e}/terminal?tail=${TERMINAL_TAIL_SIZE}`;let $;try{$=await this._fetchTerminalCapture(w?`/api/sessions/${e}/terminal?full=1`:N,{full:w})}catch(g){if(g?.name!=="AbortError"||!w)throw g;_crashDiag.log("FULL CAPTURE ABORTED \u2192 tail"),this._fullHistoryLoaded.delete(e),$=await this._fetchTerminalCapture(N)}const B=$.headersAt;if(this._isStaleSelect(r)){this._clearTerminalLoadState(e,r);return}const _=$.json?.data??{},x=performance.now(),O=this._bufferLoadFinishOpts(_,B);_crashDiag.log(`FETCH_DONE: ${_.terminalBuffer?(_.terminalBuffer.length/1024).toFixed(0)+"KB":"empty"} truncated=${_.truncated}`);let H=0;if(_.terminalBuffer){if(D||u||_.terminalBuffer!==L){_crashDiag.log(`REWRITE: ${(_.terminalBuffer.length/1024).toFixed(0)}KB`),this._setTerminalLoadState(e,r,"replaying");const C=performance.now();this._resetTerminalForReplay(),this._setHistoryTruncation(e,_);const{parsedAt:W}=await this.chunkedTerminalWrite(_.terminalBuffer,TERMINAL_CHUNK_SIZE,d,O);if(H=W-C,this._isStaleSelect(r)){this._clearTerminalLoadState(e,r);return}this.terminal.scrollToBottom()}if(l?.mode==="shell")this.terminalBufferCache.delete(e);else if(this.terminalBufferCache.set(e,_.terminalBuffer),this.terminalBufferCache.size>20){const C=this.terminalBufferCache.keys().next().value;this.terminalBufferCache.delete(C)}}else(!L||u)&&(u||this._resetTerminalForReplay(),h=!0);const M={trigger:"session-select",mode:l?.mode||"unknown",full:w,source:_.source||"unknown",chars:_.terminalBuffer?.length||0,ttfbMs:B-P,bodyAndJsonMs:x-B,cacheResetAndParseMs:f,freshResetAndParseMs:H,selectToReplayCompleteMs:performance.now()-o,serverTiming:$.headers?.get?.("server-timing")||""};if(this._isLoadingBuffer&&this._finishBufferLoad(d,h?{flushQueued:!0,since:0}:O),this._markTerminalBufferReconciled(e),this._restoringFlushedState=!1,this._flushedOffsets?.has(e)&&this._localEchoOverlay){this._localEchoOverlay.setFlushed(this._flushedOffsets.get(e),this._flushedTexts?.get(e)||"",!1);const g=this._localEchoOverlay;this.terminal.write("",()=>{g.hasPending&&g.rerender()})}this.sendResize(e);const k=this.getTerminalDimensions?.(),A=_.source==="mux-visible",b=A&&Number.isFinite(_.captureRows)&&!!m&&!!k&&(k.cols!==m.cols||k.rows!==m.rows),E=A&&Number.isFinite(_.captureRows)&&_.captureRows>(this.terminal?.rows||0),R=A&&Number.isFinite(_.captureCols)&&_.captureCols>(this.terminal?.cols||0),V=!!k&&_.captureCols===k.cols&&_.captureRows===k.rows;(typeof requestIdleCallback=="function"?requestIdleCallback:g=>setTimeout(g,16))(()=>{if(r!==this._selectGeneration)return;this.respawnStatus[e]?(this.showRespawnBanner(),this.updateRespawnBanner(this.respawnStatus[e].state),document.getElementById("respawnCycleCount").textContent=this.respawnStatus[e].cycleCount||0,this.updateCountdownTimerDisplay(),this.updateActionLogDisplay(),Object.keys(this.respawnCountdownTimers[e]||{}).length>0&&this.startCountdownInterval()):(this.hideRespawnBanner(),this.stopCountdownInterval());const g=document.getElementById("taskPanel");g&&g.classList.contains("open")&&this.renderTaskPanel();const C=this.sessions.get(e);if(C&&(C.ralphLoop||C.ralphTodos)&&this.updateRalphState(e,{loop:C.ralphLoop,todos:C.ralphTodos}),this.renderRalphStatePanel(),this.updateCliInfoDisplay(),this.renderProjectInsightsPanel(),this.updateSubagentWindowVisibility(),this.loadAppSettingsFromStorage().showFileBrowser){const I=this.$("fileBrowserPanel");if(I&&(I.classList.add("visible"),this.loadFileBrowser(e),!this.fileBrowserDragListeners)){const F=I.querySelector(".file-browser-header");if(F){const U=()=>{if(!I.style.left){const q=I.getBoundingClientRect();I.style.left=`${q.left}px`,I.style.top=`${q.top}px`,I.style.right="auto"}};F.addEventListener("mousedown",U),F.addEventListener("touchstart",U,{passive:!0}),this.fileBrowserDragListeners=this.makeWindowDraggable(I,F),this.fileBrowserDragListeners._onFirstDrag=U}}}}),this._connectWs(e),_crashDiag.log("FOCUS"),n&&this.terminal&&this.terminal.focus(),this.scrollToLastNonEmptyLine(),typeof KeyboardHandler<"u"&&KeyboardHandler.keyboardVisible&&KeyboardHandler.onKeyboardShow();const v=performance.now()-o;M.selectDoneMs=v,this._recordTerminalLoadTiming(M),this._clearTerminalLoadState(e,r),_crashDiag.log(`SELECT_DONE: ${v.toFixed(0)}ms`),console.log(`[CRASH-DIAG] selectSession DONE: ${e.slice(0,8)} in ${v.toFixed(0)}ms`),A&&Number.isFinite(_.captureRows)&&!E&&!R?this._geometryRetryUseless?.delete(e):t?.resizeRetry&&(E||R)&&(this._geometryRetryUseless||=new Set).add(e),(b||E||R)&&!V&&!this._geometryRetryUseless?.has(e)&&!t?.resizeRetry&&!this._isStaleSelect(r)&&(_crashDiag.log(`RESIZE_RETRY: capture ${_.captureCols}x${_.captureRows} vs terminal ${this.terminal?.cols}x${this.terminal?.rows}`+(b?" (size moved under load)":"")),w&&this._fullHistoryLoaded.delete(e),await this.selectSession(e,{auto:!0,forceReload:!0,resizeRetry:!0}))}catch(p){if(this._isLoadingBuffer&&this._finishBufferLoad(d),this._restoringFlushedState=!1,console.error("Failed to load session terminal:",p),this._isStaleSelect(r)){this._clearTerminalLoadState(e,r);return}this._connectWs(e),u&&this.terminal&&this.terminal.write(`\r
|
|
38
|
-
\x1B[2m History did not load.\r
|
|
39
|
-
Live output continues.\r
|
|
40
|
-
Reload to try again.\x1B[0m\r
|
|
41
|
-
`),this._clearTerminalLoadState(e,r)}}_cleanupSessionData(e){this.closeTabRailActionMenu?.(),this._markTerminalBufferReconciled(e),this._activeRename?.sessionId===e&&this._activeRename.cancel(),this.sessions.delete(e);const t=this.sessionOrder.indexOf(e);t!==-1&&(this.sessionOrder.splice(t,1),this.saveSessionOrder()),this.terminalBuffers.delete(e),this.terminalBufferCache.delete(e),this._clearHistoryTruncation(e),this._xtermSnapshots?.delete(e);try{localStorage.removeItem(`codeman-xs-${e}`)}catch{}this._flushedOffsets?.delete(e),this._flushedTexts?.delete(e),typeof KeyboardAccessoryBar<"u"&&KeyboardAccessoryBar.discardComposerDraft?.(e),this._pendingDeliveries?.delete(e),this._seqCounters?.delete(e),this._postDraining?.delete(e),this._persistReliableState(),this.ralphStates.delete(e),this.ralphClosedSessions.delete(e),this.projectInsights.delete(e),this.pendingHooks.delete(e),this.tabAlerts.delete(e),this.attachmentHistoryCounts.delete(e),this.attachmentHistoryDrawerOpen&&this.activeSessionId===e&&this.closeAttachmentHistory?.(),this.terminalLoadStates.delete(e),this.clearCountdownTimers(e),this.closeSessionLogViewerWindows(e),this.closeSessionImagePopups(e),this.closeSessionAttachmentCards(e),this.closeSessionSubagentWindows(e,!0);const s=this.idleTimers.get(e);s&&(clearTimeout(s),this.idleTimers.delete(e)),delete this.respawnStatus[e],delete this.respawnTimers[e],delete this.respawnCountdownTimers[e],delete this.respawnActionLogs[e]}async closeSession(e,t=!0){const s=this.activeSessionId===e;this._closingSessions.add(e);try{if(await this._apiDelete(`/api/sessions/${e}?killMux=${t}`),this._cleanupSessionData(e),s){this.activeSessionId=null;try{localStorage.removeItem("codeman-active-session")}catch{}const i=this.sessionOrder.find(n=>n!==e&&this.sessions.has(n));i?this.selectSession(i,{auto:!0}):(this.terminal.clear(),this.showWelcome(),this.renderRalphStatePanel())}this.renderSessionTabs(),t?this.showToast("Session closed and tmux killed","success"):this.showToast("Tab hidden, tmux still running","info")}catch{this.showToast("Failed to close session","error")}finally{this._closingSessions.delete(e)}}requestCloseSession(e){const t=this.sessions.get(e);if(!t)return;this.pendingCloseSessionId=e;const s=this.getSessionName(t),i=document.getElementById("closeConfirmSessionName");i.textContent=s;const n=document.getElementById("closeConfirmKillTitle");n&&(n.textContent=t.mode==="opencode"?"Kill Tmux & OpenCode":t.mode==="codex"?"Kill Tmux & Codex":t.mode==="gemini"?"Kill Tmux & Gemini":t.mode==="antigravity"?"Kill Tmux & Antigravity":t.mode==="pi"?"Kill Tmux & Pi":t.mode==="grok"?"Kill Tmux & Grok":t.mode==="deepseek"?"Kill Tmux & DeepSeek":t.mode==="omp"?"Kill Tmux & OMP":"Kill Tmux & Claude Code"),document.getElementById("closeConfirmModal").classList.add("active")}cancelCloseSession(){this.pendingCloseSessionId=null,document.getElementById("closeConfirmModal").classList.remove("active")}async confirmCloseSession(e=!0){const t=this.pendingCloseSessionId;this.cancelCloseSession(),t&&await this.closeSession(t,e)}nextSession(){if(this.sessionOrder.length<=1)return;const t=(this.sessionOrder.indexOf(this.activeSessionId)+1)%this.sessionOrder.length;this.selectSession(this.sessionOrder[t])}prevSession(){if(this.sessionOrder.length<=1)return;const t=(this.sessionOrder.indexOf(this.activeSessionId)-1+this.sessionOrder.length)%this.sessionOrder.length;this.selectSession(this.sessionOrder[t])}goHome(){this._retireUrlSession(),this.activeSessionId=null;try{localStorage.removeItem("codeman-active-session")}catch{}this.terminal.clear(),this.showWelcome(),this.renderSessionTabs(),this.renderRalphStatePanel()}ralphWizardStep=1;ralphWizardConfig={taskDescription:"",completionPhrase:"COMPLETE",maxIterations:10,caseName:"testcase",enableRespawn:!1,generatedPlan:null,planGenerated:!1,skipPlanGeneration:!1,planDetailLevel:"detailed",existingPlan:null,useExistingPlan:!1};planLoadingTimer=null;planLoadingStartTime=null;async killActiveSession(){if(!this.activeSessionId){this.showToast("No active session","warning");return}await this.closeSession(this.activeSessionId)}async killAllSessions(){if(this.sessions.size!==0&&confirm(`Kill all ${this.sessions.size} session(s)?`))try{await this._apiDelete("/api/sessions"),this.sessions.clear(),this.terminalBuffers.clear(),this.terminalBufferCache.clear(),this.terminalLoadStates.clear(),this._xtermSnapshots?.clear();try{for(const e of Object.keys(localStorage))e.startsWith("codeman-xs-")&&localStorage.removeItem(e)}catch{}this.activeSessionId=null;try{localStorage.removeItem("codeman-active-session")}catch{}this.respawnStatus={},this.respawnCountdownTimers={},this.respawnActionLogs={},this.stopCountdownInterval(),this.hideRespawnBanner(),this.renderSessionTabs(),this.terminal.clear(),this.showWelcome(),this.showToast("All sessions killed","success")}catch{this.showToast("Failed to kill sessions","error")}}showTimer(){document.getElementById("timerBanner").style.display="flex",this.updateTimer(),this.timerInterval=setInterval(()=>this.updateTimer(),1e3)}hideTimer(){document.getElementById("timerBanner").style.display="none",this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null)}updateTimer(){if(!this.currentRun||this.currentRun.status!=="running")return;const e=Date.now(),t=Math.max(0,this.currentRun.endAt-e),s=this.currentRun.endAt-this.currentRun.startedAt,i=e-this.currentRun.startedAt,n=Math.min(100,i/s*100);document.getElementById("timerValue").textContent=this.formatTime(t),document.getElementById("timerProgress").style.width=`${n}%`,document.getElementById("timerMeta").textContent=`${this.currentRun.completedTasks} tasks | $${this.currentRun.totalCost.toFixed(2)}`}async stopCurrentRun(){if(this.currentRun)try{await fetch(`/api/scheduled/${this.currentRun.id}`,{method:"DELETE"})}catch{this.showToast("Failed to stop run","error")}}formatTime(e){const t=Math.floor(e/1e3),s=Math.floor(t/3600),i=Math.floor(t%3600/60),n=t%60;return`${s.toString().padStart(2,"0")}:${i.toString().padStart(2,"0")}:${n.toString().padStart(2,"0")}`}updateCost(){this.updateTokens()}updateTokens(){this._clearTimer("_updateTokensTimeout"),this._updateTokensTimeout=setTimeout(()=>{this._updateTokensTimeout=null,this._updateTokensImmediate()},200)}_updateTokensImmediate(){let e=0,t=0;this.globalStats?(e=this.globalStats.totalInputTokens||0,t=this.globalStats.totalOutputTokens||0):this.sessions.forEach(a=>{a.tokens&&(e+=a.tokens.input||0,t+=a.tokens.output||0)});const s=e+t;this.totalTokens=s;const i=this.formatTokens(s),n=this.estimateCost(e,t),o=this.$("headerTokens");if(o){const r=this.loadAppSettingsFromStorage().showCost??!1;o.textContent=s>0?r?`${i} tokens \xB7 $${n.toFixed(2)}`:`${i} tokens`:"0 tokens",o.title=this.globalStats?`Lifetime: ${this.globalStats.totalSessionsCreated} sessions created${r?`
|
|
42
|
-
Estimated cost based on Claude Opus pricing`:""}`:`Token usage across active sessions${r?`
|
|
43
|
-
Estimated cost based on Claude Opus pricing`:""}`}}getShortcutRegistry(){const t=this.loadAppSettingsFromStorage().shortcutOverrides||{};return DEFAULT_SHORTCUTS.map(s=>{const i=t[s.id];if(!i)return s;const n={...s};return Array.isArray(i.bindings)&&(n.bindings=i.bindings,delete n.displayBindings),typeof i.disabled=="boolean"&&(n.disabled=i.disabled),n})}matchesShortcutEvent(e,t){return!t||!Array.isArray(t.bindings)?!1:t.bindings.some(s=>{const i=s.modifiers||[];return(i.includes("ctrl")||i.includes("meta"))!==!!(e.ctrlKey||e.metaKey)||i.includes("shift")!==!!e.shiftKey||i.includes("alt")!==!!e.altKey?!1:!!(s.code&&e.code===s.code||s.key&&typeof e.key=="string"&&e.key.toLowerCase()===s.key.toLowerCase())})}showShortcutOverlay(){const e=document.getElementById("shortcutOverlayModal");e&&(this.renderShortcutOverlay(),e.classList.add("active"),e.focus?.())}renderShortcutOverlay(){const e=document.getElementById("shortcutOverlayList");if(!e)return;const t=this.getShortcutRegistry(),s={};for(const n of t){const o=n.group||"General";s[o]||(s[o]=[]),s[o].push(n)}const i=n=>n.displayBindings?n.displayBindings.map(o=>`<kbd>${escapeHtml(o)}</kbd>`).join(" / "):n.bindings?n.bindings.map(o=>{const a=[...(o.modifiers||[]).map(r=>r.charAt(0).toUpperCase()+r.slice(1)),o.key||o.code||""];return`<kbd>${escapeHtml(a.join("+"))}</kbd>`}).join(" / "):"";e.innerHTML=Object.entries(s).map(([n,o])=>`<div class="shortcut-overlay-group"><div class="shortcut-overlay-group-label">${escapeHtml(n)}</div>`+o.map(a=>`<div class="shortcut-overlay-row"><span class="shortcut-overlay-label">${escapeHtml(a.label)}</span><span class="shortcut-overlay-keys">${i(a)}</span></div>`).join("")+"</div>").join("")}closeShortcutOverlay(){const e=document.getElementById("shortcutOverlayModal");e&&e.classList.remove("active")}}try{for(let S=0;S<localStorage.length;S++){const e=localStorage.key(S);if(e&&(e.startsWith("claudeman-")||e.startsWith("claudeman_"))){const t=e.replace(/^claudeman[-_]/,s=>"codeman"+s.charAt(s.length-1));localStorage.getItem(t)===null&&localStorage.setItem(t,localStorage.getItem(e))}}}catch{}let app;document.addEventListener("DOMContentLoaded",()=>{app=new CodemanApp,window.app=app}),window.MobileDetection=MobileDetection;
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|