aicodeman 1.23.0 → 1.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +1 -1
  2. package/dist/web/public/admin-ui.js.gz +0 -0
  3. package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
  4. package/dist/web/public/app.c5cf1b8a.js +36 -0
  5. package/dist/web/public/app.c5cf1b8a.js.br +0 -0
  6. package/dist/web/public/app.c5cf1b8a.js.gz +0 -0
  7. package/dist/web/public/approvals-ui.js.gz +0 -0
  8. package/dist/web/public/constants.f4ea0a19.js.gz +0 -0
  9. package/dist/web/public/cron-ui.js.gz +0 -0
  10. package/dist/web/public/entrance-animations.js.gz +0 -0
  11. package/dist/web/public/home-sessions.js.gz +0 -0
  12. package/dist/web/public/i18n.9ae15b51.js.gz +0 -0
  13. package/dist/web/public/image-input.ee16ad88.js.gz +0 -0
  14. package/dist/web/public/index.html +5 -5
  15. package/dist/web/public/index.html.br +0 -0
  16. package/dist/web/public/index.html.gz +0 -0
  17. package/dist/web/public/input-cjk.87f14251.js.gz +0 -0
  18. package/dist/web/public/keyboard-accessory.0454a3e9.js.gz +0 -0
  19. package/dist/web/public/mobile-handlers.0f83a608.js.gz +0 -0
  20. package/dist/web/public/mobile-overview.js.gz +0 -0
  21. package/dist/web/public/mobile.cab92e3f.css.gz +0 -0
  22. package/dist/web/public/notification-manager.5d229063.js.gz +0 -0
  23. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  24. package/dist/web/public/{panels-ui.50200a8d.js → panels-ui.344de87d.js} +40 -32
  25. package/dist/web/public/panels-ui.344de87d.js.br +0 -0
  26. package/dist/web/public/panels-ui.344de87d.js.gz +0 -0
  27. package/dist/web/public/ralph-panel.6de2d0f8.js.gz +0 -0
  28. package/dist/web/public/ralph-wizard.13a1831e.js.gz +0 -0
  29. package/dist/web/public/readmymind-ui.js.gz +0 -0
  30. package/dist/web/public/respawn-ui.ff0dae4c.js.gz +0 -0
  31. package/dist/web/public/sanitize-html.bc7078d6.js.gz +0 -0
  32. package/dist/web/public/session-lineage.js.gz +0 -0
  33. package/dist/web/public/session-ui.103656d3.js.gz +0 -0
  34. package/dist/web/public/{settings-ui.45f311a7.js → settings-ui.3261b896.js} +1 -1
  35. package/dist/web/public/settings-ui.3261b896.js.br +0 -0
  36. package/dist/web/public/{settings-ui.45f311a7.js.gz → settings-ui.3261b896.js.gz} +0 -0
  37. package/dist/web/public/styles.1938fd02.css.gz +0 -0
  38. package/dist/web/public/subagent-windows.e6ca799f.js.gz +0 -0
  39. package/dist/web/public/sw.js.gz +0 -0
  40. package/dist/web/public/tab-rail-resize.42c24949.js.gz +0 -0
  41. package/dist/web/public/terminal-ui.5e0c230c.js +2 -0
  42. package/dist/web/public/terminal-ui.5e0c230c.js.br +0 -0
  43. package/dist/web/public/terminal-ui.5e0c230c.js.gz +0 -0
  44. package/dist/web/public/ultracode-panel.js.gz +0 -0
  45. package/dist/web/public/ultracode-windows.js.gz +0 -0
  46. package/dist/web/public/upload.html.gz +0 -0
  47. package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
  48. package/dist/web/public/vendor/marked.min.js.gz +0 -0
  49. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  50. package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
  51. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  52. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  53. package/dist/web/public/vendor/xterm-predictive-echo.bd6882b8.js.gz +0 -0
  54. package/dist/web/public/vendor/xterm-zerolag-input.6fee72f2.js.gz +0 -0
  55. package/dist/web/public/vendor/xterm.css.gz +0 -0
  56. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  57. package/dist/web/public/voice-input.4ec670b0.js.gz +0 -0
  58. package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
  59. package/dist/web/public/webview-tabs.js.gz +0 -0
  60. package/package.json +1 -1
  61. package/dist/web/public/app.360ece48.js +0 -36
  62. package/dist/web/public/app.360ece48.js.br +0 -0
  63. package/dist/web/public/app.360ece48.js.gz +0 -0
  64. package/dist/web/public/panels-ui.50200a8d.js.br +0 -0
  65. package/dist/web/public/panels-ui.50200a8d.js.gz +0 -0
  66. package/dist/web/public/settings-ui.45f311a7.js.br +0 -0
  67. package/dist/web/public/terminal-ui.ef68a666.js +0 -2
  68. package/dist/web/public/terminal-ui.ef68a666.js.br +0 -0
  69. package/dist/web/public/terminal-ui.ef68a666.js.gz +0 -0
@@ -1,36 +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=`${new Date().toISOString().slice(11,23)} ${S}`;this._entries.push(e),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("/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("/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.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.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}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;class CodemanApp{constructor(){this.sessions=new Map,this._shortIdCache=new Map,this.sessionOrder=[],this.draggedTabId=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.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.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.pendingWrites=[],this.writeFrameScheduled=!1,this._wasAtBottomBeforeWrite=!0,this.syncWaitTimeout=null,this._isLoadingBuffer=!1,this._loadBufferQueue=null,this._bufferLoadSeq=0,this._bufferLoadOwner=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()),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"),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();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.isComposing||s.keyCode===229)){if(this.shouldOpenCommandPaletteFromShortcut?.(s)){s.preventDefault(),this.openCommandPalette();return}if(s.key==="Escape"&&(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())),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,l=(this.webviewOrder||[])[r];l&&(s.preventDefault(),this.openWebview(l))}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=location.pathname.match(/^\/session\/([^/]+)\/?$/);return e?decodeURIComponent(e[1]):null}catch{return 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("/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)}_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(`/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];this._sseHandlerWrappers.set(i,a=>{try{o.call(this,a.data?JSON.parse(a.data):{})}catch(r){console.error(`[SSE] Error handling ${i}:`,r)}})}}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.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)}_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()}_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._wsSessionId===e.id||this._onSessionTerminal(e)}_onSSENeedsRefresh(e){this._wsReady&&this._wsSessionId===e?.id||this._onSessionNeedsRefresh(e)}_onSSEClearTerminal(e){this._wsReady&&this._wsSessionId===e?.id||this._onSessionClearTerminal(e)}_onSessionTerminal(e){if(e.id===this.activeSessionId){if(e.data.length>32768&&_crashDiag.log(`TERMINAL: ${(e.data.length/1024).toFixed(0)}KB`),(this.pendingWrites?.reduce((s,i)=>s+i.length,0)||0)+(this.flickerFilterBuffer?.length||0)>131072){this._clientDropRecoveryTimer||(this._clientDropRecoveryTimer=setTimeout(()=>{this._clientDropRecoveryTimer=null,this._onSessionNeedsRefresh()},2e3));return}this.batchTerminalWrite(e.data)}}_sanitizeHtml(e){return typeof window<"u"&&typeof window.sanitizeMarkdownHtml=="function"?window.sanitizeMarkdownHtml(e):String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_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){const t=e||"";if(typeof marked<"u"&&marked.parse)try{const i=this._preprocessAsciiArt(t);let n=this._sanitizeHtml(marked.parse(i,{breaks:!0,gfm:!0}));n=n.replace(/<table>/g,'<div class="rv-table-wrap"><table>').replace(/<\/table>/g,"</table></div>");const o=/[─-╿▀-▟]/,a=document.createElement("template");return a.innerHTML=n,a.content.querySelectorAll("pre > code").forEach(r=>{const l=r.parentElement,c=o.test(r.textContent||""),h=document.createElement("div");h.className=c?"rv-code-wrap rv-diagram-wrap":"rv-code-wrap";const d=document.createElement("div");d.className="rv-code-actions";const g=document.createElement("button");if(g.className="rv-copy-btn",g.type="button",g.setAttribute("aria-label","Copy code"),g.setAttribute("title","Copy code"),d.appendChild(g),c){l.classList.add("rv-diagram");const f=document.createElement("button");f.className="rv-wrap-toggle",f.type="button",f.setAttribute("aria-label","Toggle line wrapping"),f.setAttribute("title","Toggle line wrapping"),d.appendChild(f)}l.parentNode.insertBefore(h,l),h.appendChild(d),h.appendChild(l)}),a.content.querySelectorAll("a[href]").forEach(r=>{const l=r.getAttribute("href")||"";!l||l.startsWith("#")||/^(?:mailto|tel):/i.test(l)||(r.setAttribute("target","_blank"),r.setAttribute("rel","noopener noreferrer"))}),a.innerHTML}catch{}return`<pre style="white-space:pre-wrap;word-break:break-word">${t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}</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,this.activeSessionId);return}const i=t.target.closest(".rv-copy-btn");if(i){t.preventDefault(),t.stopPropagation();const l=i.closest(".rv-code-wrap")?.querySelector("pre code"),c=l?await this._copyText(l.textContent||""):!1;i.classList.remove("rv-copied","rv-copy-failed"),i.classList.add(c?"rv-copied":"rv-copy-failed"),clearTimeout(i._resetTimer),i._resetTimer=setTimeout(()=>{i.classList.remove("rv-copied","rv-copy-failed")},1500);return}const n=t.target.closest(".rv-wrap-toggle");if(!n)return;t.preventDefault(),t.stopPropagation();const o=n.closest(".rv-diagram-wrap"),a=o?.querySelector("pre.rv-diagram");if(!a||!o)return;const r=a.classList.toggle("rv-nowrap");o.classList.toggle("rv-wrap-nowrap",r)}))}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){const i=document.createElement("div"),n=t==="user";i.className="rv-message "+(n?"rv-msg-user":"rv-msg-assistant");const o=document.createElement("div");o.className="rv-role "+(n?"rv-role-user":"rv-role-assistant"),o.textContent=n?"You":s,i.appendChild(o);const a=document.createElement("div");return a.className="rv-text",a.innerHTML=this._renderMarkdown(e),this._linkifyFilePaths(a),i.appendChild(a),i}_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,l;for(t.lastIndex=0;(l=t.exec(o))!==null;){const c=l[1];l.index>r&&a.appendChild(document.createTextNode(o.slice(r,l.index)));const h=document.createElement("a");h.className="rv-path",h.href="#",h.dataset.path=c,h.title=c,h.textContent=c,a.appendChild(h),r=l.index+c.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==="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{let o=((await(await fetch(`/api/sessions/${this.activeSessionId}/last-response`)).json())?.data??{}).text||"";const a=this.sessions.get(this.activeSessionId)?.mode||"claude";if(!o&&(a==="claude"||a==="shell")){const d=(await(await fetch(`/api/sessions/${this.activeSessionId}/terminal`)).json())?.data??{};d.terminalBuffer&&(o=this._cleanTerminalBuffer(d.terminalBuffer))}const r=document.getElementById("responseViewerBody");o?(r.innerHTML="",r.appendChild(this._buildResponseViewerMessage(o,"assistant",this._getResponseViewerAgentLabel())),this._bindResponseViewerInteractions(r)):r.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"),c=document.getElementById("responseViewerMore");l&&(l.textContent="Last Response"),c&&(c.style.display="",c.textContent="More"),e.classList.add("visible"),t.classList.add("visible"),r.scrollTop=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){n.textContent="No conversation history available";return}const a=this._getResponseViewerAgentLabel();n.innerHTML="";for(const r of i)n.appendChild(this._buildResponseViewerMessage(r.text,r.role,a));this._bindResponseViewerInteractions(n),o&&(o.textContent=`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 _onSessionNeedsRefresh(){if(!this.activeSessionId||!this.terminal||this._isLoadingBuffer)return;const e=this.activeSessionId;try{let t=await fetch(`/api/sessions/${e}/terminal?full=1`),s=(await t.json())?.data??{};if(s.terminalBuffer&&this._replayWouldShrinkBuffer(s.terminalBuffer)&&(t=await fetch(`/api/sessions/${e}/terminal?tail=${TERMINAL_TAIL_SIZE}`),s=(await t.json())?.data??{}),this.activeSessionId!==e)return;if(s.terminalBuffer){const i=this.terminal.buffer?.active,n=i?Math.max(0,(i.baseY||0)-(i.viewportY||0)):0;this.terminal.clear(),this.terminal.reset(),await this.chunkedTerminalWrite(s.terminalBuffer),this._setHistoryTruncation(e,s);const o=computeRewriteScrollLine({linesFromBottom:n,baseY:this.terminal.buffer?.active?.baseY??0});o===null||typeof this.terminal.scrollToLine!="function"?this.terminal.scrollToBottom():this.terminal.scrollToLine(o),this._localEchoOverlay?.rerender(),this.activeSessionId&&this.sendResize(this.activeSessionId)}}catch(t){console.error("needsRefresh reload failed:",t)}}async _onSessionClearTerminal(e){if(e.id===this.activeSessionId){if(this._isLoadingBuffer)return;try{const s=(await(await fetch(`/api/sessions/${e.id}/terminal`)).json())?.data??{};if(this.terminal.clear(),this.terminal.reset(),s.terminalBuffer){const i=s.terminalBuffer.replace(DEC_SYNC_STRIP_RE,"");await this.chunkedTerminalWrite(i)}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=l=>l&&typeof l.usedPercentage=="number"?Math.round(l.usedPercentage):null,i=s(e.fiveHour),n=s(e.sevenDay);if(i===null&&n===null)return;const o=l=>l>=85?"pu-red":l>=60?"pu-yellow":"pu-green",a=(l,c)=>{if(c===null)return"";const h=Math.round(Number(c));return Number.isFinite(h)?`<span class="pu-win"><span class="pu-label">${l}</span><span class="pu-val ${o(h)}">${h}%</span></span>`:""};t.innerHTML=[a("5h",i),a("7d",n)].filter(Boolean).join('<span class="pu-sep">\xB7</span>');const r=l=>l&&l.resetAt?new Date(l.resetAt).toLocaleString():"\u2014";t.title=`Claude plan usage
15
- 5-hour limit: ${i??"\u2014"}% used (resets ${r(e.fiveHour)})
16
- Weekly limit: ${n??"\u2014"}% used (resets ${r(e.sevenDay)})`}_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}/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))},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)}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}`);const l=this.activeSessionId===e;if(r.action==="give-up")this._wsState=l?"fallback":"disconnected",this._updateConnectionIndicator();else if(r.action==="reconnect")if(l){this._wsState="reconnecting",this._updateConnectionIndicator();const c=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)},c)}else this._wsState="disconnected",this._updateConnectionIndicator();else this._wsState=l?"fallback":"disconnected",this._updateConnectionIndicator(),l&&(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){!e||!t||this._reliableSend(e,t,s?.useMux===!0)}_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._persistReliableState(),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 break}}finally{this._postDraining.delete(e)}})())}}_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){this._wsSessionId&&Number.isInteger(e)&&this._ackDelivery(this._wsSessionId,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))Array.isArray(i)&&i.length&&this._pendingDeliveries.set(s,i.filter(n=>n&&typeof n.data=="string"&&Number.isInteger(n.seq)).map(n=>({seq:n.seq,data:n.data,useMux:!!n.useMux,ts:n.ts||Date.now(),tries:0,sentAt:0})))}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,l,c;switch(this._wsState){case"connected":r="connected",l="WS",c="Terminal connected over WebSocket";break;case"fallback":r="fallback",l="HTTP",c="WebSocket unavailable \u2014 input sent over HTTP";break;case"reconnecting":r="reconnecting",l="WS\u2026",c="Reconnecting WebSocket";break;default:r="reconnecting",l="WS\u2026",c="Connecting WebSocket";break}return{display:"flex",dotClass:`connection-dot ${r}`,text:`${l}${a}`,title:c}}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"),l=this.$("offlineOverlayHost"),c=this.$("offlineOverlayStatus");a&&(a.textContent=i.title),r&&(r.textContent=i.detail),l&&(l.textContent=location.host),c&&(c.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(){this.sessions.clear(),this.ralphStates.clear(),this.terminalBuffers.clear(),this.terminalBufferCache.clear(),this._xtermSnapshots?.clear(),this.projectInsights.clear(),this.teams.clear(),this.teamTasks.clear();for(const e of this.idleTimers.values())clearTimeout(e);if(this.idleTimers.clear(),this._clearTimer("flickerFilterTimeout"),this.flickerFilterBuffer="",this.flickerFilterActive=!1,this._clearTimer("syncWaitTimeout"),this.pendingWrites=[],this.writeFrameScheduled=!1,this._isLoadingBuffer=!1,this._loadBufferQueue=null,this._bufferLoadOwner=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:e}of this.notificationManager.groupingMap.values())clearTimeout(e);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),e.version){const n=this.$("versionDisplay"),o=this.$("headerVersion");n&&(n.textContent=`v${e.version}`,n.title=`Codeman v${e.version}`),o&&(o.textContent=`v${e.version}`,o.title=`Codeman v${e.version}`)}VoiceInput.cleanup(),this._resetAllAppState(),e.sessions.forEach(n=>{this.sessions.set(n.id,n),(n.ralphLoop||n.ralphTodos)&&!this.ralphClosedSessions.has(n.id)&&this.ralphStates.set(n.id,{loop:n.ralphLoop||null,todos:n.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(),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((n,o)=>n+(o.totalCost||0),0),this.totalCost+=e.scheduledRuns.reduce((n,o)=>n+(o.totalCost||0),0);const s=e.scheduledRuns.find(n=>n.status==="running");if(s&&(this.currentRun=s,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(n=>{this.subagents.set(n.agentId,n)}),this.renderSubagentPanel(),this.subagentParentMap.clear(),this.loadSubagentParentMap().then(()=>{for(const[n,o]of this.subagentParentMap){const a=this.subagents.get(n);if(a&&this.sessions.has(o)){a.parentSessionId=o;const r=this.sessions.get(o);r&&(a.parentSessionName=this.getSessionName(r)),this.subagents.set(n,a)}}for(const[n]of this.subagents)this.subagentParentMap.has(n)||this.findParentSessionForSubagent(n);this.restoreSubagentWindowStates()})),e.workflowRuns&&this.seedWorkflowRuns(e.workflowRuns),t!==this._initGeneration)return;if(this.isSoloWindow){this._applySoloMode();return}const i=this.activeSessionId;if(this.activeSessionId=null,this.sessionOrder.length>0){let n=i;if(!n||!this.sessions.has(n))try{n=localStorage.getItem("codeman-active-session")}catch{}n&&this.sessions.has(n)?this.selectSession(n,{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()}_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"),l=document.getElementById("sessionSidebarList");if(!a||!r||!l)return;const c=document.getElementById("tabRail"),h=!t&&document.documentElement.getAttribute("data-tab-orientation")==="vertical",d=t?l:h&&c?c:r;a.parentElement!==d&&d.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",d===r?"horizontal":"vertical");const g=document.getElementById("sidebarToggleBtn");if(g){g.classList.toggle("btn-sidebar-toggle--hidden",!t);const _=s?"Expand session sidebar":"Collapse session sidebar";g.setAttribute("aria-expanded",s?"false":"true"),g.setAttribute("aria-label",_),g.setAttribute("title",_)}const f=document.getElementById("sessionSidebar");if(f){f.classList.toggle("open",t&&!s);const _=t&&s&&this._isSessionSidebarOverlay();f.toggleAttribute("inert",_),_?f.setAttribute("aria-hidden","true"):f.removeAttribute("aria-hidden")}if(!t){this._sidebarFilter="";const _=document.getElementById("sessionSidebarFilter");_&&(_.value="")}const m=this._tallTabsEnabled;this.applyTabWrapSettings();const y=i!==document.documentElement.dataset.sessionList||n!==document.documentElement.dataset.sidebarDetail,w=o!==document.documentElement.dataset.sidebar;(y||w)&&m===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));return{state:s,pill:this._sidebarRichPillLabel(s),createdAt:Number(t.createdAt)||0,since:this._mobileOverviewSince?this._mobileOverviewSince(s,t):null}}_sidebarRichMetaHTML(e){if(!e)return"";const t=(o,a,r,l)=>{const c=this._sidebarRichStampText(a,r),h=a?` title="${escapeHtml(`${o==="created"?"First created":o}: ${new Date(a).toLocaleString()}`)}"`:"";return`<span class="tab-meta-item ${l}"${h}><span class="tab-meta-key">${escapeHtml(o)}</span><span data-tab-ts="${a||0}" data-tab-fmt="${r}">${escapeHtml(c)}</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"))),s.push(`<span class="tab-pill tab-pill--${escapeHtml(e.state)}">${escapeHtml(e.pill)}</span>`);const i=[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"${i?` title="${escapeHtml(i)}"`:""} 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.since?i.since.at:0}:${i.createdAt}`;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),l=a.querySelector(".tab-meta");l?l.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;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._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 l=window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches;typeof s.scrollTo=="function"?s.scrollTo({left:r,behavior:l?"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=new Set(this.sessions.keys()),n=[...e.querySelectorAll(".session-tab[data-webview-id]")].map(l=>l.dataset.webviewId),o=(this.webviewOrder||[]).filter(l=>this.webviews?.has(l)),a=n.length===o.length&&n.every((l,c)=>l===o[c]);if(s.size===i.size&&[...s].every(l=>i.has(l))&&a){const l=this.isRichTabRows();for(const[c,h]of this.sessions){const d=e.querySelector(`.session-tab[data-id="${c}"]`);if(!d)continue;const g=c===this.activeSessionId&&!this.activeWebviewId,f=h.status||"idle",m=this.getSessionName(h),y=h.taskStats||{running:0,total:0},w=y.running>0,_=this.terminalLoadStates.get(c);if(g&&!d.classList.contains("active")?d.classList.add("active"):!g&&d.classList.contains("active")&&d.classList.remove("active"),d.classList.toggle("tab-loading",!!_),_){if(d.setAttribute("aria-busy","true"),d.dataset.loadPhase=_.phase,!d.querySelector(".tab-load-spinner")){const u=document.createElement("span");u.className="tab-load-spinner",u.setAttribute("aria-hidden","true");const p=d.querySelector(".tab-number");p?p.insertAdjacentElement("afterend",u):d.insertBefore(u,d.firstChild)}}else d.setAttribute("aria-busy","false"),delete d.dataset.loadPhase,d.querySelector(".tab-load-spinner")?.remove();const A=this.tabAlerts.get(c),D=A==="action",L=A==="idle",I=d.classList.contains("tab-alert-action"),x=d.classList.contains("tab-alert-idle");if(D&&!I?(d.classList.add("tab-alert-action"),d.classList.remove("tab-alert-idle")):L&&!x?(d.classList.add("tab-alert-idle"),d.classList.remove("tab-alert-action")):!A&&(I||x)&&d.classList.remove("tab-alert-action","tab-alert-idle"),!d.querySelector(".tab-number")){const u=this.sessionOrder.indexOf(c);if(u>=0&&u<9){const p=document.createElement("span");p.className="tab-number",p.textContent=String(u+1),d.insertBefore(p,d.firstChild)}}const E=d.querySelector(".tab-status");E&&!E.classList.contains(f)&&(E.className=`tab-status ${f}`),l?this._updateSidebarRichRow(d,c,h):d.dataset.tabState&&(d.querySelector(".tab-meta")?.remove(),d.classList.remove(`tab-state-${d.dataset.tabState}`),delete d.dataset.tabState,delete d.dataset.tabMetaSig);const C=d.querySelector(".tab-name");if(C){const u=parseSessionPrefix(m);if(C.dataset.fullName!==m){if(C.replaceChildren(),u&&u.suffix){const p=document.createElement("span");p.className="tab-name-prefix",p.textContent=`${u.prefix}: `,C.append(p,document.createTextNode(u.suffix))}else C.textContent=m;C.dataset.fullName=m,d.title=u&&u.suffix?h.workingDir?`${u.prefix} (${h.workingDir})`:u.prefix:h.workingDir||""}}const R=d.querySelector(".tab-badge");if(w)if(R)R.textContent!==String(y.running)&&(R.textContent=y.running);else{this._fullRenderSessionTabs();return}else if(R){this._fullRenderSessionTabs();return}const O=d.querySelector(".tab-subagent-badge"),M=this.minimizedSubagents.get(c),b=M?.size||0;if(b>0&&O){const u=O.querySelector(".subagent-label"),p=b===1?"AGENT":`AGENTS (${b})`;u&&u.textContent!==p&&(u.textContent=p);const T=O.querySelector(".subagent-dropdown");if(T){const v=this.renderSubagentTabBadge(c,M),k=document.createElement("div");k.innerHTML=v;const N=k.querySelector(".subagent-dropdown");N&&(T.innerHTML=N.innerHTML)}}else if(b>0&&!O){const u=this.renderSubagentTabBadge(c,M),p=d.querySelector(":scope > .tab-actions");p?p.insertAdjacentHTML("beforebegin",u):d.insertAdjacentHTML("beforeend",u)}else b===0&&O&&O.remove()}}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;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(c=>c.remove()),this.cancelHideSubagentDropdown();const t=e.scrollLeft,s=e.scrollTop,i=this._lastRenderedActiveTabId,n=!e.querySelector(".session-tab"),o=[],a=this.sessionOrder,r=this.isRichTabRows();let l=0;for(const c of a){const h=this.sessions.get(c);if(!h)continue;const d=c===this.activeSessionId&&!this.activeWebviewId,g=h.status||"idle",f=this.getSessionName(h),m=h.mode||"claude",y=h.color||"default",w=h.taskStats||{running:0,total:0},_=w.running>0,A=this.tabAlerts.get(c),D=A==="action"?" tab-alert-action":A==="idle"?" tab-alert-idle":"",L=this.terminalLoadStates.get(c),I=this.minimizedSubagents.get(c),E=(I?.size||0)>0?this.renderSubagentTabBadge(c,I):"",C=this.renderUltracodeTabBadge?this.renderUltracodeTabBadge(c):"",R=h.workingDir&&h.workingDir.split("/").pop()||"",M=(this._tallTabsEnabled??!1)&&h.name&&R&&R!==f,b=parseSessionPrefix(f),u=b&&b.suffix?`<span class="tab-name-prefix">${escapeHtml(b.prefix)}: </span>${escapeHtml(b.suffix)}`:escapeHtml(f),p=b&&b.suffix?h.workingDir?`${b.prefix} (${h.workingDir})`:b.prefix:h.workingDir||"",T=r?this._sidebarRichRow(c,h):null,v=this._sidebarRichMetaHTML(T),k=T?` tab-state-${T.state}`:"",N=T?` data-tab-state="${T.state}" data-tab-meta-sig="${T.state}:${T.since?T.since.at:0}:${T.createdAt}"`:"",P=this.shouldInlineSessionActions(),B=`<span class="tab-actions"><span class="tab-gear" onclick="event.stopPropagation(); app.openSessionOptions(${escapeHtml(JSON.stringify(c))})" title="Session options" aria-label="Session options" tabindex="0">&#x2699;</span><span class="tab-detach" onclick="event.stopPropagation(); app.detachSession(${escapeHtml(JSON.stringify(c))})" title="Open in a new window" aria-label="Open session in a new window" tabindex="0">&#x29C9;</span><span class="tab-close" onclick="event.stopPropagation(); app.requestCloseSession(${escapeHtml(JSON.stringify(c))})" title="Close session" aria-label="Close session" tabindex="0">&times;</span><button type="button" class="tab-more" onclick="event.stopPropagation(); app.openTabRailActionMenu(event, ${escapeHtml(JSON.stringify(c))})" title="Session actions" aria-label="Session actions">&#x22EF;</button></span>`;o.push(`<div class="session-tab ${d?"active":""}${D}${k}${L?" tab-loading":""}${this.hasTabDetachOverride(c)?" tab-show-detach":""}"${N} data-id="${c}" data-color="${y}" ${L?`data-load-phase="${escapeHtml(L.phase)}"`:""} onclick="app.handleSessionTabClick(event, ${escapeHtml(JSON.stringify(c))})" oncontextmenu="event.preventDefault(); app.startInlineRename(${escapeHtml(JSON.stringify(c))})" tabindex="0" role="tab" aria-selected="${d?"true":"false"}" aria-busy="${L?"true":"false"}" aria-label="${escapeHtml(f)} session" ${p?`title="${escapeHtml(p)}"`:""}>
17
- ${l<9?'<span class="tab-number">'+(l+1)+"</span>":""}
18
- ${L?'<span class="tab-load-spinner" aria-hidden="true"></span>':""}
19
- <span class="tab-status ${g}" aria-hidden="true"></span>
20
- <span class="tab-info">
21
- <span class="tab-name-row">
22
- ${m==="shell"?'<span class="tab-mode shell" aria-hidden="true">sh</span>':m==="opencode"?'<span class="tab-mode opencode" aria-hidden="true">oc</span>':m==="codex"?'<span class="tab-mode codex" aria-hidden="true">cx</span>':m==="gemini"?'<span class="tab-mode gemini" aria-hidden="true">gm</span>':m==="antigravity"?'<span class="tab-mode antigravity" aria-hidden="true">ag</span>':m==="pi"?'<span class="tab-mode pi" aria-hidden="true">pi</span>':m==="grok"?'<span class="tab-mode grok" aria-hidden="true">gk</span>':m==="deepseek"?'<span class="tab-mode deepseek" aria-hidden="true">ds</span>':""}
23
- <span class="tab-name" data-session-id="${c}" data-full-name="${escapeHtml(f)}">${u}</span>
24
- ${P?B:""}
25
- <span class="tab-detached-badge" aria-hidden="true">detached</span>
26
- </span>
27
- ${M?`<span class="tab-folder">\u{1F4C1} ${escapeHtml(R)}</span>`:""}
28
- ${v}
29
- </span>
30
- ${_?`<span class="tab-badge" onclick="event.stopPropagation(); app.toggleTaskPanel()" aria-label="${w.running} running tasks">${w.running}</span>`:""}
31
- ${E}
32
- ${C}
33
- ${P?"":B}
34
- </div>`),l++}o.push(this.renderWebviewTabs?this.renderWebviewTabs(l):""),e.innerHTML=o.join(""),e.scrollLeft=t,e.scrollTop=s,this._lastRenderedActiveTabId=this.activeSessionId,(n||i!==this.activeSessionId)&&this._scrollActiveTabIntoView(this.activeSessionId,n?"auto":"smooth"),this.setupTabDragHandlers(),this.setupTabKeyboardNavigation(e),this.updateConnectionLines(),this.updateTabOverflowMode(),this._applyTabEntrances?.(),this.applySidebarFilter(this._sidebarFilter),r?this._startSidebarRichClock():this._stopSidebarRichClock()}setupTabKeyboardNavigation(e){this._tabKeydownHandler&&e.removeEventListener("keydown",this._tabKeydownHandler),this._tabKeydownHandler=t=>{if(!["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Home","End","Enter"," "].includes(t.key))return;const s=[...e.querySelectorAll(".session-tab:not(.tab-filtered-out)")],i=s.indexOf(document.activeElement);if((t.key==="Enter"||t.key===" ")&&i>=0){t.preventDefault();const o=s[i].dataset.id;this.selectSession(o,{forceReload:!0});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)}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()}setupTabDragHandlers(){const e=this.$("sessionTabs");e.querySelectorAll(".session-tab[data-id]").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,l=this.sessionOrder.indexOf(o);let c=this.sessionOrder.indexOf(n);l===-1||c===-1||(this.sessionOrder.splice(l,1),c=this.sessionOrder.indexOf(n),c!==-1&&(r?this.sessionOrder.splice(c,0,o):this.sessionOrder.splice(c+1,0,o),this.saveSessionOrder(),this._fullRenderSessionTabs()))})})}moveActiveTabLeft(){if(!this.activeSessionId)return;const e=this.sessionOrder.indexOf(this.activeSessionId);e<=0||([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.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,l)=>Number(o.has(r.slice(s.length)))-Number(o.has(l.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._clearTimer("syncWaitTimeout"),this.pendingWrites=[],this.writeFrameScheduled=!1,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{}if(this.activeSessionId){const s=this._localEchoOverlay?.pendingText||"",i=this._localEchoOverlay?.getFlushed()?.count||0,n=this._localEchoOverlay?.getFlushed()?.text||"";s&&this._sendInputAsync(this.activeSessionId,s);const o=i+s.length;o>0&&(this._flushedOffsets||(this._flushedOffsets=new Map),this._flushedTexts||(this._flushedTexts=new Map),this._flushedOffsets.set(this.activeSessionId,o),this._flushedTexts.set(this.activeSessionId,n+s))}this._localEchoOverlay?.clear(),this._predictiveEcho?.clearPredictions(),this._localEchoOverlay&&!this._flushedOffsets?.has(e)&&this._localEchoOverlay.suppressBufferDetection()}_resetTerminalForReplay(){this.terminal.reset(),this.terminal.write("\x1B[3J\x1B[H\x1B[2J")}_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);if(!e&&s?.mode==="shell")return;const i=Date.now(),n=this._fullHistoryRepullUseless?.has(t)?6e4:4e3;if(!(!e&&i-(this._fullHistoryRepullAt.get(t)||0)<n)){this._fullHistoryRepullAt.set(t,i),this._fullHistoryRepullInFlight=!0;try{const o=performance.now(),a=await fetch(`/api/sessions/${t}/terminal?full=1`),r=performance.now(),l=(await a.json())?.data??{},c=performance.now(),h=l.terminalBuffer,d={trigger:e?"full-history-button":"full-history-scroll",mode:s?.mode||"unknown",full:!0,source:l.source||"unknown",chars:h?.length||0,ttfbMs:r-o,bodyAndJsonMs:c-r,resetAndParseMs:0,totalMs:0,serverTiming:a.headers?.get?.("server-timing")||"",refused:!1};if(!h||this.activeSessionId!==t)return;if(this._replayWouldShrinkBuffer(h)){d.refused=!0,d.totalMs=performance.now()-o,this._recordTerminalLoadTiming(d),(this._fullHistoryRepullUseless||=new Set).add(t),this._logScrollRouting?.("repull-refused-downgrade"),this._setHistoryTruncation(t,{...l,exhausted:!0});return}this._setHistoryTruncation(t,l),this._fullHistoryRepullUseless?.delete(t);const g=this.terminal.buffer.active.length,f=performance.now();this._resetTerminalForReplay();const{parsedAt:m,bufferLength:y,completed:w}=await this.chunkedTerminalWrite(h,TERMINAL_CHUNK_SIZE,t);if(d.resetAndParseMs=m-f,!w||this.activeSessionId!==t)return;this.sessions.get(t)?.mode!=="shell"?this.terminalBufferCache.set(t,h):this.terminalBufferCache.delete(t);const _=y-g;_>0?this.terminal.scrollToLine(_):this.terminal.scrollToTop(),d.totalMs=performance.now()-o,this._recordTerminalLoadTiming(d)}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(!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._isLoadingBuffer=!1,this._loadBufferQueue=null,this._chunkedWriteGen=(this._chunkedWriteGen||0)+1,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._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._flushedOffsets?.has(e)&&this._localEchoOverlay&&this._localEchoOverlay.setFlushed(this._flushedOffsets.get(e),this._flushedTexts?.get(e)||"",!1);const l=document.querySelector(`.session-tab.active[data-id="${e}"]`);l&&(l.classList.add("tab-glow"),l.addEventListener("animationend",()=>l.classList.remove("tab-glow"),{once:!0}));const c=this.sessions.get(e);if(this.currentSessionWorkingDir=c?.workingDir||null,c&&c.pid===null)if(c.respawnBlocked){const f=c.name||"Session";if(window.confirm(`${f} 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})}),c.respawnBlocked=!1,c.status="busy"}catch(m){console.error("Failed to restart crash-looped session:",m)}}else try{const f=c.mode==="shell"?`/api/sessions/${e}/shell`:`/api/sessions/${e}/interactive`;await fetch(f,{method:"POST"}),c.status="busy"}catch(f){console.error("Failed to attach to restored session:",f)}this._restoringFlushedState=!0;const h=this._beginBufferLoad(r);let d=!1,g=0;try{this.fitAddon&&this.fitAddon.fit();const f=await this.sendResize(e,{forceHttp:!0}).catch(()=>!1);if(this._isStaleSelect(r)){this._clearTerminalLoadState(e,r);return}let m=this._xtermSnapshots?.get(e);if(m&&!this._isUsableXtermSnapshot(m)&&(this._xtermSnapshots?.delete(e),m=null),!m)try{const u=localStorage.getItem(`codeman-xs-${e}`);u&&this._isUsableXtermSnapshot(u)?(m=u,this._xtermSnapshots?.delete(e),this._xtermSnapshots?.set(e,u)):u&&localStorage.removeItem(`codeman-xs-${e}`)}catch{}const y=c&&(c.status==="busy"||c.status==="working");let w=!1;if(m&&!y&&c?.mode!=="shell"){if(_crashDiag.log(`SNAPSHOT_RESTORE: ${(m.length/1024).toFixed(0)}KB`),this._setTerminalLoadState(e,r,"replaying"),this._resetTerminalForReplay(),await new Promise(u=>this.terminal.write(m,u)),this._isStaleSelect(r)){this._clearTerminalLoadState(e,r);return}this.scrollToLastNonEmptyLine(),_crashDiag.log("SNAPSHOT_RESTORE_DONE"),w=!0}const _=this.terminalBufferCache.get(e);let A=!1;if(_&&!y&&!w&&c?.mode!=="shell"){_crashDiag.log(`CACHE_WRITE: ${(_.length/1024).toFixed(0)}KB`),this._setTerminalLoadState(e,r,"replaying");const u=performance.now();this._resetTerminalForReplay();const{parsedAt:p}=await this.chunkedTerminalWrite(_,TERMINAL_CHUNK_SIZE,h);if(g=p-u,this._isStaleSelect(r)){this._clearTerminalLoadState(e,r);return}this.terminal.scrollToBottom(),_crashDiag.log("CACHE_DONE")}else(y||c?.mode==="shell")&&(this._resetTerminalForReplay(),A=!0,_crashDiag.log(c?.mode==="shell"?"CACHE_SKIP_SHELL":"CACHE_SKIP_BUSY"));if(c?.mode!=="shell"&&f&&(await new Promise(u=>setTimeout(u,TUI_REDRAW_SETTLE_MS)),this._isStaleSelect(r))){this._clearTerminalLoadState(e,r);return}this._setTerminalLoadState(e,r,"fetching"),_crashDiag.log("FETCH_START");const D=c?.mode!=="shell"&&!this._fullHistoryLoaded.has(e);D&&this._fullHistoryLoaded.add(e);const L=performance.now(),I=await fetch(D?`/api/sessions/${e}/terminal?full=1`:`/api/sessions/${e}/terminal?tail=${TERMINAL_TAIL_SIZE}`),x=performance.now();if(this._isStaleSelect(r)){this._clearTerminalLoadState(e,r);return}const E=(await I.json())?.data??{},C=performance.now();_crashDiag.log(`FETCH_DONE: ${E.terminalBuffer?(E.terminalBuffer.length/1024).toFixed(0)+"KB":"empty"} truncated=${E.truncated}`);let R=0;if(E.terminalBuffer){if(w||A||E.terminalBuffer!==_){_crashDiag.log(`REWRITE: ${(E.terminalBuffer.length/1024).toFixed(0)}KB`),this._setTerminalLoadState(e,r,"replaying");const p=performance.now();this._resetTerminalForReplay(),this._setHistoryTruncation(e,E);const{parsedAt:T}=await this.chunkedTerminalWrite(E.terminalBuffer,TERMINAL_CHUNK_SIZE,h);if(R=T-p,this._isStaleSelect(r)){this._clearTerminalLoadState(e,r);return}this.terminal.scrollToBottom()}if(c?.mode==="shell")this.terminalBufferCache.delete(e);else if(this.terminalBufferCache.set(e,E.terminalBuffer),this.terminalBufferCache.size>20){const p=this.terminalBufferCache.keys().next().value;this.terminalBufferCache.delete(p)}}else(!_||A)&&(A||this._resetTerminalForReplay(),d=!0);const O={trigger:"session-select",mode:c?.mode||"unknown",full:D,source:E.source||"unknown",chars:E.terminalBuffer?.length||0,ttfbMs:x-L,bodyAndJsonMs:C-x,cacheResetAndParseMs:g,freshResetAndParseMs:R,selectToReplayCompleteMs:performance.now()-o,serverTiming:I.headers?.get?.("server-timing")||""};if(this._isLoadingBuffer&&this._finishBufferLoad(h,{flushQueued:d}),this._restoringFlushedState=!1,this._flushedOffsets?.has(e)&&this._localEchoOverlay){this._localEchoOverlay.setFlushed(this._flushedOffsets.get(e),this._flushedTexts?.get(e)||"",!1);const u=this._localEchoOverlay;this.terminal.write("",()=>{u.hasPending&&u.rerender()})}this.sendResize(e),(typeof requestIdleCallback=="function"?requestIdleCallback:u=>setTimeout(u,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 u=document.getElementById("taskPanel");u&&u.classList.contains("open")&&this.renderTaskPanel();const p=this.sessions.get(e);if(p&&(p.ralphLoop||p.ralphTodos)&&this.updateRalphState(e,{loop:p.ralphLoop,todos:p.ralphTodos}),this.renderRalphStatePanel(),this.updateCliInfoDisplay(),this.renderProjectInsightsPanel(),this.updateSubagentWindowVisibility(),this.loadAppSettingsFromStorage().showFileBrowser){const v=this.$("fileBrowserPanel");if(v&&(v.classList.add("visible"),this.loadFileBrowser(e),!this.fileBrowserDragListeners)){const k=v.querySelector(".file-browser-header");if(k){const N=()=>{if(!v.style.left){const P=v.getBoundingClientRect();v.style.left=`${P.left}px`,v.style.top=`${P.top}px`,v.style.right="auto"}};k.addEventListener("mousedown",N),k.addEventListener("touchstart",N,{passive:!0}),this.fileBrowserDragListeners=this.makeWindowDraggable(v,k),this.fileBrowserDragListeners._onFirstDrag=N}}}}),this._connectWs(e),_crashDiag.log("FOCUS"),n&&this.terminal&&this.terminal.focus(),this.scrollToLastNonEmptyLine(),typeof KeyboardHandler<"u"&&KeyboardHandler.keyboardVisible&&KeyboardHandler.onKeyboardShow();const b=performance.now()-o;O.selectDoneMs=b,this._recordTerminalLoadTiming(O),this._clearTerminalLoadState(e,r),_crashDiag.log(`SELECT_DONE: ${b.toFixed(0)}ms`),console.log(`[CRASH-DIAG] selectSession DONE: ${e.slice(0,8)} in ${b.toFixed(0)}ms`)}catch(f){this._isLoadingBuffer&&this._finishBufferLoad(h),this._restoringFlushedState=!1,this._setTerminalLoadState(e,r,"failed"),console.error("Failed to load session terminal:",f)}}_cleanupSessionData(e){this.closeTabRailActionMenu?.(),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),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":"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.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?`
35
- Estimated cost based on Claude Opus pricing`:""}`:`Token usage across active sessions${r?`
36
- 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
@@ -1,2 +0,0 @@
1
- "use strict";(function(e){const t=/^\x1b\[[\?>=]?[\d;]*[cnR]$/,i=/^\x1b\][\d;]*[^\x07\x1b]*(?:\x07|\x1b\\)$/,s=/^\x1b\[<\d+;\d+;\d+[Mm]$/,n=/^\x1b\[M[\s\S]{3}$/,o=/^\x1b\[[IO]$/,u=["input","textarea","select","button","a[href]",'[contenteditable=""]','[contenteditable="true"]','[tabindex]:not([tabindex="-1"])',".keyboard-accessory-bar",".path-picker-overlay"].join(","),y=/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b\[[0-9;?<>=!]*[ -/]*[@-~]|\x1b[()#][0-9A-Za-z]|\x1b[=>78M]/g,I="\x1B[5~",v="\x1B[6~",_=.5,l=3,p=4,m=/^\x1b(?:\[(?:[ABCDHF]|1;[2-8][ABCDHF]|[1-8](?:;[2-8])?~)|O[ABCDHF])$/,S="\x1B[200~";function g(E){return m.test(E)}const f=/^› /;function w(E){const C=Array.from(E);if(C.length===1){const x=C[0].codePointAt(0);return x===127?"backspace":x>=32?"char":"clear"}return E.charCodeAt(0)===27?"clear":E.charCodeAt(0)>=32?"text":"clear"}function T(E){try{const C=E.buffer.active,x=C.getLine(C.baseY+C.cursorY);return!!x&&f.test(x.translateToString(!0))}catch{return!1}}function L(E){return t.test(E)||i.test(E)}function M(E){return L(E)}function A(E){return o.test(E)||s.test(E)||n.test(E)}const R={og:{background:"#0d0d0d",foreground:"#e0e0e0",cursor:"#e0e0e0",cursorAccent:"#0d0d0d",selection:"rgba(255,255,255,0.3)",black:"#0d0d0d",red:"#ff6b6b",green:"#51cf66",yellow:"#ffd43b",blue:"#339af0",magenta:"#cc5de8",cyan:"#22b8cf",white:"#e0e0e0",brightBlack:"#495057",brightRed:"#ff8787",brightGreen:"#69db7c",brightYellow:"#ffe066",brightBlue:"#5c7cfa",brightMagenta:"#da77f2",brightCyan:"#66d9e8",brightWhite:"#ffffff"},"daylight-green":{background:"#161b23",foreground:"#dfe6ef",cursor:"#2fd3aa",cursorAccent:"#161b23",selection:"rgba(47,211,170,0.22)",black:"#161b23",red:"#ff8585",green:"#34d8a0",yellow:"#f0c25a",blue:"#5cc6e8",magenta:"#c79af2",cyan:"#2bcbbb",white:"#dfe6ef",brightBlack:"#5b6675",brightRed:"#ffa0a0",brightGreen:"#5fe6b8",brightYellow:"#ffd884",brightBlue:"#82d4ee",brightMagenta:"#d6b3f7",brightCyan:"#5ee0d4",brightWhite:"#f3f6fa"},"daylight-blue":{background:"#161b23",foreground:"#dfe6ef",cursor:"#38b6f0",cursorAccent:"#161b23",selection:"rgba(56,182,240,0.22)",black:"#161b23",red:"#ff8585",green:"#34d8a0",yellow:"#f0c25a",blue:"#5cc6e8",magenta:"#c79af2",cyan:"#2bcbbb",white:"#dfe6ef",brightBlack:"#5b6675",brightRed:"#ffa0a0",brightGreen:"#5fe6b8",brightYellow:"#ffd884",brightBlue:"#82d4ee",brightMagenta:"#d6b3f7",brightCyan:"#5ee0d4",brightWhite:"#f3f6fa"},"paper-gray":{background:"#f6f8fa",foreground:"#1f2328",cursor:"#0969da",cursorAccent:"#ffffff",selection:"rgba(9,105,218,0.2)",black:"#24292f",red:"#cf222e",green:"#1a7f37",yellow:"#9a6700",blue:"#0969da",magenta:"#8250df",cyan:"#1b7c83",white:"#59636e",brightBlack:"#6e7781",brightRed:"#a40e26",brightGreen:"#116329",brightYellow:"#7d4e00",brightBlue:"#0550ae",brightMagenta:"#6639ba",brightCyan:"#116b75",brightWhite:"#1f2328"},"solarized-light":{background:"#fdf6e3",foreground:"#586e75",cursor:"#147ba3",cursorAccent:"#fdf6e3",selection:"rgba(38,139,210,0.2)",black:"#eee8d5",red:"#dc322f",green:"#758600",yellow:"#9b7800",blue:"#147ba3",magenta:"#d33682",cyan:"#2a9189",white:"#073642",brightBlack:"#93a1a1",brightRed:"#cb4b16",brightGreen:"#657b83",brightYellow:"#586e75",brightBlue:"#268bd2",brightMagenta:"#6c71c4",brightCyan:"#2aa198",brightWhite:"#002b36"},"catppuccin-latte":{background:"#eff1f5",foreground:"#4c4f69",cursor:"#1e66f5",cursorAccent:"#ffffff",selection:"rgba(30,102,245,0.18)",black:"#5c5f77",red:"#d20f39",green:"#3b8f2b",yellow:"#a86605",blue:"#1e66f5",magenta:"#8839ef",cyan:"#177f86",white:"#6c6f85",brightBlack:"#7c7f93",brightRed:"#b50930",brightGreen:"#2f7622",brightYellow:"#8b5604",brightBlue:"#174fbf",brightMagenta:"#6f2bc5",brightCyan:"#116b71",brightWhite:"#4c4f69"},"rose-pine-dawn":{background:"#faf4ed",foreground:"#575279",cursor:"#286983",cursorAccent:"#fffaf3",selection:"rgba(40,105,131,0.2)",black:"#575279",red:"#b4637a",green:"#286983",yellow:"#96681f",blue:"#477f91",magenta:"#907aa9",cyan:"#3f7f8b",white:"#6e6a86",brightBlack:"#797593",brightRed:"#984d66",brightGreen:"#1f5266",brightYellow:"#7d5417",brightBlue:"#386b7c",brightMagenta:"#765f90",brightCyan:"#326b76",brightWhite:"#575279"}},P=new Set(["paper-gray","solarized-light","catppuccin-latte","rose-pine-dawn"]);function F(){return typeof document<"u"&&document.documentElement.dataset.skin||"daylight-blue"}function k(){const E=F();return R[E]||R["daylight-blue"]}function b(E=F()){return P.has(E)}e.CodemanTerminalInput={isTerminalQueryResponse:L,shouldSuppressTerminalQueryResponse:M,isTerminalFocusOrMouseReport:A,isComposerNavKey:g,classifyPredictInput:w,isCodexComposerRow:T,CODEX_COMPOSER_ROW_RE:f,BRACKETED_PASTE_START:S,USER_SCROLL_STICKY_SUPPRESS_MS:1500,TOUCH_COMPAT_MOUSE_SUPPRESS_MS:450,REPLAY_ESCAPE_RE:y,KEY_PAGE_UP:I,KEY_PAGE_DOWN:v,PAGE_KEY_SCREEN_FRACTION:_,PAGE_KEY_MAX_PER_BATCH:l,TUI_PROMPT_DEFAULT_ROWS_FROM_BOTTOM:p,MOBILE_KEYBOARD_DISMISS_EXEMPT_SELECTOR:u,MOBILE_KEYBOARD_DISMISS_TAP_SLOP:8,TOUCH_SELECT_LONG_PRESS_MS:350,TOUCH_SELECT_FOCUS_GUARD_MS:800},e.CODEMAN_XTERM_THEMES=R,e.codemanCurrentXtermTheme=k,e.codemanCurrentSkinIsLight=b})(window),Object.assign(CodemanApp.prototype,{initTerminal(){const e=parseInt(localStorage.getItem("codeman-scrollback")),t=Number.isFinite(e)&&e>0?Math.max(e,DEFAULT_SCROLLBACK):DEFAULT_SCROLLBACK;if(this.terminal=new Terminal({theme:{...window.codemanCurrentXtermTheme()},fontFamily:window.CodemanTerminalFont.resolve(this.loadAppSettingsFromStorage?.().terminalFontFamily),fontSize:MobileDetection.getDeviceType()==="mobile"?10:14,lineHeight:1.2,cursorBlink:!1,cursorStyle:"block",minimumContrastRatio:window.codemanCurrentSkinIsLight()?4.5:1,scrollback:t,allowTransparency:!0,allowProposedApi:!0}),this.fitAddon=new FitAddon.FitAddon,this.terminal.loadAddon(this.fitAddon),this._xtermSnapshots=new Map,typeof SerializeAddon<"u")try{this._serializeAddon=new SerializeAddon.SerializeAddon,this.terminal.loadAddon(this._serializeAddon)}catch{this._serializeAddon=null}if(typeof Unicode11Addon<"u")try{const l=new Unicode11Addon.Unicode11Addon;this.terminal.loadAddon(l),this.terminal.unicode.activeVersion="11"}catch{}const i=document.getElementById("terminalContainer");this.terminal.open(i),this._installMobileTapMouseGuard(),this._installTouchSelectionFocusGuard(),this.terminal.attachCustomKeyEventHandler(l=>{if(l.isComposing||l.key==="Process"||l.keyCode===229)return!0;if(l.altKey&&!l.ctrlKey&&!l.shiftKey&&/^(Digit[1-9]|BracketLeft|BracketRight|KeyK)$/.test(l.code||"")||l.type==="keydown"&&this.shouldOpenCommandPaletteFromShortcut?.(l))return!1;if(this.shouldCopyTerminalSelectionFromShortcut?.(l)){const p=this.terminal.hasSelection?.()?this.terminal.getSelection():"";return p?(l.preventDefault(),this.copyTerminalSelection(p),!1):l.shiftKey?(l.preventDefault(),!1):!0}if(l.type==="keydown"&&this.shouldToggleSessionSidebarFromShortcut?.(l))return!1;if((l.ctrlKey||l.metaKey)&&l.key==="v"&&l.type==="keydown")return this.activeSessionId&&this._handleImagePaste&&this._handleImagePaste(),!1;if(l.key==="Enter"&&(l.shiftKey||l.ctrlKey)&&l.type==="keydown"){if(this.activeSessionId)if(this._localEchoEnabled){const p=this._localEchoOverlay?.pendingText||"";this._localEchoOverlay?.clear(),this._localEchoOverlay?.suppressBufferDetection(),this._flushedOffsets?.delete(this.activeSessionId),this._flushedTexts?.delete(this.activeSessionId),p&&(this._pendingInput+=p,_()),setTimeout(()=>{fetch(`/api/sessions/${this.activeSessionId}/send-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:l.ctrlKey?"C-Enter":"S-Enter"})})},p?80:0)}else fetch(`/api/sessions/${this.activeSessionId}/send-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:l.ctrlKey?"C-Enter":"S-Enter"})});return!1}return!0}),this._webglAddon=null;const s=new URLSearchParams(location.search),n=(()=>{try{const l=localStorage.getItem("codeman-webgl-disabled");if(!l)return!1;const{at:p}=JSON.parse(l);return Date.now()-p>WEBGL_FALLBACK.STICKY_EXPIRY_MS?(localStorage.removeItem("codeman-webgl-disabled"),!1):!0}catch{return!1}})(),o=this.loadAppSettingsFromStorage(),r=this.getDefaultSettings(),a=o.webglRendererEnabled??r.webglRendererEnabled,{skip:h,clearSticky:d}=shouldSkipWebGL({deviceType:MobileDetection.getDeviceType(),noWebglParam:s.has("nowebgl"),forceParam:s.get("webgl")==="force",stickyDisabled:n,userPrefEnabled:a});if(d)try{localStorage.removeItem("codeman-webgl-disabled")}catch{}if(h&&n&&console.log("[CRASH-DIAG] WebGL sticky-disabled from prior stalls \u2014 DOM renderer in use. Re-enable: ?webgl=force"),!h)if(typeof WebglAddon<"u")this._initWebGL();else{const l=document.createElement("script");l.src="vendor/xterm-addon-webgl.min.js",l.onload=()=>this._initWebGL(),l.onerror=()=>console.warn("[CRASH-DIAG] Failed to load WebGL addon \u2014 using canvas renderer"),document.head.appendChild(l)}this._localEchoOverlay=new LocalEchoOverlay(this.terminal),this._predictiveEcho=typeof PredictiveEchoOverlay<"u"?new PredictiveEchoOverlay(this.terminal):null,this._predictiveEcho?.setPredictWhen(l=>window.CodemanTerminalInput.isCodexComposerRow(l)),MobileDetection.isTouchDevice()&&(this.terminal.onCursorMove(()=>this._syncMobileHelperTextareaToCursor()),this.terminal.onRender(()=>this._syncMobileHelperTextareaToCursor())),this._cjkInput=null,typeof CjkInput<"u"&&(this._cjkInput=CjkInput.init({send:l=>{this._handleCjkInput(l)}}));const c=this.terminal.focus.bind(this.terminal);this.terminal.focus=()=>{const l=document.getElementById("cjkInput");l?.classList.contains("cjk-input-visible")?l.focus():c()},MobileDetection.getDeviceType()==="mobile"&&document.body.classList.contains("safari-browser")?requestAnimationFrame(()=>{this.fitAddon.fit(),requestAnimationFrame(()=>this.fitAddon.fit())}):this.fitAddon.fit(),this.registerFilePathLinkProvider(),this.terminal.onSelectionChange?.(()=>{if(!this.terminal?.hasSelection?.()){this._touchSelecting=!1,this._touchSelectionActive=!1,this._touchSelectionAnchor=null,this._hideTouchSelectionBar(),this._autoCopyPending=!1;return}this._autoCopyPending=!0}),this._autoCopyListenerInstalled||(this._autoCopyListenerInstalled=!0,document.addEventListener("mouseup",()=>this._flushAutoCopySelection())),i.addEventListener("wheel",l=>{const p=this.terminal?.modes?.mouseTrackingMode;if(p&&p!=="none"||this.terminal?.buffer?.active?.type==="alternate")return;if(l.preventDefault(),l.stopPropagation(),this._shouldForwardWheelToApp(l)){this._logScrollRouting("forward-sgr"),this._forwardScrollToApp(l.clientX,l.clientY,this._wheelScrollLines(l));return}const m=this._wheelScrollLinesFloat(l);this._maybePageCliTranscript(l,m)||(this._logScrollRouting("local-scrollback"),this._noteTerminalUserScroll(m),this._smoothScrollBy(m))},{passive:!1,capture:!0});{const l=()=>this.terminal._core?._renderService?.dimensions?.css?.cell?.height||13;let p=0,m=0,S=0,g=0,f=null,w=!1;const T=C=>{const x=g?(C-g)/16.67:1;if(g=C,!w&&Math.abs(S)>.3){const O=Math.round(S/l());O!==0&&(this._shouldForwardWheelToApp({shiftKey:!1})?this._forwardScrollToApp(p,m,O):this._maybePageCliTranscript({shiftKey:!1},O)||(this.terminal.scrollLines(O),this._maybeLoadMoreHistoryOnScroll(O))),S*=.92,f=requestAnimationFrame(T)}else w?f=requestAnimationFrame(T):(f=null,S=0)};let L=0,M=!1,A=null,R=0,P=0,F=0,k=!1,b=null;const E=window.CodemanTerminalInput.MOBILE_KEYBOARD_DISMISS_TAP_SLOP;i.addEventListener("touchstart",C=>{if(!C.target?.closest?.(".term-select-bar")&&(C.touches.length!==1&&(clearTimeout(A),A=null),C.touches.length===1)){p=C.touches[0].clientX,m=C.touches[0].clientY,F=m,S=0,L=0,w=!0,M=!1,k=this._isMobileTerminalInputFocused();const x=this._classifyMobileTerminalTap(p,m);b={x:p,y:m,intent:x},x==="content"&&(C.preventDefault(),this._blurMobileTerminalInput()),R=p,P=m,clearTimeout(A),A=setTimeout(()=>{A=null,this._beginTouchSelection(R,P)},window.CodemanTerminalInput.TOUCH_SELECT_LONG_PRESS_MS),g=0,f&&(cancelAnimationFrame(f),f=null)}},{passive:!1}),i.addEventListener("touchmove",C=>{if(this._touchSelecting){C.preventDefault();const x=C.touches[0];x&&this._extendTouchSelection(x.clientX,x.clientY);return}if(A&&C.touches.length===1){const x=C.touches[0];(Math.abs(x.clientX-R)>E||Math.abs(x.clientY-P)>E)&&(clearTimeout(A),A=null)}if(C.touches.length===1&&w){const x=C.touches[0].clientY;if(!M&&Math.abs(x-F)>=E&&(M=!0),!M)return;C.preventDefault();const O=m-x;L+=O,S=O*1.2,p=C.touches[0].clientX,m=x;const D=l(),B=Math.trunc(L/D);B!==0&&(this._shouldForwardWheelToApp({shiftKey:!1})?(this._logScrollRouting("forward-sgr"),this._forwardScrollToApp(p,m,B)):this._maybePageCliTranscript({shiftKey:!1},B)||(this._logScrollRouting("local-scrollback"),this._noteTerminalUserScroll(B),this.terminal.scrollLines(B),this._maybeLoadMoreHistoryOnScroll(B)),L-=B*D)}},{passive:!1}),i.addEventListener("touchend",C=>{if(!C.target?.closest?.(".term-select-bar")){if(clearTimeout(A),A=null,w=!1,this._touchSelecting){C.preventDefault(),S=0,this._endTouchSelectionGesture(),k=!1;return}if(!f&&Math.abs(S)>.3&&(f=requestAnimationFrame(T)),!M&&this.terminal){const x=C.changedTouches&&C.changedTouches[0];if(x){this._suppressTrustedTapMouseEvents();const O=b&&b.x===x.clientX&&b.y===x.clientY?b.intent:null;this._handleMobileTerminalTap(x,k,O)}}k=!1}},{passive:!1}),i.addEventListener("contextmenu",C=>{(A!==null||this._touchSelecting||this._touchSelectionActive)&&C.preventDefault()}),i.addEventListener("touchcancel",()=>{clearTimeout(A),A=null,w=!1,this._touchSelecting=!1,S=0,L=0,k=!1},{passive:!0})}i.addEventListener("click",l=>this._handleDesktopTerminalClick(l)),this._installMobileKeyboardDismiss(),this.showWelcome(),this.initImageInput(),this._chunkedWriteGen=0,this._bufferLoadSeq=0,this._bufferLoadOwner=null,this._lastUserScrollUpAt=null,this._resizeTimeout=null,this._lastResizeDims=null;const y=40,I=10,v=()=>{this._tabRailResizeOwnsObserver||(this._resizeTimeout&&clearTimeout(this._resizeTimeout),this._resizeTimeout=setTimeout(()=>{this._resizeTimeout=null,this.fitAddon&&this.fitAddon.fit(),this.flickerFilterBuffer&&(this.flickerFilterTimeout&&(clearTimeout(this.flickerFilterTimeout),this.flickerFilterTimeout=null),this.flushFlickerBuffer());const l=typeof KeyboardHandler<"u"&&KeyboardHandler.keyboardVisible;if(this.activeSessionId&&!l){const p=this.fitAddon.proposeDimensions(),m=p?Math.max(p.cols,y):y,S=p?Math.max(p.rows,I):I;if(!this._lastResizeDims||m!==this._lastResizeDims.cols||S!==this._lastResizeDims.rows){const g=this.activeSessionId?this.sessions.get(this.activeSessionId):null;g&&g.mode!=="shell"&&this.terminal&&this.isTerminalAtBottom()&&this.terminal.write("\x1B[3J\x1B[H\x1B[2J"),this._lastResizeDims={cols:m,rows:S};const f=typeof MobileDetection<"u"&&MobileDetection.getDeviceType?MobileDetection.getDeviceType():"desktop";let w=!1;if(this._wsReady&&this._wsSessionId===this.activeSessionId)try{this._ws.send(JSON.stringify({t:"z",c:m,r:S,v:f})),w=!0}catch{}w||fetch(`/api/sessions/${this.activeSessionId}/resize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cols:m,rows:S,viewportType:f})}).catch(()=>{})}}this.applyLineageLineSettings?.(),this.updateConnectionLines(),this._localEchoOverlay?.hasPending&&this._localEchoOverlay.rerender()},300))};window.addEventListener("resize",v),this.terminalResizeObserver&&this.terminalResizeObserver.disconnect(),this.terminalResizeObserver=new ResizeObserver(v),this.terminalResizeObserver.observe(i),this._pendingInput="",this._inputFlushTimeout=null,this._lastKeystrokeTime=0;const _=()=>{if(this._inputFlushTimeout=null,this._pendingInput&&this.activeSessionId){const l=this._pendingInput,p=this.activeSessionId;this._pendingInput="",this._sendInputAsync(p,l)}};this.terminal.onData(l=>{if(!/^\x1b\[<\d+;\d+;\d+[Mm]$/.test(l)&&(window.cjkActive||document.activeElement?.id==="cjkInput")){const m=document.getElementById("cjkInput");m?.classList.contains("cjk-input-visible")&&document.activeElement===this.terminal.textarea&&!window.CodemanTerminalInput?.shouldSuppressTerminalQueryResponse(l)&&(_crashDiag.log("CJK regain-focus (onData swallowed input)"),m.focus());return}if(this.activeSessionId){if(window.CodemanTerminalInput?.shouldSuppressTerminalQueryResponse(l))return;typeof KeyboardAccessoryBar<"u"&&KeyboardAccessoryBar.isCtrlArmed?.()&&!window.CodemanTerminalInput?.isTerminalFocusOrMouseReport(l)&&(l=KeyboardAccessoryBar.consumeCtrl(l)),this._lastTerminalData={data:l,time:performance.now()};const m=this._localEchoEnabled&&this._echoPassthroughSessions?.has(this.activeSessionId);if(m&&(l==="\r"||l==="")&&this._echoPassthroughSessions.delete(this.activeSessionId),this._localEchoEnabled&&!m){if(l==="\x7F"){const g=this._localEchoOverlay?.removeChar();if(g==="flushed"){const{count:f,text:w}=this._localEchoOverlay.getFlushed();this._flushedOffsets?.has(this.activeSessionId)&&(f===0?(this._flushedOffsets.delete(this.activeSessionId),this._flushedTexts?.delete(this.activeSessionId)):(this._flushedOffsets.set(this.activeSessionId,f),this._flushedTexts?.set(this.activeSessionId,w))),this._pendingInput+=l,_()}else g===!1&&(this._pendingInput+=l,_());return}if(/^[\r\n]+$/.test(l)){const g=this._localEchoOverlay?.pendingText||"";this._localEchoOverlay?.clear(),this._localEchoOverlay?.suppressBufferDetection(),this._flushedOffsets?.delete(this.activeSessionId),this._flushedTexts?.delete(this.activeSessionId),this._inputFlushTimeout&&(clearTimeout(this._inputFlushTimeout),this._inputFlushTimeout=null),g&&(this._pendingInput+=g,_()),setTimeout(()=>{this._pendingInput+="\r",_()},80);return}if(l.length>1&&l.charCodeAt(0)>=32){this._localEchoOverlay?.appendText(l);return}if(l.charCodeAt(0)<32){if(l.length>1&&l.charCodeAt(0)===27){if(l.startsWith(window.CodemanTerminalInput.BRACKETED_PASTE_START)){const f=!!this._localEchoOverlay?.pendingText;this._flushLocalEchoPending(),f?(_(),setTimeout(()=>{this._pendingInput+=l,_()},80)):(this._pendingInput+=l,_());return}if(window.CodemanTerminalInput.isComposerNavKey(l)){this._flushLocalEchoPending(),this._echoPassthroughSessions||(this._echoPassthroughSessions=new Set),this._echoPassthroughSessions.add(this.activeSessionId),this._pendingInput+=l,_();return}this._pendingInput+=l,_();return}if(this._restoringFlushedState){this._pendingInput+=l,_();return}if(l===" "){const f=this._localEchoOverlay?.pendingText||"";this._localEchoOverlay?.clear(),this._flushedOffsets?.delete(this.activeSessionId),this._flushedTexts?.delete(this.activeSessionId),f&&(this._pendingInput+=f),this._pendingInput+=l,this._inputFlushTimeout&&(clearTimeout(this._inputFlushTimeout),this._inputFlushTimeout=null);let w="";try{const L=this._localEchoOverlay?.findPrompt?.();if(L){const M=this.terminal.buffer.active,A=M.getLine(M.viewportY+L.row);A&&(w=A.translateToString(!0).slice(L.col+2).trimEnd())}}catch{}this._tabCompletionBaseText=w,_(),this._tabCompletionSessionId=this.activeSessionId,this._tabCompletionRetries=0,this._tabCompletionFallback&&clearTimeout(this._tabCompletionFallback);const T=this;this._tabCompletionFallback=setTimeout(()=>{if(T._tabCompletionFallback=null,!T._tabCompletionSessionId||T._tabCompletionSessionId!==T.activeSessionId)return;const L=T._localEchoOverlay;!L||L.pendingText||T.terminal.write("",()=>{if(!T._tabCompletionSessionId)return;L.resetBufferDetection();const M=L.detectBufferText();M&&M!==T._tabCompletionBaseText&&(T._tabCompletionSessionId=null,T._tabCompletionRetries=0,T._tabCompletionBaseText=null,L.rerender())})},300);return}const g=this._localEchoOverlay?.pendingText||"";this._localEchoOverlay?.clear(),this._localEchoOverlay?.suppressBufferDetection(),this._flushedOffsets?.delete(this.activeSessionId),this._flushedTexts?.delete(this.activeSessionId),g&&(this._pendingInput+=g),this._pendingInput+=l,this._inputFlushTimeout&&(clearTimeout(this._inputFlushTimeout),this._inputFlushTimeout=null),_();return}if(l.length===1&&l.charCodeAt(0)>=32){this._localEchoOverlay?.addChar(l);return}}if(this._predictHookOnData(l),this._pendingInput+=l,l.charCodeAt(0)<32||l.length>1){this._inputFlushTimeout&&(clearTimeout(this._inputFlushTimeout),this._inputFlushTimeout=null),_();return}const S=performance.now();S-this._lastKeystrokeTime>50?(this._inputFlushTimeout&&(clearTimeout(this._inputFlushTimeout),this._inputFlushTimeout=null),this._lastKeystrokeTime=S,_()):(this._lastKeystrokeTime=S,this._inputFlushTimeout||(this._inputFlushTimeout=setTimeout(_,0)))}})},registerFilePathLinkProvider(){const e=this;let t=-1;const i={provideLinks(s,n){s!==t&&(t=s,console.debug("[LinkProvider] Checking line:",s));const o=e.terminal.buffer.active;if(!o.getLine(s-1)){n(void 0);return}const h=window.CodemanTerminalLines?.terminalLogicalLine(o,s-1,e.terminal.cols,12);if(!h){n(void 0);return}const d=h.text,c=S=>{const g=h.offsetToCell(S);return{x:g.col+1,y:g.row+1}};if(!d||!d.includes("/")){n(void 0);return}const u=[],y=/https?:\/\/(?:[^\s"'<>|;&)\]\x00-\x1f]|&(?!&))+/g,I=(S,g)=>{const f=S.replace(/[.,;:!?)&]+$/,""),w=d.indexOf(f,g);if(w===-1)return;const T=c(w),L=c(w+f.length);u.some(M=>M.range.start.x===T.x&&M.range.start.y===T.y)||u.push({text:f,range:{start:T,end:L},decorations:{pointerCursor:!0,underline:!0},activate(M,A){window.open(A,"_blank","noopener,noreferrer")},hover(){e._linkHovered=!0},leave(){e._linkHovered=!1}})},v=/\b(tail|cat|head|less|grep|watch|vim|nano)\s+(?:[^\s\/]+\s+){0,4}(\/[^\s"'<>|;&\n\x00-\x1f]+)/g,_=absoluteFilePathPattern(),l=/Bash\([^)]*?(\/(?:home|tmp|var|etc|opt)[^\s"'<>|;&\)\n\x00-\x1f]+)/g,p=(S,g)=>{const f=d.indexOf(S,g);if(f===-1)return;const w=c(f),T=c(f+S.length);u.some(L=>L.range.start.x===w.x&&L.range.start.y===w.y)||u.push({text:S,range:{start:w,end:T},decorations:{pointerCursor:!0,underline:!0},activate(L,M){if(previewsInFileViewer(M)||e._isExternalPreviewPath(M,e.activeSessionId)){e.openFilePreview(M,e.activeSessionId);return}e.openLogViewerWindow(M,e.activeSessionId)},hover(){e._linkHovered=!0},leave(){e._linkHovered=!1}})};let m;for(y.lastIndex=0;(m=y.exec(d))!==null;)I(m[0],m.index);for(v.lastIndex=0;(m=v.exec(d))!==null;)p(m[2],m.index);for(_.lastIndex=0;(m=_.exec(d))!==null;)p(m[1],m.index);for(l.lastIndex=0;(m=l.exec(d))!==null;)p(m[1],m.index);u.length>0&&console.debug("[LinkProvider] Found links:",u.map(S=>S.text)),n(u.length>0?u:void 0)}};this._terminalLinkProvider=i,this.terminal.registerLinkProvider(i),console.log("[LinkProvider] File path link provider registered")},_terminalLinkAtPoint(e,t){const i=this._terminalLinkProvider,s=this.terminal?.buffer?.active;if(!i||!s)return null;const n=this._clientPointToCell(e,t);if(!n)return null;const o=(s.viewportY||0)+n.row;let r=null;try{i.provideLinks(o,d=>{r=d||[]})}catch{return null}if(!r||r.length===0)return null;const a=Math.max(1,this.terminal.cols||1),h=o*a+n.col;return r.find(d=>{const c=d?.range?.start,u=d?.range?.end;return!c||!u?!1:c.y*a+c.x<=h&&h<=u.y*a+u.x})||null},_tapIsOnCaretLine(e,t){const i=this.terminal?.buffer?.active;if(!i?.getLine)return!1;const s=this._clientPointToCell(e,t);if(!s)return!1;const n=Math.max(1,this.terminal.rows||1),o=Math.max(0,Math.min(n-1,i.cursorY||0)),r=s.row-1;if(r===o)return!0;let a=o;for(;a>0&&i.getLine(i.viewportY+a)?.isWrapped;)a--;let h=o;for(;h+1<n&&i.getLine(i.viewportY+h+1)?.isWrapped;)h++;return r>=a&&r<=h},_activateTerminalLinkAtPoint(e,t){const i=this._terminalLinkAtPoint(e,t);if(!i||typeof i.activate!="function")return!1;try{i.activate(null,i.text)}catch(s){return console.warn("[LinkProvider] tap activation failed:",s),!1}return!0},_installTouchSelectionFocusGuard(){const e=this.terminal?.textarea;!e||e._codemanSelectionFocusGuard||(e._codemanSelectionFocusGuard=!0,e.addEventListener("focus",()=>{this._touchSelectionFocusGuarded()&&this._blurMobileTerminalInput()}))},_touchSelectionFocusGuarded(){return this._touchSelecting?!0:performance.now()<(this._touchSelectionFocusGuardUntil||0)},_armTouchSelectionFocusGuard(){this._touchSelectionFocusGuardUntil=performance.now()+(window.CodemanTerminalInput?.TOUCH_SELECT_FOCUS_GUARD_MS||800)},_touchSelectionCellAt(e,t){const i=this._clientPointToCell(e,t),s=this.terminal?.buffer?.active;return!i||!s?null:{col:i.col-1,row:(s.viewportY||0)+i.row-1}},_touchSelectionLogicalLine(e){const t=this.terminal?.buffer?.active,i=Math.max(1,this.terminal?.cols||1);return!t||typeof window.CodemanTerminalLines?.terminalLogicalLine!="function"?null:window.CodemanTerminalLines.terminalLogicalLine(t,e,i)},_touchSelectionWordAt(e){const t=Math.max(1,this.terminal?.cols||1),i=this._touchSelectionLogicalLine(e.row);if(!i)return null;const s=i.cellToOffset(e.row,e.col);if(s<0)return null;const n=i.text[s];if(!n||!n.trim())return null;let o=s;for(;o>0&&i.text[o-1]&&i.text[o-1].trim();)o--;let r=s;for(;r+1<i.text.length&&i.text[r+1]&&i.text[r+1].trim();)r++;const a=i.offsetToCell(o),h=i.offsetToCell(r),d=a.row*t+a.col,c=h.row*t+h.col-d+1;return c>0?{index:d,length:c}:null},_applyTouchSelection(e,t){const i=Math.max(1,this.terminal?.cols||1);t<=0||this.terminal?.select?.(e%i,Math.floor(e/i),t)},_beginTouchSelection(e,t){const i=this._touchSelectionCellAt(e,t);if(!i)return!1;const s=this._touchSelectionWordAt(i);if(!s)return!1;this._blurMobileTerminalInput(),this._touchSelectionAnchor=s,this._touchSelecting=!0,this._touchSelectionActive=!0,this._suppressTrustedTapMouseEvents(),this._armTouchSelectionFocusGuard(),this._applyTouchSelection(s.index,s.length);try{navigator.vibrate?.(15)}catch{}return this._showTouchSelectionBar(),!0},_extendTouchSelection(e,t){const i=this._touchSelectionAnchor,s=this._touchSelectionCellAt(e,t);if(!i||!s)return;const n=Math.max(1,this.terminal?.cols||1),o=s.row*n+s.col,r=Math.min(i.index,o),a=Math.max(i.index+i.length,o+1);this._applyTouchSelection(r,a-r),this._armTouchSelectionFocusGuard(),this._positionTouchSelectionBar()},_endTouchSelectionGesture(){this._touchSelecting=!1,this._suppressTrustedTapMouseEvents(),this._armTouchSelectionFocusGuard(),this._positionTouchSelectionBar(),this._flushAutoCopySelection()},_selectTouchSelectionLine(){const e=this._touchSelectionAnchor,t=Math.max(1,this.terminal?.cols||1);if(!e)return;const i=this._touchSelectionLogicalLine(Math.floor(e.index/t));if(!i)return;const n=(this.terminal?.buffer?.active?.getLine(i.endRow)?.translateToString(!0)||"").length,o=i.startRow*t,r=i.endRow*t+Math.max(0,n-1)-o+1;r<=0||(this._touchSelectionAnchor={index:o,length:r},this._applyTouchSelection(o,r),this._positionTouchSelectionBar(),this._flushAutoCopySelection())},async _copyTouchSelection(){const e=await this.copyTerminalSelection();return this._clearTouchSelection(),typeof MobileDetection<"u"&&MobileDetection.isTouchDevice?.()&&this._blurMobileTerminalInput(),e},_clearTouchSelection(){this._touchSelecting=!1,this._touchSelectionActive=!1,this._touchSelectionAnchor=null,this.terminal?.clearSelection?.(),this._hideTouchSelectionBar()},_ensureTouchSelectionBar(){if(this._touchSelectionBar?.isConnected)return this._touchSelectionBar;const e=document.getElementById("terminalContainer");if(!e)return null;const t=document.createElement("div");return t.className="term-select-bar",t.setAttribute("role","toolbar"),t.innerHTML='<button type="button" class="term-select-btn" data-act="copy">Copy</button><button type="button" class="term-select-btn" data-act="line">Line</button><button type="button" class="term-select-btn term-select-btn--close" data-act="close" aria-label="Clear selection">\u2715</button>',t.addEventListener("click",i=>{const s=i.target?.closest?.("[data-act]")?.dataset?.act;s&&(i.preventDefault(),i.stopPropagation(),s==="copy"?this._copyTouchSelection():s==="line"?this._selectTouchSelectionLine():this._clearTouchSelection())}),e.appendChild(t),this._touchSelectionBar=t,t},_showTouchSelectionBar(){const e=this._ensureTouchSelectionBar();e&&(e.classList.add("visible"),this._positionTouchSelectionBar())},_hideTouchSelectionBar(){this._touchSelectionBar?.classList.remove("visible")},_positionTouchSelectionBar(){const e=this._touchSelectionBar,t=document.getElementById("terminalContainer"),i=this.terminal?.element?.querySelector(".xterm-screen"),s=this.terminal?._core?._renderService?.dimensions?.css?.cell,n=this.terminal?.getSelectionPosition?.(),o=this.terminal?.buffer?.active;if(!e||!t||!i||!s?.height||!n||!o)return;const r=i.getBoundingClientRect(),a=t.getBoundingClientRect(),h=l=>l-(o.viewportY||0),d=r.top-a.top+h(n.start.y)*s.height,c=r.top-a.top+(h(n.end.y)+1)*s.height,u=e.offsetHeight||36,y=6;let I=d-u-y;I<0&&(I=c+y),I=Math.max(0,Math.min(I,a.height-u));const v=r.left-a.left+n.start.x*(s.width||8),_=e.offsetWidth||150;e.style.top=`${Math.round(I)}px`,e.style.left=`${Math.round(Math.max(0,Math.min(v,a.width-_)))}px`},showWelcome(){if(this.shouldUseMobileOverview?.()){const t=document.getElementById("welcomeOverlay");t&&t.classList.remove("visible"),this.hideHomeSessions?.(),this.showMobileOverview(),this._updateCjkInputState?.();return}this.hideMobileOverview?.();const e=document.getElementById("welcomeOverlay");e&&(e.classList.add("visible"),this.loadTunnelStatus(),this.applyWelcomeCliVisibility(),this.loadHistorySessions(),this.initSearchPanel(),this.showHomeSessions?.()),this._updateCjkInputState?.()},hideWelcome(){this.hideMobileOverview?.(),this.hideHomeSessions?.();const e=document.getElementById("welcomeOverlay");e&&e.classList.remove("visible");const t=document.getElementById("welcomeQr");t&&(clearTimeout(this._welcomeQrShrinkTimer),t.classList.remove("expanded")),this._updateCjkInputState?.()},async _fetchHistorySessions(){const i=(await(await fetch("/api/history/sessions")).json()).data?.sessions||[];if(i.length===0)return[];const s=new Map;for(const o of i){const r=o.projectKey||o.workingDir;s.has(r)||s.set(r,[]),s.get(r).push(o)}const n=[];for(const[,o]of s)n.push(...o.slice(0,3));return n.sort((o,r)=>new Date(r.lastModified)-new Date(o.lastModified)),n},async _fetchUnifiedSessions(e=60){const t=await fetch("/api/sessions/unified?limit="+e),i=await t.json().catch(()=>null);if(!t.ok||!i||i.success===!1||!i.data)throw new Error(i?.error||`unified sessions request failed (HTTP ${t.status})`);return i.data.sessions||[]},_worktreeLabel(e){const t=e&&e.worktreeName;if(!t)return"";let i=e.gitBranch||"";return(i===t||i===`worktree-${t}`)&&(i=""),i.length>24&&(i=i.slice(0,23)+"\u2026"),"\u2442 "+[t,i].filter(Boolean).join(" \xB7 ")},_resolveCaseLabel(e,t){if(!e)return"";let i=null;for(const s of t||[])if(!(!s||!s.path)){if(e===s.path)return`#${s.name}`;if(e.startsWith(s.path+"/")){const n=s.path.length;(!i||n>i.len)&&(i={name:s.name,suffix:e.slice(n),len:n})}}return i?`#${i.name}${i.suffix}`:e.split("/").pop()||e},_shortenHomePath(e){return(e||"").replace(/^\/(?:home|Users)\/[^/]+(?=\/|$)/,"~")},_buildHistoryItem(e,t,i){const s=i?.showViewAll!==!1,n=typeof e.sizeBytes=="number",o=n?e.sizeBytes<1024?`${e.sizeBytes}B`:e.sizeBytes<1048576?`${(e.sizeBytes/1024).toFixed(0)}K`:`${(e.sizeBytes/1048576).toFixed(1)}M`:"",r=typeof e.lastActivityAt=="number"?e.lastActivityAt:e.lastModified?Date.parse(e.lastModified):NaN;let a="";if(!Number.isNaN(r)){const b=new Date(r);a=b.toLocaleDateString("en",{month:"short",day:"numeric"})+" "+b.toLocaleTimeString("en",{hour:"2-digit",minute:"2-digit",hour12:!1})}const h=this._shortenHomePath(e.workingDir),d=this._resolveCaseLabel(e.workingDir,t),c=Array.isArray(e.sources)&&e.sources.includes("live"),u=e.pinned===!0,y=document.createElement("div");y.className="history-item"+(u?" is-pinned":""),y.title=e.workingDir||"";const I=document.createElement("div");I.className="history-item-main",I.addEventListener("click",i?.onActivate||(()=>{c&&this.sessions.has(e.sessionId)?this.selectSession(e.sessionId):this.resumeHistorySession(e.claudeSessionId||e.sessionId,e.workingDir||"",e.name)}));const v=document.createElement("div");v.className="history-item-text";const _=document.createElement("span");if(_.className="history-item-title",u){const b=document.createElement("span");b.className="history-item-pin",b.textContent="\u{1F4CC}",b.setAttribute("aria-label","Pinned"),b.title="Pinned",_.appendChild(b)}_.appendChild(document.createTextNode(this._historyRowLabel(e,h)));const l=document.createElement("div");if(l.className="history-item-badges",e.mode){const b=document.createElement("span");b.className="history-item-badge history-item-badge-mode",b.textContent=e.mode,l.appendChild(b)}const p=this._worktreeLabel(e);if(p){const b=document.createElement("span");b.className="history-item-badge history-item-badge-worktree",b.textContent=p,b.title=e.worktreeRepo?`worktree of ${e.worktreeRepo}`:p,l.appendChild(b)}if(c){const b=document.createElement("span");b.className="history-item-badge history-item-badge-live",b.textContent="LIVE",l.appendChild(b)}const m=document.createElement("span");m.className="history-item-subtitle",d.startsWith("#")&&m.classList.add("is-case"),m.textContent=d,v.append(_),l.childElementCount>0&&v.append(l),v.append(m);const S=document.createElement("span");S.className="history-item-meta",S.textContent=a;const g=document.createElement("button");g.className="history-item-expand",g.type="button",g.setAttribute("aria-haspopup","menu"),g.setAttribute("aria-label","Session actions"),g.setAttribute("aria-expanded","false"),g.textContent="\u22EF",I.append(v,S,g);const f=document.createElement("div");f.className="history-item-detail",f.hidden=!0;const w=document.createElement("div");w.className="history-detail-row";const T=document.createElement("span");T.className="history-detail-label",T.textContent="Prompt";const L=document.createElement("span");L.className="history-detail-value history-detail-prompt",L.textContent=e.firstPrompt||"(no prompt captured)",w.append(T,L);let M=null;if(e.lastPrompt&&e.lastPrompt!==e.firstPrompt){M=document.createElement("div"),M.className="history-detail-row";const b=document.createElement("span");b.className="history-detail-label",b.textContent="Last prompt";const E=document.createElement("span");E.className="history-detail-value history-detail-prompt",E.textContent=e.lastPrompt,M.append(b,E)}const A=document.createElement("div");A.className="history-detail-row";const R=document.createElement("span");R.className="history-detail-label",R.textContent="Path";const P=document.createElement("span");P.className="history-detail-value history-detail-path",P.textContent=h,A.append(R,P);const F=document.createElement("div");F.className="history-detail-row history-detail-meta";const k=[];if(a&&k.push(a),n&&k.push(o),k.push(e.sessionId.slice(0,8)),F.textContent=k.join(" \xB7 "),f.append(w),M&&f.append(M),f.append(A,F),s&&e.projectKey){const b=document.createElement("div");b.className="history-detail-row history-detail-actions";const E=document.createElement("button");E.type="button",E.className="history-view-all-btn",E.textContent="View all in this folder",E.addEventListener("click",C=>{C.stopPropagation(),this.openFolderHistoryModal(e.projectKey,e.workingDir,t)}),b.appendChild(E),f.appendChild(b)}return g.addEventListener("click",b=>{b.stopPropagation(),b.preventDefault(),this._openSessionRowMenu(b.currentTarget,e,t,y,f)}),y.append(I,f),y},_openSessionRowMenu(e,t,i,s,n){if(this._openRowMenuClose)try{this._openRowMenuClose()}catch{}const o=Array.isArray(t.sources)&&t.sources.includes("live")&&this.sessions.has(t.sessionId),r=document.createElement("div");r.className="session-row-menu",r.setAttribute("role","menu");let a=null,h=null,d=null;const c=()=>{document.removeEventListener("mousedown",a,!0),document.removeEventListener("keydown",h,!0),window.removeEventListener("scroll",d,!0),window.removeEventListener("resize",d,!0);try{r.remove()}catch{}this._openRowMenuEl===r&&(this._openRowMenuEl=null,this._openRowMenuClose=null)},u=(m,S,g)=>{const f=document.createElement("button");f.type="button",f.className="session-row-menu-item",f.setAttribute("role","menuitem");const w=document.createElement("span");if(w.className="session-row-menu-label",w.textContent=m,f.appendChild(w),g&&g.sublabel){const T=document.createElement("span");T.className="session-row-menu-sublabel",T.textContent=g.sublabel,f.appendChild(T)}f.addEventListener("click",async T=>{T.stopPropagation(),T.preventDefault(),await S()}),r.appendChild(f)};u(o?"Switch to session":"Resume session",()=>{o?this.selectSession(t.sessionId):this.resumeHistorySession(t.claudeSessionId||t.sessionId,t.workingDir||"",t.name),this.closeSessionManager?.(),c()});const y=t.pinned===!0;u(y?"Unpin session":"Pin to top",async()=>{await this._setSessionPinned(t.sessionId,!y)?(t.pinned=!y,this.showToast(y?"Unpinned":"Pinned to top","success")):this.showToast("Pin failed","error"),c()}),o&&u("Open folder",()=>{this.selectSession(t.sessionId),this.loadFileBrowser?.(t.sessionId),this.closeSessionManager?.(),c()}),t.workingDir&&u("Copy path",async()=>{const m=await this._copyText(t.workingDir);this.showToast(m?"Path copied":"Copy failed",m?"success":"error"),c()}),u("Show details",()=>{const m=s.classList.toggle("expanded");n.hidden=!m,e.setAttribute("aria-expanded",m?"true":"false"),c()}),document.body.appendChild(r);const I=e.getBoundingClientRect(),v=r.getBoundingClientRect(),_=4;let l=I.bottom+_;l+v.height>window.innerHeight&&I.top-_-v.height>=0&&(l=I.top-_-v.height);let p=I.right-v.width;p<_&&(p=_),p+v.width>window.innerWidth-_&&(p=Math.max(_,window.innerWidth-_-v.width)),r.style.top=`${Math.max(_,l)}px`,r.style.left=`${p}px`,a=m=>{r.contains(m.target)||e.contains(m.target)||c()},h=m=>{m.key==="Escape"&&(m.stopPropagation(),c())},d=()=>c(),document.addEventListener("mousedown",a,!0),document.addEventListener("keydown",h,!0),window.addEventListener("scroll",d,!0),window.addEventListener("resize",d,!0),this._openRowMenuEl=r,this._openRowMenuClose=c},async _setSessionPinned(e,t){try{const i=await fetch(`/api/sessions/${encodeURIComponent(e)}/pin`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"same-origin",body:JSON.stringify({pinned:t})});return i.ok?(await i.json())?.success===!0:!1}catch(i){return console.error("[_setSessionPinned]",i),!1}},_HISTORY_INITIAL_COUNT:10,_HISTORY_FETCH_LIMIT:200,_HISTORY_SORT_KEY:"codeman:historySort",async loadHistorySessions(){const e=document.getElementById("historySessions"),t=document.getElementById("historyList");if(!(!e||!t))try{const i=Array.isArray(this.cases)&&this.cases.length>0?Promise.resolve(this.cases):fetch("/api/cases").then(o=>o.ok?o.json():null).then(o=>o?.data||[]).catch(()=>[]),[s,n]=await Promise.all([this._fetchUnifiedSessions(this._HISTORY_FETCH_LIMIT),i]);if(s.length===0){e.style.display="none";return}this._historyAll=s,this._historyCases=n,this._wireHistoryControls(),this._renderHistoryList(),e.style.display=""}catch(i){console.error("[loadHistorySessions]",i),e.style.display="none"}},_wireHistoryControls(){if(this._historyControlsWired)return;const e=document.getElementById("historyFilter"),t=document.getElementById("historySort");if(!(!e&&!t)){if(this._historyControlsWired=!0,t)try{const i=localStorage.getItem(this._HISTORY_SORT_KEY);i&&Array.from(t.options).some(s=>s.value===i)&&(t.value=i)}catch{}e&&(e.addEventListener("input",()=>this._renderHistoryList()),e.addEventListener("keydown",i=>{i.key==="Escape"&&e.value&&(i.stopPropagation(),e.value="",this._renderHistoryList())})),t&&t.addEventListener("change",()=>{try{localStorage.setItem(this._HISTORY_SORT_KEY,t.value)}catch{}this._renderHistoryList()})}},_historyRowMatches(e,t,i){return[e.name,e.workingDir,this._resolveCaseLabel(e.workingDir,i),e.firstPrompt,e.lastPrompt,e.sessionId].some(n=>typeof n=="string"&&n.toLowerCase().includes(t))},_historyRowLabel(e,t){return e.name||e.firstPrompt||t||""},_sortHistoryRows(e,t){const n=t==="name"?a=>this._historyRowLabel(a,this._shortenHomePath(a.workingDir)).toLowerCase():a=>((a.workingDir||"").split("/").pop()||"").toLowerCase(),o=t==="recent"?e.slice():e.slice().sort((a,h)=>n(a).localeCompare(n(h),void 0,{sensitivity:"base",numeric:!0})),r=o.filter(a=>a.pinned);return r.length===0?o:r.concat(o.filter(a=>!a.pinned))},_renderHistoryList(){const e=document.getElementById("historyList");if(!e)return;const t=this._historyAll||[],i=this._historyCases||[],s=document.getElementById("historyCount"),n=(document.getElementById("historyFilter")?.value||"").trim().toLowerCase(),o=document.getElementById("historySort")?.value||"recent",r=n?t.filter(u=>this._historyRowMatches(u,n,i)):t,a=this._sortHistoryRows(r,o),h=!!this._historyExpanded||n.length>0,d=h?a:a.slice(0,this._HISTORY_INITIAL_COUNT);if(e.replaceChildren(),e.classList.toggle("expanded",h),a.length===0){const u=document.createElement("div");u.className="history-empty",u.textContent=`No conversations match "${n}"`,e.appendChild(u)}for(const u of d)e.appendChild(this._buildHistoryItem(u,i));const c=a.length-d.length;if(c>0){const u=document.createElement("button");u.className="history-show-more",u.textContent=`Show ${c} more`,u.addEventListener("click",()=>{this._historyExpanded=!0,this._renderHistoryList()}),e.appendChild(u)}else if(h&&!n&&a.length>this._HISTORY_INITIAL_COUNT){const u=document.createElement("button");u.className="history-show-more",u.textContent="Show less",u.addEventListener("click",()=>{this._historyExpanded=!1,this._renderHistoryList(),e.scrollTop=0}),e.appendChild(u)}s&&(s.textContent=n?`${a.length} of ${t.length}`:a.length>d.length?`${d.length} of ${a.length}`:String(a.length))},_FOLDER_HISTORY_PAGE_SIZE:20,openFolderHistoryModal(e,t,i){this._closeFolderHistoryModal();const s=document.createElement("div");s.className="modal active folder-history-modal",s.id="folderHistoryModal";const n=document.createElement("div");n.className="modal-backdrop",n.addEventListener("click",()=>this._closeFolderHistoryModal());const o=document.createElement("div");o.className="modal-content modal-lg";const r=document.createElement("div");r.className="modal-header";const a=document.createElement("h3");a.textContent="Folder History";const h=document.createElement("div");h.className="folder-history-subtitle",h.textContent=this._shortenHomePath(t);const d=document.createElement("button");d.className="modal-close",d.setAttribute("aria-label","Close"),d.innerHTML="&times;",d.addEventListener("click",()=>this._closeFolderHistoryModal()),r.append(a,d);const c=document.createElement("div");c.className="modal-body";const u=document.createElement("div");u.className="folder-history-list",u.setAttribute("data-loading","true"),u.textContent="Loading...",c.append(h,u),o.append(r,c),s.append(n,o),document.body.appendChild(s),this._folderHistoryState={projectKey:e,workingDir:t,cases:i||[],offset:0,total:null,list:u},this._folderHistoryEscHandler=y=>{y.key==="Escape"&&this._closeFolderHistoryModal()},document.addEventListener("keydown",this._folderHistoryEscHandler),this._loadFolderHistoryPage()},async _loadFolderHistoryPage(){const e=this._folderHistoryState;if(!e)return;const{projectKey:t,cases:i,list:s}=e,n=this._FOLDER_HISTORY_PAGE_SIZE,o=e.offset,r=s.querySelector(".folder-history-more");r&&r.remove(),o===0&&(s.replaceChildren(),s.removeAttribute("data-loading"));try{const a=`/api/history/sessions?projectKey=${encodeURIComponent(t)}&offset=${o}&limit=${n}`,d=await(await fetch(a)).json(),c=d.data?.sessions||[];if(e.total=typeof d.data?.total=="number"?d.data.total:c.length+o,o===0&&c.length===0){const u=document.createElement("div");u.className="folder-history-empty",u.textContent="No conversations found in this folder.",s.appendChild(u);return}for(const u of c)s.appendChild(this._buildHistoryItem(u,i,{showViewAll:!1}));if(e.offset=o+c.length,e.offset<e.total){const u=e.total-e.offset,y=document.createElement("button");y.className="history-show-more folder-history-more",y.textContent=`Show ${Math.min(n,u)} more (${u} remaining)`,y.addEventListener("click",()=>this._loadFolderHistoryPage()),s.appendChild(y)}}catch(a){console.error("[loadFolderHistoryPage]",a);const h=document.createElement("div");h.className="folder-history-empty",h.textContent="Failed to load folder history.",s.appendChild(h)}},_closeFolderHistoryModal(){const e=document.getElementById("folderHistoryModal");e&&e.remove(),this._folderHistoryEscHandler&&(document.removeEventListener("keydown",this._folderHistoryEscHandler),this._folderHistoryEscHandler=null),this._folderHistoryState=null},_resolveResumeName(e,t){if(typeof e=="string"&&e.trim())return e;const i=(t||"").split("/").pop()||"session";let s=1;for(const[,n]of this.sessions){const o=n.name&&n.name.match(/^w(\d+)-/);if(o){const r=parseInt(o[1]);r>=s&&(s=r+1)}}return`w${s}-${i}`},async resumeHistorySession(e,t,i){document.getElementById("runModeMenu")?.classList.remove("active"),this._closeFolderHistoryModal();try{this.terminal.clear(),this.terminal.writeln(`\x1B[1;32m Resuming conversation ${e.slice(0,8)}...\x1B[0m`);const s=this._resolveResumeName(i,t),o=(this.cases||[]).find(y=>y.path===t)?.name||t.split("/").pop()||"",r=this.loadAppSettingsFromStorage(),a=this.buildEnvOverrides(this.getCaseSettings(o),r),h=this.getEffortSetting(r),c=await(await fetch("/api/sessions",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({workingDir:t,name:s,resumeSessionId:e,...Object.keys(a).length>0?{envOverrides:a}:{},...h?{effort:h}:{}})})).json();if(!c.success)throw new Error(c.error);const u=c.data.session.id;await fetch(`/api/sessions/${u}/interactive`,{method:"POST"}),this.terminal.writeln(`\x1B[90m Session ${s} ready\x1B[0m`),await this.selectSession(u),this.terminal.focus()}catch(s){this.terminal.writeln(`\x1B[1;31m Error: ${s.message}\x1B[0m`)}},isTerminalAtBottom(){if(!this.terminal)return!0;const e=this.terminal.buffer.active;return e.viewportY>=e.baseY-2},_noteTerminalUserScroll(e){e<0?this._lastUserScrollUpAt=performance.now():this.isTerminalAtBottom()&&(this._lastUserScrollUpAt=null)},_maybeLoadMoreHistoryOnScroll(e){e>=0||this.terminal?.buffer?.active?.viewportY===0&&this._maybeRefetchFullHistory?.()},_estimateReplayRows(e,t){if(typeof e!="string"||!e)return 0;const i=t>0?t:80,s=e.replace(window.CodemanTerminalInput.REPLAY_ESCAPE_RE,"");let n=0;for(const o of s.split(`
2
- `)){const r=o.endsWith("\r")?o.length-1:o.length;n+=r>i?Math.ceil(r/i):1}return n},_replayWouldShrinkBuffer(e){const t=this.terminal,i=t?.buffer?.active?.length||0;if(!i)return!1;const s=t?.rows||24;return this._estimateReplayRows(e,t?.cols)+s<i},_smoothScrollBy(e){if(!e||(this._smoothScrollPending=(this._smoothScrollPending||0)+e,this._smoothScrollSession=this.activeSessionId,this._smoothScrollFrame))return;const t=()=>{this._smoothScrollFrame=null;const i=this._smoothScrollPending||0;if(!i)return;if(this.activeSessionId!==this._smoothScrollSession){this._smoothScrollPending=0;return}if(Math.abs(i)<1)return;const s=i*.22,n=i>0?Math.max(1,Math.floor(s)):Math.min(-1,Math.ceil(s));this._smoothScrollPending=i-n,this.terminal.scrollLines(n),this._maybeLoadMoreHistoryOnScroll(n),Math.abs(this._smoothScrollPending)>=1&&(this._smoothScrollFrame=requestAnimationFrame(t))};this._smoothScrollFrame=requestAnimationFrame(t)},_forwardScrollToApp(e,t,i){this._terminalViewportAtBottom()||this.terminal.scrollToBottom(),this._sendSyntheticSgrWheel(e,t,i)},_hasRecentUserScrollUp(){return typeof this._lastUserScrollUpAt!="number"?!1:performance.now()-this._lastUserScrollUpAt<window.CodemanTerminalInput.USER_SCROLL_STICKY_SUPPRESS_MS},batchTerminalWrite(e){if(this._isLoadingBuffer){this._loadBufferQueue&&this._loadBufferQueue.push(e);return}if(this.writeFrameScheduled||(this._wasAtBottomBeforeWrite=this.isTerminalAtBottom()),(this.activeSessionId?this.sessions.get(this.activeSessionId):null)?.flickerFilterEnabled??!1){if(e.includes("\x1B[2J")||e.includes("\x1B[H\x1B[J")||e.includes("\x1B[H")&&e.includes("\x1B[?25l")){this.flickerFilterActive=!0,this.flickerFilterBuffer+=e,this.flickerFilterTimeout&&clearTimeout(this.flickerFilterTimeout),this.flickerFilterTimeout=setTimeout(()=>{this.flickerFilterTimeout=null,this.flushFlickerBuffer()},SYNC_WAIT_TIMEOUT_MS);return}if(this.flickerFilterActive){this.flickerFilterBuffer+=e;return}}this.pendingWrites.push(e),this._scheduleTerminalWriteFlush()},_scheduleTerminalWriteFlush(){this.writeFrameScheduled||this.pendingWrites.length===0||(this.writeFrameScheduled=!0,this._safeYield(()=>{this.writeFrameScheduled=!1,this.flushPendingWrites()}))},flushFlickerBuffer(){this.flickerFilterBuffer&&(this.pendingWrites.push(this.flickerFilterBuffer),this.flickerFilterBuffer="",this.flickerFilterActive=!1,this._scheduleTerminalWriteFlush())},_flushLocalEchoPending(){const e=this._localEchoOverlay?.pendingText||"";this._localEchoOverlay?.clear(),this._localEchoOverlay?.suppressBufferDetection(),this._flushedOffsets?.delete(this.activeSessionId),this._flushedTexts?.delete(this.activeSessionId),e&&(this._pendingInput+=e)},_updateLocalEchoState(){const e=this.loadAppSettingsFromStorage(),t=this.activeSessionId?this.sessions.get(this.activeSessionId):null,i=e.localEchoEnabled??MobileDetection.isTouchDevice(),s=!!(i&&t);this._localEchoEnabled&&!s&&this._localEchoOverlay?.clear(),this._localEchoEnabled=s,this._localEchoOverlay&&t&&(t.mode==="opencode"?this._localEchoOverlay.setPrompt({type:"custom",offset:3,find:o=>{try{const r=o.buffer.active,a=r.cursorY,h=r.getLine(r.viewportY+a);if(!h)return null;const c=h.translateToString(!0).indexOf("\u2503");return c>=0?{row:a,col:c}:null}catch{return null}}}):t.mode==="shell"||t.mode==="codex"?(this._localEchoOverlay.clear(),this._localEchoEnabled=!1):this._localEchoOverlay.setPrompt({type:"custom",offset:0,find:o=>{try{const r=o.buffer.active;for(let a=o.rows-1;a>=0;a--){const h=r.getLine(r.viewportY+a);if(!h)continue;const c=h.translateToString(!0).lastIndexOf("\u276F");if(c>=0)return{row:a,col:c+2}}return{row:Math.max(0,Math.min(o.rows-1,r.cursorY)),col:Math.max(0,Math.min(o.cols-1,r.cursorX))}}catch{return null}}}));let n="off";t&&i&&(t.mode==="codex"?n="predict":t.mode!=="shell"&&(n="buffer")),this._localEchoPolicy=n,n!=="predict"&&this._predictiveEcho?.clearPredictions()},_predictHookOnData(e){if(!(this._localEchoPolicy!=="predict"||!this._predictiveEcho))try{const t=window.CodemanTerminalInput.classifyPredictInput(e);t==="char"?this._predictiveEcho.predictChar(e):t==="backspace"?this._predictiveEcho.predictBackspace():this._predictiveEcho.clearPredictions()}catch{}},_handleCjkInput(e){if(!this.activeSessionId){_crashDiag.log(`CJK send DROP no-session len=${e.length}`);return}typeof KeyboardAccessoryBar<"u"&&KeyboardAccessoryBar.isCtrlArmed?.()&&(e=KeyboardAccessoryBar.consumeCtrl(e)),this._localEchoPolicy==="predict"&&this._predictiveEcho?.clearPredictions(),_crashDiag.log(`CJK send\u2192${this.activeSessionId.slice(0,8)} len=${e.length}`),this._sendInputAsync(this.activeSessionId,e)},flushPendingWrites(){if(this.pendingWrites.length===0||!this.terminal)return;const e=performance.now(),t=this.pendingWrites.join("");this.pendingWrites=[];const i=t.length;i>16384&&_crashDiag.log(`FLUSH: ${(i/1024).toFixed(0)}KB`);const n=(this.activeSessionId&&this.sessions?this.sessions.get(this.activeSessionId):null)?.mode==="codex"?32768:65536;let o=!1;const r=this.terminal.buffer?.active&&!this.isTerminalAtBottom()?this.terminal.buffer.active.viewportY:null;i<=n?this.terminal.write(t):(this.terminal.write(t.slice(0,n)),this.pendingWrites.push(t.slice(n)),o=!0,this._scheduleTerminalWriteFlush()),r!==null&&this.terminal.buffer?.active?.viewportY!==r&&typeof this.terminal.scrollToLine=="function"&&this.terminal.scrollToLine(r);const a=o?n:i,h=performance.now()-e;if((h>100||o)&&console.warn(`[CRASH-DIAG] flushPendingWrites: ${h.toFixed(0)}ms, ${(a/1024).toFixed(0)}KB written${o?", rest deferred":""} (total ${(i/1024).toFixed(0)}KB)`),this._wasAtBottomBeforeWrite&&!this._hasRecentUserScrollUp()&&this.terminal.scrollToBottom(),this._localEchoOverlay?.hasPending&&this._localEchoOverlay.rerender(),this._tabCompletionSessionId&&this._tabCompletionSessionId===this.activeSessionId&&this._localEchoOverlay&&!this._localEchoOverlay.pendingText){const d=this._localEchoOverlay,c=this;this.terminal.write("",()=>{if(!c._tabCompletionSessionId)return;d.resetBufferDetection();const u=d.detectBufferText();u?u===c._tabCompletionBaseText?(d.undoDetection(),c._tabCompletionRetries=(c._tabCompletionRetries||0)+1,c._tabCompletionRetries>60&&(c._tabCompletionSessionId=null,c._tabCompletionRetries=0)):(c._tabCompletionSessionId=null,c._tabCompletionRetries=0,c._tabCompletionBaseText=null,c._tabCompletionFallback&&(clearTimeout(c._tabCompletionFallback),c._tabCompletionFallback=null),d.rerender()):(c._tabCompletionRetries=(c._tabCompletionRetries||0)+1,c._tabCompletionRetries>60&&(c._tabCompletionSessionId=null,c._tabCompletionRetries=0))})}},_safeYield(e){let t=!1;const i=()=>{t||(t=!0,e())};requestAnimationFrame(i),setTimeout(i,50),this._workerYield(i)},_workerYield(e){try{if(this._yieldWorker===void 0){const t="onmessage=()=>setTimeout(()=>postMessage(0),0);",i=new Blob([t],{type:"application/javascript"}),s=URL.createObjectURL(i);this._yieldWorker=new Worker(s),URL.revokeObjectURL(s),this._yieldQueue=[],this._yieldWorker.onmessage=()=>{const n=this._yieldQueue.shift();n&&n()}}if(!this._yieldWorker)return;this._yieldQueue.push(e),this._yieldWorker.postMessage(0)}catch{this._yieldWorker=null}},scrollToLastNonEmptyLine(){if(!this.terminal?.buffer?.active){this.terminal?.scrollToBottom?.();return}const e=this.terminal.buffer.active,t=e.length;let i=-1;for(let s=t-1;s>=0;s--)if(e.getLine(s)?.translateToString(!0).trim()){i=s;break}if(i>=0&&typeof this.terminal.scrollToLine=="function"){let s=Math.max(0,i-this.terminal.rows+2);const n=Math.max(0,i);for(;s<n&&!e.getLine(s)?.translateToString(!0).trim();)s++;this.terminal.scrollToLine(s)}else this.terminal.scrollToBottom()},chunkedTerminalWrite(e,t=TERMINAL_CHUNK_SIZE,i){const s=++this._chunkedWriteGen,n=this._beginBufferLoad(i);return new Promise(o=>{const r=(y=this._chunkedWriteGen===s)=>({parsedAt:performance.now(),bufferLength:this.terminal?.buffer?.active?.length??0,completed:y});if(!e||e.length===0){this._finishBufferLoad(n),o(r());return}const a=e.replace(DEC_SYNC_STRIP_RE,"");if(a.length<=t){this.terminal.write(a,()=>o(r())),this._finishBufferLoad(n);return}let h=0;const d=performance.now();let c=0;const u=()=>{if(this._chunkedWriteGen!==s){o(r(!1));return}const y=a.slice(h,h+t);if(h+=y.length,c++,this.terminal.write(y),h>=a.length){this.terminal.write("",()=>{const I=r(),v=I.parsedAt-d;console.log(`[CRASH-DIAG] chunkedTerminalWrite complete: ${a.length} bytes in ${c} chunks, ${v.toFixed(0)}ms parsed`),o(I)}),this._finishBufferLoad(n);return}this._safeYield(u)};this._safeYield(u)})},_beginBufferLoad(e){this._bufferLoadSeq===void 0&&(this._bufferLoadSeq=0);const t=e===void 0?`buffer-${++this._bufferLoadSeq}`:e;return this._bufferLoadOwner=t,this._isLoadingBuffer=!0,this._loadBufferQueue=[],t},_finishBufferLoad(e,t){if(e!==void 0&&this._bufferLoadOwner!==e)return!1;const i=this._loadBufferQueue;if(this._isLoadingBuffer=!1,this._loadBufferQueue=null,this._bufferLoadOwner=null,t?.flushQueued&&i&&i.length)for(const s of i)this.batchTerminalWrite(s);return!0},clearTerminal(){this.terminal.clear()},insertTerminalText(e){!this.activeSessionId||!e||(this._localEchoPolicy==="predict"&&this._predictiveEcho?.clearPredictions(),this._localEchoEnabled&&this._localEchoOverlay&&!this._echoPassthroughSessions?.has(this.activeSessionId)?this._localEchoOverlay.appendText(e):this.sendInput(e).catch(()=>{}),this.terminal?.focus())},clearTerminalInput(){if(this.activeSessionId){if(typeof CjkInput<"u"&&CjkInput.clear(),this._inputFlushTimeout&&(clearTimeout(this._inputFlushTimeout),this._inputFlushTimeout=null),this._pendingInput="",this._localEchoPolicy==="predict"&&this._predictiveEcho?.clearPredictions(),this._localEchoEnabled&&this._localEchoOverlay){const e=this._localEchoOverlay.getFlushed?.()||{count:0,text:""};this._localEchoOverlay.clear(),this._localEchoOverlay.suppressBufferDetection(),this._flushedOffsets?.delete(this.activeSessionId),this._flushedTexts?.delete(this.activeSessionId),e.count>0&&this.sendInput("\x7F".repeat(e.count)).catch(()=>{})}else this.sendInput("").catch(()=>{});this.showToast?.("Input cleared","success"),this.terminal?.focus()}},async restoreTerminalSize(){if(!this.activeSessionId){this.showToast("No active session","warning");return}const e=this.getTerminalDimensions();if(!e){this.showToast("Could not determine terminal size","error");return}try{await this.sendResize(this.activeSessionId,{force:!0}),this.showToast(`Terminal restored to ${e.cols}x${e.rows}`,"success")}catch(t){console.error("Failed to restore terminal size:",t),this.showToast("Failed to restore terminal size","error")}},sendPendingCtrlL(e){},shouldCopyTerminalSelectionFromShortcut(e){if(!e||e.type!=="keydown"||!e.ctrlKey&&!e.metaKey&&!e.altKey)return!1;const i=typeof this.getShortcutRegistry=="function"&&typeof this.matchesShortcutEvent=="function"?this.getShortcutRegistry().find(s=>s.id==="copy-selection"):null;return i?!i.disabled&&this.matchesShortcutEvent(e,i):!e.altKey&&(e.key||"").toLowerCase()==="c"},async copyTerminalSelection(e){const t=e??(this.terminal.hasSelection?.()?this.terminal.getSelection():"");if(!t)return!1;const i=await this._copyText(t);return i?(this.terminal.clearSelection?.(),this.showToast("Copied to clipboard","success")):this.showToast("Failed to copy","error"),this.terminal.focus(),i},_autoCopySelectionEnabled(){try{return this.loadAppSettingsFromStorage?.()?.autoCopySelection===!0}catch{return!1}},async _flushAutoCopySelection(){const e=window.CodemanAutoCopy?.decide;if(!e||!this.terminal)return;const t=this.terminal.hasSelection?.()?this.terminal.getSelection():"",i=e({enabled:this._autoCopySelectionEnabled(),text:t,lastCopied:this._autoCopyLastText,pending:!!this._autoCopyPending});if(this._autoCopyPending=!1,i==="skip")return;if(i==="too-large"){this._autoCopyNotify("Selection too large to copy automatically. Press Ctrl+C.","warning");return}this._autoCopyLastText=t;const s=document.activeElement,n=await this._copyText(t);if(s&&s!==document.activeElement&&s.isConnected&&typeof s.focus=="function")try{s.focus()}catch{}if(!n){this._autoCopyLastText="",this._autoCopyNotify("Auto Copy failed: the browser blocked clipboard access","error");return}this._autoCopyHintShown||(this._autoCopyHintShown=!0,this.showToast("Auto Copy: selection copied","success"))},_autoCopyNotify(e,t){const i=Date.now(),s=this._autoCopyNotifiedAt;s!==void 0&&i-s<1e4||(this._autoCopyNotifiedAt=i,this.showToast(e,t))},_syncMobileHelperTextareaToCursor(){if(!(!MobileDetection.isTouchDevice()||!this.terminal?.element))try{const e=this.terminal.element,t=this.terminal.element.querySelector(".xterm-cursor"),i=this.terminal.element.querySelector(".xterm-screen");if(!(e instanceof HTMLElement)||!(t instanceof HTMLElement)||!(i instanceof HTMLElement))return;const s=t.getBoundingClientRect(),n=i.getBoundingClientRect();if(!s.width&&!s.height)return;const o=Math.max(0,Math.round(s.left-n.left)),r=Math.max(0,Math.round(s.top-n.top));e.style.setProperty("--xterm-helper-left",`${o}px`),e.style.setProperty("--xterm-helper-top",`${r}px`)}catch{}},_isMobileTerminalInputFocused(){const e=document.activeElement;return e===this.terminal?.textarea||e?.classList?.contains("xterm-helper-textarea")||e?.id==="cjkInput"},_classifyMobileTerminalTap(e,t){if(!this._terminalViewportAtBottom())return"history";const i=this._clientPointToCell(e,t);if(!i||!this.terminal)return"input";const s=this.terminal.modes?.mouseTrackingMode;if(!(!!s&&s!=="none")&&!this._shouldReportMouseToCli())return"input";const o=this.terminal.buffer?.active;if(!o?.getLine)return"input";const r=Math.max(1,this.terminal.rows||1),a=[],h=[];let d=!1;for(let m=0;m<r;m++){const S=o.getLine(o.viewportY+m),g=S?.translateToString?.(!0)||"";a.push(g),h.push(!!S?.isWrapped),g.trim()&&(d=!0)}if(!d)return"input";const c=Math.max(0,Math.min(r-1,o.cursorY||0)),u=this.sessions?.get(this.activeSessionId)?.mode||"claude";let y=-1,I=!1;if(u==="opencode")a[c]?.includes("\u2503")&&(y=c);else for(let m=r-1;m>=0;m--){const S=a[m].match(/^\s*[❯›]/);if(!S)continue;const g=a[m].slice(S[0].length).trim(),f=a.some((w,T)=>T!==m&&/^\s+\d+[.)]\s/.test(w));if(/^\d+[.)]\s/.test(g)&&f){I=!0;break}y=m;break}const v=i.row-1;let _=v;for(;_>0&&h[_];)_--;let l=v;for(;l+1<r&&h[l+1];)l++;const p=a.slice(_,l+1).join("");if(u==="claude"&&/\b(?:esc to interrupt|background)\b/i.test(p)||I)return"content";if(y>=0){const m=c>=y?c:y;if(v>=y&&v<=m)return"input"}else if(v===c||v>=Math.max(0,r-window.CodemanTerminalInput.TUI_PROMPT_DEFAULT_ROWS_FROM_BOTTOM))return"input";return"content"},_blurMobileTerminalInput(){const e=document.activeElement;(e===this.terminal?.textarea||e?.classList?.contains("xterm-helper-textarea")||e?.id==="cjkInput")&&e.blur?.()},_installMobileKeyboardDismiss(){if(this._mobileKeyboardDismissHandler)return;let e=0,t=0,i=!1;this._mobileKeyboardDismissStart=s=>{if(s.touches.length!==1){i=!0;return}e=s.touches[0].clientX,t=s.touches[0].clientY,i=!1},this._mobileKeyboardDismissMove=s=>{if(i||!s.touches.length)return;const n=s.touches[0].clientX-e,o=s.touches[0].clientY-t,r=window.CodemanTerminalInput.MOBILE_KEYBOARD_DISMISS_TAP_SLOP;(Math.abs(n)>r||Math.abs(o)>r)&&(i=!0)},this._mobileKeyboardDismissHandler=s=>{if(i||!this._isMobileTerminalInputFocused())return;const n=s.target;!n||typeof n.closest!="function"||n.closest("#terminalContainer")||n.closest(window.CodemanTerminalInput.MOBILE_KEYBOARD_DISMISS_EXEMPT_SELECTOR)||this._blurMobileTerminalInput()},document.addEventListener("touchstart",this._mobileKeyboardDismissStart,{passive:!0}),document.addEventListener("touchmove",this._mobileKeyboardDismissMove,{passive:!0}),document.addEventListener("touchend",this._mobileKeyboardDismissHandler,{passive:!0})},_isActionableMobileTerminalTap(e,t){const i=this._clientPointToCell(e,t),s=this.terminal?.buffer?.active;if(!i||!s?.getLine)return!1;const n=Math.max(1,this.terminal.rows||1),o=[],r=[];for(let l=0;l<n;l++){const p=s.getLine(s.viewportY+l);o.push(p?.translateToString?.(!0)||""),r.push(!!p?.isWrapped)}const a=i.row-1;let h=a;for(;h>0&&r[h];)h--;let d=a;for(;d+1<n&&r[d+1];)d++;const c=o.slice(h,d+1).join(""),u=/\b(?:ctrl\+\w+|shift\+\w+|esc|enter|tab|tap)\s+to\s+(?:expand|collapse|view|open|interrupt|see)\b/i,y=Math.max(0,h-1),I=Math.min(n-1,d+1);for(let l=y;l<=I;l++)if(u.test(o[l]))return!0;const v=o.some(l=>/^\s*[❯›]\s+\d+[.)]\s/.test(l)),_=o.some(l=>/^\s+\d+[.)]\s/.test(l));return v&&_&&/^\s*(?:[❯›]\s*)?\d+[.)]\s/.test(c)},_focusMobileTerminalInput(){this._syncMobileHelperTextareaToCursor();const e=document.getElementById("cjkInput");e?.classList.contains("cjk-input-visible")?e.focus():this.terminal?.focus()},_handleMobileTerminalTap(e,t,i=null){if(!e||!this.terminal)return null;if(this._touchSelectionActive)return this._extendTouchSelection(e.clientX,e.clientY),"select";const s=i??this._classifyMobileTerminalTap(e.clientX,e.clientY),n=this._isActionableMobileTerminalTap(e.clientX,e.clientY);if(!n&&!this._tapIsOnCaretLine(e.clientX,e.clientY)&&this._activateTerminalLinkAtPoint(e.clientX,e.clientY))return"link";if(s==="history")return this._focusMobileTerminalInput(),s;const o=this.terminal.modes?.mouseTrackingMode,r=!!o&&o!=="none",a=s==="content"||t;return a&&r?this._dispatchSyntheticTerminalClick(e.clientX,e.clientY):a&&this._shouldReportMouseToCli()&&this._sendSyntheticSgrTap(e.clientX,e.clientY),s==="content"&&n?this._blurMobileTerminalInput():s==="content"&&t?this._blurMobileTerminalInput():this._focusMobileTerminalInput(),s},_dispatchSyntheticTerminalClick(e,t){const i=this.terminal?.element;if(!i||!Number.isFinite(e)||!Number.isFinite(t))return;const s={bubbles:!0,cancelable:!0,view:window,clientX:e,clientY:t,screenX:e,screenY:t,button:0,detail:1};try{i.dispatchEvent(new MouseEvent("mousedown",{...s,buttons:1})),i.dispatchEvent(new MouseEvent("mouseup",{...s,buttons:0}))}catch{}},_shouldReportMouseToCli(){const e=this.sessions?.get(this.activeSessionId),t=e?.mode||"claude";return t!=="claude"&&t!=="codex"&&t!=="gemini"?!1:e?.cliMouseTracking===!0},_terminalViewportAtBottom(){const e=this.terminal?.buffer?.active;return!e||e.viewportY>=e.baseY},_clientPointToCell(e,t){if(!this.terminal||!Number.isFinite(e)||!Number.isFinite(t))return null;const i=this.terminal.element?.querySelector(".xterm-screen"),s=this.terminal._core?._renderService?.dimensions?.css?.cell;if(!i||!s?.width||!s?.height)return null;const n=i.getBoundingClientRect(),o=Math.max(1,Math.min(this.terminal.cols,Math.floor((e-n.left)/s.width)+1)),r=Math.max(1,Math.min(this.terminal.rows,Math.floor((t-n.top)/s.height)+1));return{col:o,row:r}},_sendSyntheticSgrTap(e,t){if(!this.activeSessionId||!this._terminalViewportAtBottom())return;const i=this._clientPointToCell(e,t);i&&this._sendInputAsync(this.activeSessionId,`\x1B[<0;${i.col};${i.row}M\x1B[<0;${i.col};${i.row}m`)},_cliVersionAtLeast(e,t){if(typeof e!="string")return!1;const i=e.trim().replace(/^v/,"").split(".").map(Number);if(i.length!==3||i.some(n=>!Number.isFinite(n)))return!1;const s=t.split(".").map(Number);for(let n=0;n<3;n++)if(i[n]!==s[n])return i[n]>s[n];return!0},_wheelScrollLines(e){const t=this._wheelScrollLinesFloat(e);return t?Math.round(t)||(t>0?1:-1):0},_wheelScrollLinesFloat(e){const t=e.shiftKey&&Math.abs(e.deltaX)>Math.abs(e.deltaY)?e.deltaX:e.deltaY;return t?e.deltaMode===1?t:e.deltaMode===2?t*(this.terminal?.rows||24):t/25:0},_shouldForwardWheelToApp(e){if(e.shiftKey||this.loadAppSettingsFromStorage?.()?.terminalWheelLocalScrollback)return!1;const t=this.terminal?.modes?.mouseTrackingMode;if(t&&t!=="none")return!1;const i=this.sessions?.get(this.activeSessionId);return!((i?.mode||"claude")!=="claude"||!this._cliVersionAtLeast(i?.cliVersion,"2.1.187"))},_sendSyntheticSgrWheel(e,t,i){if(!this.activeSessionId||!i)return;const s=this._clientPointToCell(e,t);if(!s)return;const n=i<0?64:65,o=Math.min(Math.abs(i),5);this._queueScrollBytes(`\x1B[<${n};${s.col};${s.row}M`.repeat(o))},_queueScrollBytes(e){if(!e||!this.activeSessionId)return;const t=this._wheelSgrQueue||"";t.length>512||(this._wheelSgrQueue=t+e,!this._wheelSgrFlushTimer&&(this._wheelSgrFlushTimer=setTimeout(()=>this._flushWheelSgrQueue(),40)))},_localScrollbackIsHollow(){if((this.sessions?.get(this.activeSessionId)?.mode||"claude")!=="claude")return!1;const t=this.terminal?.buffer?.active;return!t||t.type==="alternate"?!1:(t.baseY||0)===0},_maybePageCliTranscript(e,t){if(!t||e?.shiftKey||!this.activeSessionId||!this._localScrollbackIsHollow())return!1;this._pageKeySession!==this.activeSessionId&&(this._pageKeySession=this.activeSessionId,this._pageKeyPending=0);const i=window.CodemanTerminalInput,s=Math.max(2,Math.round((this.terminal?.rows||24)*i.PAGE_KEY_SCREEN_FRACTION)),n=(this._pageKeyPending||0)+t,o=Math.trunc(n/s);if(this._pageKeyPending=n-o*s,o){const r=o<0?i.KEY_PAGE_UP:i.KEY_PAGE_DOWN;this._queueScrollBytes(r.repeat(Math.min(Math.abs(o),i.PAGE_KEY_MAX_PER_BATCH)))}return this._logScrollRouting("page-keys"),!0},_logScrollRouting(e){const t=this.activeSessionId||"(none)",i=this.sessions?.get(t),s=!!this.loadAppSettingsFromStorage?.()?.terminalWheelLocalScrollback,n=this.terminal?.modes?.mouseTrackingMode||"none",o=this.terminal?.buffer?.active?.baseY??-1,r=`${e}|${i?.mode}|${i?.cliVersion}|${s}|${n}|${o>0}`;this._scrollRoutingLogged||(this._scrollRoutingLogged=new Map),this._scrollRoutingLogged.get(t)!==r&&(this._scrollRoutingLogged.set(t,r),console.log(`[scroll] ${t} \u2192 ${e} (mode=${i?.mode||"?"}, cliVersion=${i?.cliVersion||"unknown"}, localScrollbackOptOut=${s}, mouseTracking=${n}, localScrollbackRows=${o})`))},_flushWheelSgrQueue(){this._wheelSgrFlushTimer=null;const e=this._wheelSgrQueue;this._wheelSgrQueue="",e&&this.activeSessionId&&this._sendInputEphemeral(this.activeSessionId,e)},_handleDesktopTerminalClick(e){if(!this.terminal||!e?.isTrusted||e.button!==0||e.detail!==1||e.shiftKey||e.altKey||e.ctrlKey||e.metaKey)return;const t=this.terminal.modes?.mouseTrackingMode;t&&t!=="none"||this._shouldReportMouseToCli()&&(this.terminal.hasSelection?.()||this._linkHovered||performance.now()<=(this._trustedTapMouseSuppressUntil||0)||e.target?.closest?.(".xterm-screen")&&this._sendSyntheticSgrTap(e.clientX,e.clientY))},_installMobileTapMouseGuard(){const e=this.terminal?.element;if(!e||e._codemanTapMouseGuardInstalled||typeof MobileDetection<"u"&&MobileDetection.isTouchDevice&&!MobileDetection.isTouchDevice())return;e._codemanTapMouseGuardInstalled=!0;const t=i=>{const s=this._trustedTapMouseSuppressUntil||0;!i.isTrusted||performance.now()>s||(i.preventDefault(),i.stopImmediatePropagation())};e.addEventListener("mousedown",t,!0),e.addEventListener("mouseup",t,!0)},_suppressTrustedTapMouseEvents(){const e=window.CodemanTerminalInput?.TOUCH_COMPAT_MOUSE_SUPPRESS_MS||450;this._trustedTapMouseSuppressUntil=performance.now()+e},increaseFontSize(){const e=this.terminal.options.fontSize||14;this.setFontSize(Math.min(e+2,24))},decreaseFontSize(){const e=this.terminal.options.fontSize||14;this.setFontSize(Math.max(e-2,10))},setFontSize(e){this.terminal.options.fontSize=e,document.getElementById("fontSizeDisplay").textContent=e,this.fitAddon.fit(),localStorage.setItem("codeman-font-size",e),this._localEchoOverlay?.refreshFont(),this._predictiveEcho?.refreshFont()},applyTerminalFontFamily(e){const t=window.CodemanTerminalFont.resolve(e);!this.terminal||this.terminal.options.fontFamily===t||(this.terminal.options.fontFamily=t,this.fitAddon?.fit(),this._localEchoOverlay?.refreshFont(),this._predictiveEcho?.refreshFont())},loadFontSize(){const e=localStorage.getItem("codeman-font-size");if(e){const t=parseInt(e,10);t>=10&&t<=24&&(this.terminal.options.fontSize=t,document.getElementById("fontSizeDisplay").textContent=t)}},getTerminalDimensions(){const i=this.fitAddon?.proposeDimensions();return i?{cols:Math.max(i.cols,40),rows:Math.max(i.rows,10)}:null},async sendResize(e,t={}){this.fitAddon&&this.fitAddon.fit();const i=this.getTerminalDimensions();if(!i)return!1;const s=this._lastResizeDims,n=!s||s.cols!==i.cols||s.rows!==i.rows;this._lastResizeDims={cols:i.cols,rows:i.rows};const o=typeof MobileDetection<"u"&&MobileDetection.getDeviceType?MobileDetection.getDeviceType():window.innerWidth<430?"mobile":window.innerWidth<768?"tablet":"desktop";if(!t.forceHttp&&this._wsReady&&this._wsSessionId===e)try{const a={t:"z",c:i.cols,r:i.rows,v:o};return t.force&&(a.f=!0),this._ws.send(JSON.stringify(a)),n}catch{}const r={...i,viewportType:o};return t.force&&(r.force=!0),await fetch(`/api/sessions/${e}/resize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)}),n},async sendInput(e){!this.activeSessionId||!e||this._sendInputAsync(this.activeSessionId,e,{useMux:!0})},toggleDirInput(){const e=document.querySelector("#dirDisplay").parentElement,t=document.getElementById("dirInput");t.classList.contains("hidden")&&(t.classList.remove("hidden"),e.style.display="none",t.focus())},hideDirInput(){const e=document.querySelector("#dirDisplay").parentElement,t=document.getElementById("dirInput");setTimeout(()=>{t.classList.add("hidden"),e.style.display="";const i=t.value.trim();document.getElementById("dirDisplay").textContent=i||"No directory"},100)},applyTerminalSkin(e){const t={...window.CODEMAN_XTERM_THEMES[e]||window.CODEMAN_XTERM_THEMES["daylight-blue"]},i=window.codemanCurrentSkinIsLight(e)?4.5:1;if(this.terminal){this.terminal.options.minimumContrastRatio=i,this.terminal.options.theme=t,this._localEchoOverlay?.refreshFont(),this._predictiveEcho?.refreshFont();try{this.terminal.refresh(0,this.terminal.rows-1)}catch{}}if(this.teammateTerminals){for(const[,s]of this.teammateTerminals)if(s&&s.terminal){s.terminal.options.minimumContrastRatio=i,s.terminal.options.theme={...t};try{s.terminal.refresh(0,s.terminal.rows-1)}catch{}}}}}),(function(e){const s={session:"Sessions",event:"Events",file:"Files"};function n(o){if(!Number.isFinite(o))return"";const r=new Date(o);return r.toLocaleDateString("en",{month:"short",day:"numeric"})+" "+r.toLocaleTimeString("en",{hour:"2-digit",minute:"2-digit",hour12:!1})}e.CodemanSearch={SEARCH_DEBOUNCE_MS:250,SEARCH_LIMIT:60,SOURCE_LABELS:s,formatSearchTime:n}})(window),Object.assign(CodemanApp.prototype,{initSearchPanel(){const e=document.getElementById("searchInput");if(!e||this._searchPanelWired){this._searchPanelWired&&this._populateSearchCaseFilter();return}this._searchPanelWired=!0,this._searchTypes=new Set(["session","event","file"]),this._searchSecondary={caseLabel:"",status:"",days:""},this._searchDebounceTimer=null,this._searchSeq=0,this._searchLastData=null;const t=document.getElementById("searchClearBtn"),i=document.getElementById("searchResults");e.addEventListener("input",()=>{t&&(t.hidden=e.value.length===0),this._scheduleSearch()}),e.addEventListener("keydown",r=>{r.key==="Escape"&&e.value&&(r.stopPropagation(),this._clearSearch())}),t&&t.addEventListener("click",()=>this._clearSearch()),document.querySelectorAll("#searchFilters .search-filter-chip").forEach(r=>{r.addEventListener("click",()=>{const a=r.dataset.typeFilter;this._searchTypes.has(a)&&this._searchTypes.size===1||(this._searchTypes.has(a)?(this._searchTypes.delete(a),r.classList.remove("active")):(this._searchTypes.add(a),r.classList.add("active")),this._runSearch())})});const s=document.getElementById("searchCaseFilter"),n=document.getElementById("searchStatusFilter"),o=document.getElementById("searchDateFilter");s&&s.addEventListener("change",()=>{this._searchSecondary.caseLabel=s.value,this._renderSearch(this._searchLastData)}),n&&n.addEventListener("change",()=>{this._searchSecondary.status=n.value,this._renderSearch(this._searchLastData)}),o&&o.addEventListener("change",()=>{this._searchSecondary.days=o.value,this._renderSearch(this._searchLastData)}),this._populateSearchCaseFilter(),i&&(i.hidden=!0)},_populateSearchCaseFilter(){const e=document.getElementById("searchCaseFilter");if(!e)return;const t=Array.isArray(this.cases)?this.cases:[],i=Array.from(new Set(t.map(o=>o&&o.name).filter(Boolean))).sort(),s=e.value;e.innerHTML="";const n=document.createElement("option");n.value="",n.textContent="All cases",e.appendChild(n);for(const o of i){const r=document.createElement("option");r.value=o,r.textContent="#"+o,e.appendChild(r)}s&&i.includes(s)&&(e.value=s)},_scheduleSearch(){clearTimeout(this._searchDebounceTimer),this._searchDebounceTimer=setTimeout(()=>this._runSearch(),window.CodemanSearch.SEARCH_DEBOUNCE_MS)},_clearSearch(){const e=document.getElementById("searchInput"),t=document.getElementById("searchClearBtn");e&&(e.value=""),t&&(t.hidden=!0),this._searchLastData=null,this._renderSearch(null)},async _runSearch(){const e=document.getElementById("searchInput");if(!e)return;const t=e.value.trim();if(t.length===0){this._searchLastData=null,this._renderSearch(null);return}const i=Array.from(this._searchTypes),s=new URLSearchParams;s.set("q",t.slice(0,200)),i.length>0&&i.length<3&&s.set("types",i.join(",")),s.set("limit",String(window.CodemanSearch.SEARCH_LIMIT));const n=++this._searchSeq,o=await this._apiJson("/api/search?"+s.toString());n===this._searchSeq&&(o?this._searchLastData=o:this._searchLastData={query:t,groups:[],totalResults:0,truncated:!1,_error:!0},this._renderSearch(this._searchLastData))},_applySecondaryFilters(e){const{caseLabel:t,status:i,days:s}=this._searchSecondary;let n=e;if(t){const o="#"+t;n=n.filter(r=>(r.sessionName||"").includes(o)||r.sessionName===t)}if(i){const o=new Set((this.sessionOrder||[]).concat(Object.keys(this.sessions||{})));n=n.filter(r=>{const a=o.has(r.sessionId);return i==="active"?a:!a})}if(s){const o=Date.now()-Number(s)*24*60*60*1e3;n=n.filter(r=>Number.isFinite(r.timestamp)&&r.timestamp>=o)}return n},_renderSearch(e){const t=document.getElementById("searchResults"),i=document.getElementById("historyHeader")||document.getElementById("historyTitle"),s=document.getElementById("historyList");if(!t)return;const n=!!e;if(i&&(i.style.display=n?"none":""),s&&(s.style.display=n?"none":""),t.innerHTML="",!e){t.hidden=!0;return}if(t.hidden=!1,e._error){const a=document.createElement("div");a.className="search-empty",a.textContent="Search unavailable \u2014 check the query and try again.",t.appendChild(a);return}const o=(e.groups||[]).map(a=>({type:a.type,results:this._applySecondaryFilters(a.results||[])})).filter(a=>a.results.length>0);if(o.reduce((a,h)=>a+h.results.length,0)===0){const a=document.createElement("div");a.className="search-empty",a.textContent='No results for "'+(e.query||"")+'"',t.appendChild(a);return}for(const a of o){const h=document.createElement("div");h.className="search-group-header";const d=document.createElement("span");d.className="search-group-label",d.textContent=window.CodemanSearch.SOURCE_LABELS[a.type]||a.type;const c=document.createElement("span");c.className="search-group-count",c.textContent=String(a.results.length),h.append(d,c),t.appendChild(h);for(const u of a.results)t.appendChild(this._buildSearchResultCard(u))}if(e.truncated){const a=document.createElement("div");a.className="search-truncated",a.textContent="Showing the top matches \u2014 refine your search to narrow results.",t.appendChild(a)}},_buildSearchResultCard(e){const t=document.createElement("div");t.className="search-result-card",t.dataset.type=e.type,t.tabIndex=0,t.setAttribute("role","button");const i=document.createElement("div");i.className="search-result-top";const s=e.jumpTo&&e.jumpTo.kind==="resume-session",n=document.createElement("span");n.className="search-result-badge search-badge-"+e.type+(s?" search-badge-past":""),n.textContent=s?"Resume":(window.CodemanSearch.SOURCE_LABELS[e.type]||e.type).replace(/s$/,"");const o=document.createElement("span");o.className="search-result-name",o.textContent=e.sessionName||e.sessionId||"(session)";const r=document.createElement("span");r.className="search-result-time",r.textContent=window.CodemanSearch.formatSearchTime(e.timestamp),i.append(n,o,r);const a=document.createElement("div");a.className="search-result-snippet",a.textContent=e.snippet||"",t.append(i,a);const h=()=>this._jumpToSearchResult(e);return t.addEventListener("click",h),t.addEventListener("keydown",d=>{(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),h())}),t},_jumpToSearchResult(e){const t=e&&e.jumpTo;if(t){if(t.kind==="resume-session"){this.resumeHistorySession(t.claudeSessionId||t.sessionId,t.workingDir||"",e.sessionName);return}typeof this.hideWelcome=="function"&&this.hideWelcome();try{t.kind==="run-summary"?this.openRunSummary(t.sessionId):t.kind==="file-preview"?this.openFilePreview(t.relativePath||"",t.sessionId,t.targetId||null):this.selectSession(t.sessionId)}catch(i){console.error("[search] jump failed",i)}}}});