aicodeman 1.9.6 → 1.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/dependency-registry.d.ts.map +1 -1
- package/dist/config/dependency-registry.js +8 -0
- package/dist/config/dependency-registry.js.map +1 -1
- package/dist/docker-hosts.d.ts.map +1 -1
- package/dist/docker-hosts.js +1 -0
- package/dist/docker-hosts.js.map +1 -1
- package/dist/mux-interface.d.ts +3 -1
- package/dist/mux-interface.d.ts.map +1 -1
- package/dist/remote-hosts.d.ts.map +1 -1
- package/dist/remote-hosts.js +1 -0
- package/dist/remote-hosts.js.map +1 -1
- package/dist/session.d.ts +6 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +18 -3
- package/dist/session.js.map +1 -1
- package/dist/tmux-manager.d.ts +2 -1
- package/dist/tmux-manager.d.ts.map +1 -1
- package/dist/tmux-manager.js +46 -5
- package/dist/tmux-manager.js.map +1 -1
- package/dist/types/session.d.ts +16 -4
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js +2 -1
- package/dist/types/session.js.map +1 -1
- package/dist/utils/antigravity-cli-resolver.d.ts +20 -0
- package/dist/utils/antigravity-cli-resolver.d.ts.map +1 -0
- package/dist/utils/antigravity-cli-resolver.js +60 -0
- package/dist/utils/antigravity-cli-resolver.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/web/public/admin-ui.js.gz +0 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/{app.adc992cd.js → app.5805dde4.js} +6 -6
- package/dist/web/public/app.5805dde4.js.br +0 -0
- package/dist/web/public/app.5805dde4.js.gz +0 -0
- package/dist/web/public/constants.e7175b95.js.gz +0 -0
- package/dist/web/public/cron-ui.js.gz +0 -0
- package/dist/web/public/entrance-animations.js +754 -0
- package/dist/web/public/entrance-animations.js.br +0 -0
- package/dist/web/public/entrance-animations.js.gz +0 -0
- package/dist/web/public/i18n.04d07c98.js +1 -0
- package/dist/web/public/i18n.04d07c98.js.br +0 -0
- package/dist/web/public/i18n.04d07c98.js.gz +0 -0
- package/dist/web/public/image-input.ee16ad88.js.gz +0 -0
- package/dist/web/public/index.html +28 -9
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.63794d0b.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.9936227d.js.gz +0 -0
- package/dist/web/public/mobile-handlers.bc2b8c1d.js.gz +0 -0
- package/dist/web/public/mobile.f8466b0a.css +1 -0
- package/dist/web/public/mobile.f8466b0a.css.br +0 -0
- package/dist/web/public/mobile.f8466b0a.css.gz +0 -0
- package/dist/web/public/notification-manager.5d229063.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/{panels-ui.3910e1e2.js → panels-ui.600881ae.js} +17 -17
- package/dist/web/public/panels-ui.600881ae.js.br +0 -0
- package/dist/web/public/panels-ui.600881ae.js.gz +0 -0
- package/dist/web/public/ralph-panel.6de2d0f8.js.gz +0 -0
- package/dist/web/public/ralph-wizard.13a1831e.js.gz +0 -0
- package/dist/web/public/respawn-ui.2d249da9.js.gz +0 -0
- package/dist/web/public/sanitize-html.bc7078d6.js.gz +0 -0
- package/dist/web/public/{session-ui.2d3541c6.js → session-ui.aab84498.js} +3 -3
- package/dist/web/public/session-ui.aab84498.js.br +0 -0
- package/dist/web/public/session-ui.aab84498.js.gz +0 -0
- package/dist/web/public/{settings-ui.08c08e71.js → settings-ui.1e126e75.js} +1 -1
- package/dist/web/public/settings-ui.1e126e75.js.br +0 -0
- package/dist/web/public/settings-ui.1e126e75.js.gz +0 -0
- package/dist/web/public/styles.7e638f69.css +1 -0
- package/dist/web/public/styles.7e638f69.css.br +0 -0
- package/dist/web/public/styles.7e638f69.css.gz +0 -0
- package/dist/web/public/{subagent-windows.69b60c35.js → subagent-windows.4cc8b005.js} +27 -3
- package/dist/web/public/subagent-windows.4cc8b005.js.br +0 -0
- package/dist/web/public/subagent-windows.4cc8b005.js.gz +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/terminal-ui.f3a51974.js.gz +0 -0
- package/dist/web/public/ultracode-panel.js.gz +0 -0
- package/dist/web/public/ultracode-windows.js +4 -0
- package/dist/web/public/ultracode-windows.js.br +0 -0
- package/dist/web/public/ultracode-windows.js.gz +0 -0
- package/dist/web/public/upload.html.gz +0 -0
- package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/voice-input.085e9e73.js.gz +0 -0
- package/dist/web/public/webview-tabs.js.gz +0 -0
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +59 -25
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/routes/system-routes.d.ts.map +1 -1
- package/dist/web/routes/system-routes.js +9 -1
- package/dist/web/routes/system-routes.js.map +1 -1
- package/dist/web/schemas.d.ts +16 -0
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +24 -5
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +1 -0
- package/dist/web/server.js.map +1 -1
- package/package.json +1 -1
- package/dist/web/public/app.adc992cd.js.br +0 -0
- package/dist/web/public/app.adc992cd.js.gz +0 -0
- package/dist/web/public/i18n.4dcf1b87.js +0 -1
- package/dist/web/public/i18n.4dcf1b87.js.br +0 -0
- package/dist/web/public/i18n.4dcf1b87.js.gz +0 -0
- package/dist/web/public/mobile.40e2d64e.css +0 -1
- package/dist/web/public/mobile.40e2d64e.css.br +0 -0
- package/dist/web/public/mobile.40e2d64e.css.gz +0 -0
- package/dist/web/public/panels-ui.3910e1e2.js.br +0 -0
- package/dist/web/public/panels-ui.3910e1e2.js.gz +0 -0
- package/dist/web/public/session-ui.2d3541c6.js.br +0 -0
- package/dist/web/public/session-ui.2d3541c6.js.gz +0 -0
- package/dist/web/public/settings-ui.08c08e71.js.br +0 -0
- package/dist/web/public/settings-ui.08c08e71.js.gz +0 -0
- package/dist/web/public/styles.30e64547.css +0 -1
- package/dist/web/public/styles.30e64547.css.br +0 -0
- package/dist/web/public/styles.30e64547.css.gz +0 -0
- package/dist/web/public/subagent-windows.69b60c35.js.br +0 -0
- package/dist/web/public/subagent-windows.69b60c35.js.gz +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";const AWAY_DIGEST_LAST_VIEWED_KEY="codeman-away-digest-last-viewed",AWAY_DIGEST_SECTIONS=[["needsAttention","Needs Attention"],["completed","Completed"],["stillRunning","Still Running"],["idle","Idle"],["informational","Informational"]];Object.assign(CodemanApp.prototype,{_addActivityEntry(e,t,s=50){const n=this.subagentActivity.get(e)||[];n.push(t),n.length>s&&n.shift(),this.subagentActivity.set(e,n)},_onTaskCreated(e){this.renderSessionTabs(),e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onTaskCompleted(e){this.renderSessionTabs(),e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onTaskFailed(e){this.renderSessionTabs(),e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onTaskUpdated(e){e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onMuxCreated(e){this.muxSessions.push(e),this.renderMuxSessions()},_onMuxKilled(e){this.muxSessions=this.muxSessions.filter(t=>t.sessionId!==e.sessionId),this.renderMuxSessions()},_onMuxDied(e){this.muxSessions=this.muxSessions.filter(t=>t.sessionId!==e.sessionId),this.renderMuxSessions(),this.showToast("Mux session died: "+this.getShortId(e.sessionId),"warning")},_onMuxStatsUpdated(e){this.muxSessions=e,document.getElementById("monitorPanel").classList.contains("open")&&this.renderMuxSessions()},_onRemoteSessionReconnected(e){const t=this.getShortId(e.sessionId);this.showToast(`Remote session ${t} reconnected`,"success")},_onRemoteReconnectExhausted(e){const t=e.sessionId,s=this.getShortId(t);this.showToast(`Remote session ${s} dropped \u2014 auto-reconnect gave up`,"error",{duration:15e3,action:{label:"Reconnect",onClick:()=>{this.sessions&&this.sessions.has(t)?this.selectSession(t,{forceReload:!0}):this.showToast("Session no longer available","warning")}}})},_onBashToolStart(e){this.handleBashToolStart(e.sessionId,e.tool)},_onBashToolEnd(e){this.handleBashToolEnd(e.sessionId,e.tool)},_onBashToolsUpdate(e){this.handleBashToolsUpdate(e.sessionId,e.tools)},_onSubagentDiscovered(e){this.subagents.set(e.agentId,e),this.subagentActivity.set(e.agentId,[]),this.subagentToolResults.delete(e.agentId),this.subagentWindows.has(e.agentId)&&this.forceCloseSubagentWindow(e.agentId),this.renderSubagentPanel(),this.findParentSessionForSubagent(e.agentId),requestAnimationFrame(()=>{this.updateConnectionLines()});const t=this.subagentParentMap.get(e.agentId);this._notifySession(t||e.sessionId,"info","subagent-spawn","Subagent Spawned",e.description||"New background agent started")},_onSubagentUpdated(e){const t=this.subagents.get(e.agentId);t?(Object.assign(t,e),this.subagents.set(e.agentId,t)):this.subagents.set(e.agentId,e),this.renderSubagentPanel(),this.subagentWindows.has(e.agentId)&&(this.renderSubagentWindowContent(e.agentId),this.updateSubagentWindowHeader(e.agentId))},_onSubagentToolCall(e){this._addActivityEntry(e.agentId,{type:"tool",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.renderSubagentPanel(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},_onSubagentProgress(e){this._addActivityEntry(e.agentId,{type:"progress",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},_onSubagentMessage(e){this._addActivityEntry(e.agentId,{type:"message",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},_onSubagentToolResult(e){this.subagentToolResults.has(e.agentId)||this.subagentToolResults.set(e.agentId,new Map);const t=this.subagentToolResults.get(e.agentId);if(t.set(e.toolUseId,e),t.size>50){const s=t.keys().next().value;t.delete(s)}this._addActivityEntry(e.agentId,{type:"tool_result",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},async _onSubagentCompleted(e){const t=this.subagents.get(e.agentId);if(t&&(t.status="completed",this.subagents.set(e.agentId,t)),this.renderSubagentPanel(),this.updateSubagentWindows(),this.subagentWindows.has(e.agentId)){const n=this.subagentWindows.get(e.agentId);n&&!n.minimized&&(await this.closeSubagentWindow(e.agentId),this.saveSubagentWindowStates())}const s=this.subagentParentMap.get(e.agentId);this._notifySession(s||t?.sessionId||e.sessionId,"info","subagent-complete","Subagent Completed",t?.description||e.description||"Background agent finished"),setTimeout(()=>{this.subagents.get(e.agentId)?.status==="completed"&&(this.subagentActivity.delete(e.agentId),this.subagentToolResults.delete(e.agentId))},300*1e3),setTimeout(()=>{this.subagents.get(e.agentId)?.status==="completed"&&!this.subagentWindows.has(e.agentId)&&(this.subagents.delete(e.agentId),this.subagentParentMap.delete(e.agentId))},1800*1e3)},_onImageDetected(e){console.log("[Image Detected]",e),this.openImagePopup(e)},shouldOpenCommandPaletteFromShortcut(e){if(!e||!e.ctrlKey&&!e.metaKey&&!e.altKey)return!1;const s=typeof this.getShortcutRegistry=="function"&&typeof this.matchesShortcutEvent=="function"?this.getShortcutRegistry().find(o=>o.id==="command-palette"):null;if(s){if(s.disabled||!this.matchesShortcutEvent(e,s))return!1}else if((e.key||"").toLowerCase()!=="k"&&e.code!=="KeyK"||e.shiftKey)return!1;const n=e.target;if(!n)return!0;const a=(n.tagName||"").toUpperCase(),i=typeof n.className=="string"?n.className:"";return n.classList?.contains?.("xterm-helper-textarea")||i.includes("xterm-helper-textarea")?!0:!(a==="INPUT"||a==="TEXTAREA"||a==="SELECT"||n.isContentEditable||typeof n.closest=="function"&&n.closest('[contenteditable="true"]'))},openCommandPalette(){const e=document.getElementById("commandPaletteModal"),t=document.getElementById("commandPaletteSearch");!e||!t||(this.commandPaletteActiveIndex=0,t.value="",e.classList.add("active"),this._wireCommandPalette(),this.renderCommandPalette(),t.focus(),t.select?.())},closeCommandPalette(){const e=document.getElementById("commandPaletteModal");e&&e.classList.remove("active")},_wireCommandPalette(){if(this._commandPaletteWired)return;this._commandPaletteWired=!0;const e=document.getElementById("commandPaletteModal"),t=document.getElementById("commandPaletteSearch"),s=document.getElementById("commandPaletteList");t?.addEventListener("input",()=>{this.commandPaletteActiveIndex=0,this.renderCommandPalette()}),t?.addEventListener("keydown",async n=>{if(n.key==="ArrowDown"){n.preventDefault(),this.moveCommandPaletteSelection(1);return}if(n.key==="ArrowUp"){n.preventDefault(),this.moveCommandPaletteSelection(-1);return}if(n.key==="Enter"){n.preventDefault(),n.stopPropagation(),await this.activateCommandPaletteItem();return}n.key==="Escape"&&(n.preventDefault(),this.closeCommandPalette())}),e?.addEventListener("keydown",n=>{n.key==="Escape"&&(n.preventDefault(),this.closeCommandPalette())}),s?.addEventListener?.("click",n=>{const a=n.target?.closest?.("[data-command-index]");a&&(this.commandPaletteActiveIndex=Number(a.dataset.commandIndex)||0,this.activateCommandPaletteItem())})},buildCommandPaletteItems(e=""){const t=e.trim().toLowerCase(),s=[...Array.isArray(this.sessionOrder)?this.sessionOrder:[],...Array.from(this.sessions?.keys?.()||[]).filter(i=>!this.sessionOrder?.includes?.(i))],n=new Set,a=[];for(const i of s){if(n.has(i))continue;n.add(i);const r=this.sessions?.get?.(i);if(!r)continue;const o=this.getSessionName?.(r)||r.name||r.title||i.slice(0,8),l=[r.workingDir,r.mode,r.status].filter(Boolean),d=[o,r.workingDir,r.mode,r.status,i].filter(Boolean).join(" ").toLowerCase();t&&!d.includes(t)||a.push({id:`session:${i}`,type:"session",sessionId:i,title:o,subtitle:l.join(" \xB7 ")})}return a.push(this._buildCommandPaletteNewSessionItem(e)),a.push({id:"browse-sessions",type:"browse-sessions",title:"Browse all sessions\u2026",subtitle:"Open Session Manager"}),a},_buildCommandPaletteNewSessionItem(e=""){const t=this.runMode||this._runMode||"claude",s={claude:"Claude",opencode:"OpenCode",codex:"Codex",gemini:"Gemini"},n=this._findCommandPaletteCaseMatch(e)||document.getElementById("quickStartCase")?.value||"testcase";return{id:"new-session",type:"new-session",caseName:n,title:"New session",subtitle:`Run ${s[t]||t} in ${n}`}},_findCommandPaletteCaseMatch(e=""){const t=e.trim().toLowerCase();if(!t||!Array.isArray(this.cases))return null;const s=i=>{const r=String(i?.name||"").trim();if(!r)return 0;const o=[r,i?.path,i?.casePath,i?.workingDir,i?.remote?.path,i?.remote?.hostId].filter(Boolean).join(" ").toLowerCase(),l=r.toLowerCase();return l===t?100:l.startsWith(t)?90:l.includes(t)?80:o.includes(t)?60:0};let n=null,a=0;for(const i of this.cases){const r=s(i);r>a&&(n=i,a=r)}return n?.name||null},renderCommandPalette(){const e=document.getElementById("commandPaletteSearch"),t=document.getElementById("commandPaletteList");if(!t)return;const s=e?.value||"",n=this.buildCommandPaletteItems(s);this.commandPaletteItems=n,this.commandPaletteActiveIndex=Math.max(0,Math.min(this.commandPaletteActiveIndex||0,n.length-1)),t.innerHTML=n.map((a,i)=>{const r=i===this.commandPaletteActiveIndex?" active":"",o=a.type==="new-session"?"+":a.type==="browse-sessions"?"\u2261":"\u203A",l=a.type==="browse-sessions"?" command-palette-item--browse":"";return`
|
|
1
|
+
"use strict";const AWAY_DIGEST_LAST_VIEWED_KEY="codeman-away-digest-last-viewed",AWAY_DIGEST_SECTIONS=[["needsAttention","Needs Attention"],["completed","Completed"],["stillRunning","Still Running"],["idle","Idle"],["informational","Informational"]];Object.assign(CodemanApp.prototype,{_addActivityEntry(e,t,s=50){const n=this.subagentActivity.get(e)||[];n.push(t),n.length>s&&n.shift(),this.subagentActivity.set(e,n)},_onTaskCreated(e){this.renderSessionTabs(),e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onTaskCompleted(e){this.renderSessionTabs(),e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onTaskFailed(e){this.renderSessionTabs(),e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onTaskUpdated(e){e.sessionId===this.activeSessionId&&this.renderTaskPanel()},_onMuxCreated(e){this.muxSessions.push(e),this.renderMuxSessions()},_onMuxKilled(e){this.muxSessions=this.muxSessions.filter(t=>t.sessionId!==e.sessionId),this.renderMuxSessions()},_onMuxDied(e){this.muxSessions=this.muxSessions.filter(t=>t.sessionId!==e.sessionId),this.renderMuxSessions(),this.showToast("Mux session died: "+this.getShortId(e.sessionId),"warning")},_onMuxStatsUpdated(e){this.muxSessions=e,document.getElementById("monitorPanel").classList.contains("open")&&this.renderMuxSessions()},_onRemoteSessionReconnected(e){const t=this.getShortId(e.sessionId);this.showToast(`Remote session ${t} reconnected`,"success")},_onRemoteReconnectExhausted(e){const t=e.sessionId,s=this.getShortId(t);this.showToast(`Remote session ${s} dropped \u2014 auto-reconnect gave up`,"error",{duration:15e3,action:{label:"Reconnect",onClick:()=>{this.sessions&&this.sessions.has(t)?this.selectSession(t,{forceReload:!0}):this.showToast("Session no longer available","warning")}}})},_onBashToolStart(e){this.handleBashToolStart(e.sessionId,e.tool)},_onBashToolEnd(e){this.handleBashToolEnd(e.sessionId,e.tool)},_onBashToolsUpdate(e){this.handleBashToolsUpdate(e.sessionId,e.tools)},_onSubagentDiscovered(e){this.subagents.set(e.agentId,e),this.subagentActivity.set(e.agentId,[]),this.subagentToolResults.delete(e.agentId),this.subagentWindows.has(e.agentId)&&this.forceCloseSubagentWindow(e.agentId),this.renderSubagentPanel(),this.findParentSessionForSubagent(e.agentId),requestAnimationFrame(()=>{this.updateConnectionLines()});const t=this.subagentParentMap.get(e.agentId);this._notifySession(t||e.sessionId,"info","subagent-spawn","Subagent Spawned",e.description||"New background agent started")},_onSubagentUpdated(e){const t=this.subagents.get(e.agentId);t?(Object.assign(t,e),this.subagents.set(e.agentId,t)):this.subagents.set(e.agentId,e),this.renderSubagentPanel(),this.subagentWindows.has(e.agentId)&&(this.renderSubagentWindowContent(e.agentId),this.updateSubagentWindowHeader(e.agentId))},_onSubagentToolCall(e){this._addActivityEntry(e.agentId,{type:"tool",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.renderSubagentPanel(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},_onSubagentProgress(e){this._addActivityEntry(e.agentId,{type:"progress",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},_onSubagentMessage(e){this._addActivityEntry(e.agentId,{type:"message",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},_onSubagentToolResult(e){this.subagentToolResults.has(e.agentId)||this.subagentToolResults.set(e.agentId,new Map);const t=this.subagentToolResults.get(e.agentId);if(t.set(e.toolUseId,e),t.size>50){const s=t.keys().next().value;t.delete(s)}this._addActivityEntry(e.agentId,{type:"tool_result",...e}),this.activeSubagentId===e.agentId&&this.renderSubagentDetail(),this.subagentWindows.has(e.agentId)&&this.scheduleSubagentWindowRender(e.agentId)},async _onSubagentCompleted(e){const t=this.subagents.get(e.agentId);if(t&&(t.status="completed",this.subagents.set(e.agentId,t)),this.renderSubagentPanel(),this.updateSubagentWindows(),this.subagentWindows.has(e.agentId)){const n=this.subagentWindows.get(e.agentId);n&&!n.minimized&&(await this.closeSubagentWindow(e.agentId),this.saveSubagentWindowStates())}const s=this.subagentParentMap.get(e.agentId);this._notifySession(s||t?.sessionId||e.sessionId,"info","subagent-complete","Subagent Completed",t?.description||e.description||"Background agent finished"),setTimeout(()=>{this.subagents.get(e.agentId)?.status==="completed"&&(this.subagentActivity.delete(e.agentId),this.subagentToolResults.delete(e.agentId))},300*1e3),setTimeout(()=>{this.subagents.get(e.agentId)?.status==="completed"&&!this.subagentWindows.has(e.agentId)&&(this.subagents.delete(e.agentId),this.subagentParentMap.delete(e.agentId))},1800*1e3)},_onImageDetected(e){console.log("[Image Detected]",e),this.openImagePopup(e)},shouldOpenCommandPaletteFromShortcut(e){if(!e||!e.ctrlKey&&!e.metaKey&&!e.altKey)return!1;const s=typeof this.getShortcutRegistry=="function"&&typeof this.matchesShortcutEvent=="function"?this.getShortcutRegistry().find(o=>o.id==="command-palette"):null;if(s){if(s.disabled||!this.matchesShortcutEvent(e,s))return!1}else if((e.key||"").toLowerCase()!=="k"&&e.code!=="KeyK"||e.shiftKey)return!1;const n=e.target;if(!n)return!0;const a=(n.tagName||"").toUpperCase(),i=typeof n.className=="string"?n.className:"";return n.classList?.contains?.("xterm-helper-textarea")||i.includes("xterm-helper-textarea")?!0:!(a==="INPUT"||a==="TEXTAREA"||a==="SELECT"||n.isContentEditable||typeof n.closest=="function"&&n.closest('[contenteditable="true"]'))},openCommandPalette(){const e=document.getElementById("commandPaletteModal"),t=document.getElementById("commandPaletteSearch");!e||!t||(this.commandPaletteActiveIndex=0,t.value="",e.classList.add("active"),this._wireCommandPalette(),this.renderCommandPalette(),t.focus(),t.select?.())},closeCommandPalette(){const e=document.getElementById("commandPaletteModal");e&&e.classList.remove("active")},_wireCommandPalette(){if(this._commandPaletteWired)return;this._commandPaletteWired=!0;const e=document.getElementById("commandPaletteModal"),t=document.getElementById("commandPaletteSearch"),s=document.getElementById("commandPaletteList");t?.addEventListener("input",()=>{this.commandPaletteActiveIndex=0,this.renderCommandPalette()}),t?.addEventListener("keydown",async n=>{if(n.key==="ArrowDown"){n.preventDefault(),this.moveCommandPaletteSelection(1);return}if(n.key==="ArrowUp"){n.preventDefault(),this.moveCommandPaletteSelection(-1);return}if(n.key==="Enter"){n.preventDefault(),n.stopPropagation(),await this.activateCommandPaletteItem();return}n.key==="Escape"&&(n.preventDefault(),this.closeCommandPalette())}),e?.addEventListener("keydown",n=>{n.key==="Escape"&&(n.preventDefault(),this.closeCommandPalette())}),s?.addEventListener?.("click",n=>{const a=n.target?.closest?.("[data-command-index]");a&&(this.commandPaletteActiveIndex=Number(a.dataset.commandIndex)||0,this.activateCommandPaletteItem())})},buildCommandPaletteItems(e=""){const t=e.trim().toLowerCase(),s=[...Array.isArray(this.sessionOrder)?this.sessionOrder:[],...Array.from(this.sessions?.keys?.()||[]).filter(i=>!this.sessionOrder?.includes?.(i))],n=new Set,a=[];for(const i of s){if(n.has(i))continue;n.add(i);const r=this.sessions?.get?.(i);if(!r)continue;const o=this.getSessionName?.(r)||r.name||r.title||i.slice(0,8),l=[r.workingDir,r.mode,r.status].filter(Boolean),d=[o,r.workingDir,r.mode,r.status,i].filter(Boolean).join(" ").toLowerCase();t&&!d.includes(t)||a.push({id:`session:${i}`,type:"session",sessionId:i,title:o,subtitle:l.join(" \xB7 ")})}return a.push(this._buildCommandPaletteNewSessionItem(e)),a.push({id:"browse-sessions",type:"browse-sessions",title:"Browse all sessions\u2026",subtitle:"Open Session Manager"}),a},_buildCommandPaletteNewSessionItem(e=""){const t=this.runMode||this._runMode||"claude",s={claude:"Claude",opencode:"OpenCode",codex:"Codex",gemini:"Gemini",antigravity:"Antigravity"},n=this._findCommandPaletteCaseMatch(e)||document.getElementById("quickStartCase")?.value||"testcase";return{id:"new-session",type:"new-session",caseName:n,title:"New session",subtitle:`Run ${s[t]||t} in ${n}`}},_findCommandPaletteCaseMatch(e=""){const t=e.trim().toLowerCase();if(!t||!Array.isArray(this.cases))return null;const s=i=>{const r=String(i?.name||"").trim();if(!r)return 0;const o=[r,i?.path,i?.casePath,i?.workingDir,i?.remote?.path,i?.remote?.hostId].filter(Boolean).join(" ").toLowerCase(),l=r.toLowerCase();return l===t?100:l.startsWith(t)?90:l.includes(t)?80:o.includes(t)?60:0};let n=null,a=0;for(const i of this.cases){const r=s(i);r>a&&(n=i,a=r)}return n?.name||null},renderCommandPalette(){const e=document.getElementById("commandPaletteSearch"),t=document.getElementById("commandPaletteList");if(!t)return;const s=e?.value||"",n=this.buildCommandPaletteItems(s);this.commandPaletteItems=n,this.commandPaletteActiveIndex=Math.max(0,Math.min(this.commandPaletteActiveIndex||0,n.length-1)),t.innerHTML=n.map((a,i)=>{const r=i===this.commandPaletteActiveIndex?" active":"",o=a.type==="new-session"?"+":a.type==="browse-sessions"?"\u2261":"\u203A",l=a.type==="browse-sessions"?" command-palette-item--browse":"";return`
|
|
2
2
|
<button class="command-palette-item${r}${l}" type="button" data-command-index="${i}">
|
|
3
3
|
<span class="command-palette-icon" aria-hidden="true">${o}</span>
|
|
4
4
|
<span class="command-palette-text">
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
<span class="stat-card-value">${this.formatTokens(c+m)}</span>
|
|
68
68
|
<span class="stat-card-cost">~$${u.toFixed(2)}</span>
|
|
69
69
|
</div>
|
|
70
|
-
`;const p=document.getElementById("statsChart"),
|
|
70
|
+
`;const p=document.getElementById("statsChart"),y=document.getElementById("statsChartDays"),b=[];for(let g=6;g>=0;g--){const S=new Date;S.setDate(S.getDate()-g);const $=S.toISOString().split("T")[0],w=t.find(D=>D.date===$);b.push({date:$,dayName:S.toLocaleDateString("en-US",{weekday:"short"}),tokens:w?w.inputTokens+w.outputTokens:0,cost:w?w.estimatedCost:0})}const f=Math.max(...b.map(g=>g.tokens),1);p.innerHTML=b.map(g=>{const S=Math.max(g.tokens/f*100,3),$=`${g.dayName}: ${this.formatTokens(g.tokens)} (~$${g.cost.toFixed(2)})`;return`<div class="bar" style="height: ${S}%" data-tooltip="${$}"></div>`}).join(""),y.innerHTML=b.map(g=>`<span>${g.dayName}</span>`).join("");const v=document.getElementById("statsTable"),T=t.slice(0,14);T.length===0?v.innerHTML='<div class="stats-no-data">No usage data recorded yet</div>':v.innerHTML=`
|
|
71
71
|
<div class="stats-table-header">
|
|
72
72
|
<span>Date</span>
|
|
73
73
|
<span>Input</span>
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
<span class="cell cell-cost">$${g.estimatedCost.toFixed(2)}</span>
|
|
83
83
|
</div>
|
|
84
84
|
`).join("")}
|
|
85
|
-
`},closeTokenStats(){const e=document.getElementById("tokenStatsModal");e&&e.classList.remove("active")},async toggleMonitorPanel(){const e=document.getElementById("monitorPanel"),t=document.getElementById("monitorToggleBtn");e.classList.toggle("open"),e.classList.contains("open")?(e.style.display="",await this.loadMuxSessions(),await fetch("/api/mux-sessions/stats/start",{method:"POST"}),this.renderTaskPanel(),t&&(t.innerHTML="▼")):(await fetch("/api/mux-sessions/stats/stop",{method:"POST"}),t&&(t.innerHTML="▲"))},toggleTaskPanel(){this.toggleMonitorPanel()},toggleMonitorDetach(){const e=document.getElementById("monitorPanel"),t=document.getElementById("monitorDetachBtn");e.classList.contains("detached")?(e.classList.remove("detached"),e.style.top="",e.style.left="",e.style.width="",e.style.height="",t&&(t.innerHTML="⧉",t.title="Detach panel")):(e.classList.add("detached"),e.classList.add("open"),t&&(t.innerHTML="⊞",t.title="Attach panel"),this.setupMonitorDrag())},setupMonitorDrag(){const e=document.getElementById("monitorPanel"),t=document.getElementById("monitorPanelHeader");if(!e||!t)return;let s=!1,n,a,i,r;const o=c=>{if(c.target.closest("button")||!e.classList.contains("detached"))return;s=!0;const m=getEventCoords(c);n=m.clientX,a=m.clientY;const u=e.getBoundingClientRect();i=u.left,r=u.top,document.addEventListener("mousemove",l),document.addEventListener("mouseup",d),document.addEventListener("touchmove",l,{passive:!1}),document.addEventListener("touchend",d),c.preventDefault()},l=c=>{if(!s)return;const m=getEventCoords(c),u=m.clientX-n,h=m.clientY-a;let p=i+u,
|
|
85
|
+
`},closeTokenStats(){const e=document.getElementById("tokenStatsModal");e&&e.classList.remove("active")},async toggleMonitorPanel(){const e=document.getElementById("monitorPanel"),t=document.getElementById("monitorToggleBtn");e.classList.toggle("open"),e.classList.contains("open")?(e.style.display="",await this.loadMuxSessions(),await fetch("/api/mux-sessions/stats/start",{method:"POST"}),this.renderTaskPanel(),t&&(t.innerHTML="▼")):(await fetch("/api/mux-sessions/stats/stop",{method:"POST"}),t&&(t.innerHTML="▲"))},toggleTaskPanel(){this.toggleMonitorPanel()},toggleMonitorDetach(){const e=document.getElementById("monitorPanel"),t=document.getElementById("monitorDetachBtn");e.classList.contains("detached")?(e.classList.remove("detached"),e.style.top="",e.style.left="",e.style.width="",e.style.height="",t&&(t.innerHTML="⧉",t.title="Detach panel")):(e.classList.add("detached"),e.classList.add("open"),t&&(t.innerHTML="⊞",t.title="Attach panel"),this.setupMonitorDrag())},setupMonitorDrag(){const e=document.getElementById("monitorPanel"),t=document.getElementById("monitorPanelHeader");if(!e||!t)return;let s=!1,n,a,i,r;const o=c=>{if(c.target.closest("button")||!e.classList.contains("detached"))return;s=!0;const m=getEventCoords(c);n=m.clientX,a=m.clientY;const u=e.getBoundingClientRect();i=u.left,r=u.top,document.addEventListener("mousemove",l),document.addEventListener("mouseup",d),document.addEventListener("touchmove",l,{passive:!1}),document.addEventListener("touchend",d),c.preventDefault()},l=c=>{if(!s)return;const m=getEventCoords(c),u=m.clientX-n,h=m.clientY-a;let p=i+u,y=r+h;const b=e.getBoundingClientRect();p=Math.max(0,Math.min(window.innerWidth-b.width,p)),y=Math.max(0,Math.min(window.innerHeight-b.height,y)),e.style.left=p+"px",e.style.top=y+"px"},d=()=>{s=!1,document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",d),document.removeEventListener("touchmove",l),document.removeEventListener("touchend",d)};t.removeEventListener("mousedown",t._dragHandler),t.removeEventListener("touchstart",t._touchDragHandler),t._dragHandler=o,t._touchDragHandler=o,t.addEventListener("mousedown",o),t.addEventListener("touchstart",o,{passive:!1})},toggleSubagentsDetach(){const e=document.getElementById("subagentsPanel"),t=document.getElementById("subagentsDetachBtn");e.classList.contains("detached")?(e.classList.remove("detached"),e.style.top="",e.style.left="",e.style.width="",e.style.height="",t&&(t.innerHTML="⧉",t.title="Detach panel")):(e.classList.add("detached"),e.classList.add("open"),t&&(t.innerHTML="⊞",t.title="Attach panel"),this.setupSubagentsDrag())},setupSubagentsDrag(){const e=document.getElementById("subagentsPanel"),t=document.getElementById("subagentsPanelHeader");if(!e||!t)return;let s=!1,n,a,i,r;const o=c=>{if(c.target.closest("button")||!e.classList.contains("detached"))return;s=!0;const m=getEventCoords(c);n=m.clientX,a=m.clientY;const u=e.getBoundingClientRect();i=u.left,r=u.top,document.addEventListener("mousemove",l),document.addEventListener("mouseup",d),document.addEventListener("touchmove",l,{passive:!1}),document.addEventListener("touchend",d),c.preventDefault()},l=c=>{if(!s)return;const m=getEventCoords(c),u=m.clientX-n,h=m.clientY-a;let p=i+u,y=r+h;const b=e.getBoundingClientRect();p=Math.max(0,Math.min(window.innerWidth-b.width,p)),y=Math.max(0,Math.min(window.innerHeight-b.height,y)),e.style.left=p+"px",e.style.top=y+"px"},d=()=>{s=!1,document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",d),document.removeEventListener("touchmove",l),document.removeEventListener("touchend",d)};t.removeEventListener("mousedown",t._dragHandler),t.removeEventListener("touchstart",t._touchDragHandler),t._dragHandler=o,t._touchDragHandler=o,t.addEventListener("mousedown",o),t.addEventListener("touchstart",o,{passive:!1})},renderTaskPanel(){this._debouncedCall("taskPanel",this._renderTaskPanelImmediate)},_renderTaskPanelImmediate(){const e=this.sessions.get(this.activeSessionId),t=document.getElementById("backgroundTasksBody"),s=document.getElementById("taskPanelStats"),n=document.getElementById("backgroundTasksSection");if(!e||!e.taskTree||e.taskTree.length===0){n&&(n.style.display="none"),t.innerHTML="",s.textContent="0 tasks";return}n&&(n.style.display="");const a=e.taskStats||{running:0,completed:0,failed:0,total:0};s.textContent=`${a.running} running, ${a.completed} done`;const i=(l,d)=>{const c=l.status==="running"?"":l.status==="completed"?"✓":"✗",m=l.endTime?`${((l.endTime-l.startTime)/1e3).toFixed(1)}s`:`${((Date.now()-l.startTime)/1e3).toFixed(0)}s...`;let u="";if(l.children&&l.children.length>0){u='<div class="task-children">';for(const h of l.children){const p=d.find(y=>y.id===h);p&&(u+=`<div class="task-node">${i(p,d)}</div>`)}u+="</div>"}return`
|
|
86
86
|
<div class="task-item">
|
|
87
87
|
<span class="task-status-icon ${l.status}">${c}</span>
|
|
88
88
|
<div class="task-info">
|
|
@@ -94,13 +94,13 @@
|
|
|
94
94
|
</div>
|
|
95
95
|
</div>
|
|
96
96
|
${u}
|
|
97
|
-
`},r=this.flattenTaskTree(e.taskTree);let o='<div class="task-tree">';for(const l of e.taskTree)o+=`<div class="task-node">${i(l,r)}</div>`;o+="</div>",t.innerHTML=o},flattenTaskTree(e,t=[]){for(const s of e)t.push(s);return t},toggleSubagentPanel(){this.toggleSubagentsPanel()},updateSubagentBadge(){const e=this.$("subagentCountBadge"),t=Array.from(this.subagents.values()).filter(s=>s.status==="active"||s.status==="idle").length;e&&(e.textContent=t>0?t:"")},renderSubagentPanel(){this._subagentPanelRenderTimeout&&clearTimeout(this._subagentPanelRenderTimeout),this._subagentPanelRenderTimeout=setTimeout(()=>{scheduleBackground(()=>this._renderSubagentPanelImmediate())},150)},_renderSubagentPanelImmediate(){const e=this.$("subagentList");if(!e||(this.updateSubagentBadge(),this.renderMonitorSubagents(),!this.subagentPanelVisible))return;if(this.subagents.size===0){e.innerHTML='<div class="subagent-empty">No background agents detected</div>';return}const t=[],s=Array.from(this.subagents.values()).sort((n,a)=>n.status==="active"&&a.status!=="active"?-1:a.status==="active"&&n.status!=="active"?1:(a.lastActivityAt||0)-(n.lastActivityAt||0));for(const n of s){const a=this.activeSubagentId===n.agentId,i=n.status==="active"?"active":n.status==="idle"?"idle":"completed",r=this.subagentActivity.get(n.agentId)||[],o=r[r.length-1],l=o?.type==="tool"?o.tool:null,d=this.subagentWindows.has(n.agentId),c=n.status==="active"||n.status==="idle",m=n.modelShort?`<span class="subagent-model-badge ${escapeHtml(n.modelShort)}">${escapeHtml(n.modelShort)}</span>`:"",u=this.getTeammateInfo(n),h=u?u.name:n.description||n.agentId.substring(0,7),p=this.getTeammateBadgeHtml(n),
|
|
97
|
+
`},r=this.flattenTaskTree(e.taskTree);let o='<div class="task-tree">';for(const l of e.taskTree)o+=`<div class="task-node">${i(l,r)}</div>`;o+="</div>",t.innerHTML=o},flattenTaskTree(e,t=[]){for(const s of e)t.push(s);return t},toggleSubagentPanel(){this.toggleSubagentsPanel()},updateSubagentBadge(){const e=this.$("subagentCountBadge"),t=Array.from(this.subagents.values()).filter(s=>s.status==="active"||s.status==="idle").length;e&&(e.textContent=t>0?t:"")},renderSubagentPanel(){this._subagentPanelRenderTimeout&&clearTimeout(this._subagentPanelRenderTimeout),this._subagentPanelRenderTimeout=setTimeout(()=>{scheduleBackground(()=>this._renderSubagentPanelImmediate())},150)},_renderSubagentPanelImmediate(){const e=this.$("subagentList");if(!e||(this.updateSubagentBadge(),this.renderMonitorSubagents(),!this.subagentPanelVisible))return;if(this.subagents.size===0){e.innerHTML='<div class="subagent-empty">No background agents detected</div>';return}const t=[],s=Array.from(this.subagents.values()).sort((n,a)=>n.status==="active"&&a.status!=="active"?-1:a.status==="active"&&n.status!=="active"?1:(a.lastActivityAt||0)-(n.lastActivityAt||0));for(const n of s){const a=this.activeSubagentId===n.agentId,i=n.status==="active"?"active":n.status==="idle"?"idle":"completed",r=this.subagentActivity.get(n.agentId)||[],o=r[r.length-1],l=o?.type==="tool"?o.tool:null,d=this.subagentWindows.has(n.agentId),c=n.status==="active"||n.status==="idle",m=n.modelShort?`<span class="subagent-model-badge ${escapeHtml(n.modelShort)}">${escapeHtml(n.modelShort)}</span>`:"",u=this.getTeammateInfo(n),h=u?u.name:n.description||n.agentId.substring(0,7),p=this.getTeammateBadgeHtml(n),y=u?`<span class="subagent-icon teammate-dot teammate-color-${u.color}">\u25CF</span>`:'<span class="subagent-icon">\u{1F916}</span>';t.push(`
|
|
98
98
|
<div class="subagent-item ${i} ${a?"selected":""}${u?" is-teammate":""}"
|
|
99
99
|
onclick="app.selectSubagent(${escapeHtml(JSON.stringify(n.agentId))})"
|
|
100
100
|
ondblclick="app.openSubagentWindow(${escapeHtml(JSON.stringify(n.agentId))})"
|
|
101
101
|
title="Double-click to open tracking window">
|
|
102
102
|
<div class="subagent-header">
|
|
103
|
-
${
|
|
103
|
+
${y}
|
|
104
104
|
<span class="subagent-id" title="${escapeHtml(n.description||n.agentId)}">${escapeHtml(h.length>40?h.substring(0,40)+"...":h)}</span>
|
|
105
105
|
${p}
|
|
106
106
|
${m}
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
<span class="tool-detail">${escapeHtml(a)}</span>
|
|
188
188
|
</div>`}else if(e.type==="message"){const s=e.text.length>150?e.text.substring(0,150)+"...":e.text;return`<div class="message-line">
|
|
189
189
|
<span class="time">${t}</span> \u{1F4AC} ${escapeHtml(s)}
|
|
190
|
-
</div>`}return""},updateSubagentWindows(){for(const e of this.subagentWindows.keys())this.renderSubagentWindowContent(e),this.updateSubagentWindowHeader(e)},updateSubagentWindowHeader(e){const t=this.subagents.get(e);if(!t)return;const s=document.getElementById(`subagent-window-${e}`);if(!s)return;const n=s.querySelector(".subagent-window-title .id");if(n){const d=this.getTeammateInfo(t),c=d?d.name:t.description||e.substring(0,7),m=c.length>50?c.substring(0,50)+"...":c;n.textContent=m}let a=s.querySelector(".teammate-badge");const i=this.getTeammateInfo(t);if(i&&!a){const d=s.querySelector(".subagent-window-title");if(d){const c=document.createElement("span");c.className=`teammate-badge teammate-color-${i.color}`,c.title=`Team: ${i.teamName}`,c.textContent=`@${i.name}`;const m=d.querySelector(".status");m&&m.insertAdjacentElement("beforebegin",c)}}const r=s.querySelector(".subagent-window-title");r&&(r.title=t.description||e);let o=s.querySelector(".subagent-window-title .subagent-model-badge");if(t.modelShort){if(!o){o=document.createElement("span"),o.className=`subagent-model-badge ${t.modelShort}`;const d=s.querySelector(".subagent-window-title .status");d&&d.insertAdjacentElement("beforebegin",o)}o.className=`subagent-model-badge ${t.modelShort}`,o.textContent=t.modelShort}const l=s.querySelector(".subagent-window-title .status");l&&(l.className=`status ${t.status}`,l.textContent=t.status)},openAllActiveSubagentWindows(){for(const[e,t]of this.subagents)t.status==="active"&&!this.subagentWindows.has(e)&&this.openSubagentWindow(e)},initTeammateTerminal(e,t,s){const n=s.querySelector(".subagent-window-body");if(!n)return;n.innerHTML="",n.classList.add("teammate-terminal-body"),s.classList.add("has-terminal");const a=t.sessionId,i=[];this.teammateTerminals.set(e,{terminal:null,fitAddon:null,paneTarget:t.paneTarget,sessionId:a,resizeObserver:null,pendingData:i}),requestAnimationFrame(()=>{if(!document.contains(n)){this.teammateTerminals.delete(e);return}const r=new Terminal({theme:{...window.codemanCurrentXtermTheme()},minimumContrastRatio:window.codemanCurrentSkinIsLight()?4.5:1,fontFamily:'"Fira Code", "Cascadia Code", "JetBrains Mono", "SF Mono", Monaco, monospace',fontSize:12,lineHeight:1.2,cursorBlink:!0,cursorStyle:"block",scrollback:DEFAULT_SCROLLBACK,allowTransparency:!0,allowProposedApi:!0}),o=new FitAddon.FitAddon;if(r.loadAddon(o),typeof Unicode11Addon<"u")try{const c=new Unicode11Addon.Unicode11Addon;r.loadAddon(c),r.unicode.activeVersion="11"}catch{}try{r.open(n)}catch(c){console.warn("[TeammateTerminal] Failed to open terminal:",c),this.teammateTerminals.delete(e);return}setTimeout(()=>{try{o.fit()}catch{}fetch(`/api/sessions/${a}/teammate-pane-buffer/${encodeURIComponent(t.paneTarget)}`).then(c=>c.json()).then(c=>{if(c.success&&c.data?.buffer)try{r.write(c.data.buffer)}catch{}}).catch(c=>console.error("[TeammateTerminal] Failed to fetch buffer:",c));for(const c of i)try{r.write(c)}catch{}i.length=0},100),r.onData(c=>{fetch(`/api/sessions/${a}/teammate-pane-input`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({paneTarget:t.paneTarget,input:c})}).catch(m=>console.error("[TeammateTerminal] Failed to send input:",m))});const l=new ResizeObserver(()=>{requestAnimationFrame(()=>{try{o.fit()}catch{}})});l.observe(n);const d=this.teammateTerminals.get(e);d&&(d.terminal=r,d.fitAddon=o,d.resizeObserver=l)})},openTeammateTerminalWindow(e){if(!this.sessions.has(e.sessionId))return;const t=`pane-${e.paneTarget}`;if(this.subagentWindows.has(t)){const
|
|
190
|
+
</div>`}return""},updateSubagentWindows(){for(const e of this.subagentWindows.keys())this.renderSubagentWindowContent(e),this.updateSubagentWindowHeader(e)},updateSubagentWindowHeader(e){const t=this.subagents.get(e);if(!t)return;const s=document.getElementById(`subagent-window-${e}`);if(!s)return;const n=s.querySelector(".subagent-window-title .id");if(n){const d=this.getTeammateInfo(t),c=d?d.name:t.description||e.substring(0,7),m=c.length>50?c.substring(0,50)+"...":c;n.textContent=m}let a=s.querySelector(".teammate-badge");const i=this.getTeammateInfo(t);if(i&&!a){const d=s.querySelector(".subagent-window-title");if(d){const c=document.createElement("span");c.className=`teammate-badge teammate-color-${i.color}`,c.title=`Team: ${i.teamName}`,c.textContent=`@${i.name}`;const m=d.querySelector(".status");m&&m.insertAdjacentElement("beforebegin",c)}}const r=s.querySelector(".subagent-window-title");r&&(r.title=t.description||e);let o=s.querySelector(".subagent-window-title .subagent-model-badge");if(t.modelShort){if(!o){o=document.createElement("span"),o.className=`subagent-model-badge ${t.modelShort}`;const d=s.querySelector(".subagent-window-title .status");d&&d.insertAdjacentElement("beforebegin",o)}o.className=`subagent-model-badge ${t.modelShort}`,o.textContent=t.modelShort}const l=s.querySelector(".subagent-window-title .status");l&&(l.className=`status ${t.status}`,l.textContent=t.status)},openAllActiveSubagentWindows(){for(const[e,t]of this.subagents)t.status==="active"&&!this.subagentWindows.has(e)&&this.openSubagentWindow(e)},initTeammateTerminal(e,t,s){const n=s.querySelector(".subagent-window-body");if(!n)return;n.innerHTML="",n.classList.add("teammate-terminal-body"),s.classList.add("has-terminal");const a=t.sessionId,i=[];this.teammateTerminals.set(e,{terminal:null,fitAddon:null,paneTarget:t.paneTarget,sessionId:a,resizeObserver:null,pendingData:i}),requestAnimationFrame(()=>{if(!document.contains(n)){this.teammateTerminals.delete(e);return}const r=new Terminal({theme:{...window.codemanCurrentXtermTheme()},minimumContrastRatio:window.codemanCurrentSkinIsLight()?4.5:1,fontFamily:'"Fira Code", "Cascadia Code", "JetBrains Mono", "SF Mono", Monaco, monospace',fontSize:12,lineHeight:1.2,cursorBlink:!0,cursorStyle:"block",scrollback:DEFAULT_SCROLLBACK,allowTransparency:!0,allowProposedApi:!0}),o=new FitAddon.FitAddon;if(r.loadAddon(o),typeof Unicode11Addon<"u")try{const c=new Unicode11Addon.Unicode11Addon;r.loadAddon(c),r.unicode.activeVersion="11"}catch{}try{r.open(n)}catch(c){console.warn("[TeammateTerminal] Failed to open terminal:",c),this.teammateTerminals.delete(e);return}setTimeout(()=>{try{o.fit()}catch{}fetch(`/api/sessions/${a}/teammate-pane-buffer/${encodeURIComponent(t.paneTarget)}`).then(c=>c.json()).then(c=>{if(c.success&&c.data?.buffer)try{r.write(c.data.buffer)}catch{}}).catch(c=>console.error("[TeammateTerminal] Failed to fetch buffer:",c));for(const c of i)try{r.write(c)}catch{}i.length=0},100),r.onData(c=>{fetch(`/api/sessions/${a}/teammate-pane-input`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({paneTarget:t.paneTarget,input:c})}).catch(m=>console.error("[TeammateTerminal] Failed to send input:",m))});const l=new ResizeObserver(()=>{requestAnimationFrame(()=>{try{o.fit()}catch{}})});l.observe(n);const d=this.teammateTerminals.get(e);d&&(d.terminal=r,d.fitAddon=o,d.resizeObserver=l)})},openTeammateTerminalWindow(e){if(!this.sessions.has(e.sessionId))return;const t=`pane-${e.paneTarget}`;if(this.subagentWindows.has(t)){const w=this.subagentWindows.get(t);w.hidden&&(w.element.style.display="flex",w.hidden=!1),w.element.style.zIndex=++this.subagentWindowZIndex,w.minimized&&this.restoreSubagentWindow(t);return}const s=this.subagentWindows.size,n=550,a=400,i=20,r=window.innerWidth,o=window.innerHeight,l=50,d=120,c=Math.floor((r-l-50)/(n+i))||1,m=Math.floor((o-d-50)/(a+i))||1,u=s%c,h=Math.floor(s/c)%m;let p=l+u*(n+i),y=d+h*(a+i);p=Math.max(10,Math.min(p,r-n-10)),y=Math.max(10,Math.min(y,o-a-10));const b=e.color||"blue",f=document.createElement("div");f.className="subagent-window has-terminal",f.id=`subagent-window-${t}`,f.style.zIndex=++this.subagentWindowZIndex,f.style.left=`${p}px`,f.style.top=`${y}px`,f.style.width=`${n}px`,f.style.height=`${a}px`,f.innerHTML=`
|
|
191
191
|
<div class="subagent-window-header">
|
|
192
192
|
<div class="subagent-window-title" title="Teammate terminal: ${escapeHtml(e.teammateName)} (pane ${e.paneTarget})">
|
|
193
193
|
<span class="icon" style="color: var(--team-color-${b}, #339af0)">\u2B24</span>
|
|
@@ -200,7 +200,7 @@
|
|
|
200
200
|
</div>
|
|
201
201
|
<div class="subagent-window-body teammate-terminal-body" id="subagent-window-body-${t}">
|
|
202
202
|
</div>
|
|
203
|
-
`,document.body.appendChild(f);const v=this.makeWindowDraggable(f,f.querySelector(".subagent-window-header"));typeof this.makeWindowResizable=="function"&&this.makeWindowResizable(f);const S=(this.loadAppSettingsFromStorage().subagentActiveTabOnly??!0)&&e.sessionId!==this.activeSessionId;this.subagentWindows.set(t,{element:f,minimized:!1,hidden:S,dragListeners:v,description:`Teammate: ${e.teammateName}`}),this.subagentParentMap.set(t,e.sessionId),S&&(f.style.display="none"),f.addEventListener("mousedown",()=>{f.style.zIndex=++this.subagentWindowZIndex});const $=new ResizeObserver(()=>{this.updateConnectionLines()});if($.observe(f),this.subagentWindows.get(t).resizeObserver=$,S){const
|
|
203
|
+
`,document.body.appendChild(f);const v=this.makeWindowDraggable(f,f.querySelector(".subagent-window-header"));typeof this.makeWindowResizable=="function"&&this.makeWindowResizable(f);const S=(this.loadAppSettingsFromStorage().subagentActiveTabOnly??!0)&&e.sessionId!==this.activeSessionId;this.subagentWindows.set(t,{element:f,minimized:!1,hidden:S,dragListeners:v,description:`Teammate: ${e.teammateName}`}),this.subagentParentMap.set(t,e.sessionId),S&&(f.style.display="none"),f.addEventListener("mousedown",()=>{f.style.zIndex=++this.subagentWindowZIndex});const $=new ResizeObserver(()=>{this.updateConnectionLines()});if($.observe(f),this.subagentWindows.get(t).resizeObserver=$,S){const w=this.subagentWindows.get(t);w&&(w._lazyTerminal=!0,w._lazyPaneTarget=e.paneTarget,w._lazySessionId=e.sessionId)}else this.initTeammateTerminal(t,e,f);requestAnimationFrame(()=>{f.style.transition="transform 0.3s ease, opacity 0.3s ease",f.style.transform="scale(1)",f.style.opacity="1"})},rebuildTeammateMap(){this.teammateMap.clear();for(const[e,t]of this.teams)for(const s of t.members)s.agentType!=="team-lead"&&this.teammateMap.set(s.name,{name:s.name,color:s.color||"blue",teamName:e,agentId:s.agentId})},getTeammateInfo(e){if(!e?.description)return null;const t=e.description.match(/<teammate-message\s+teammate_id="?([^">\s]+)/);if(!t)return null;const n=t[1].split("@")[0];return this.teammateMap.get(n)||{name:n,color:"blue",teamName:"unknown"}},getTeammateBadgeHtml(e){const t=this.getTeammateInfo(e);return t?`<span class="teammate-badge teammate-color-${t.color}" title="Team: ${escapeHtml(t.teamName)}">@${escapeHtml(t.name)}</span>`:""},renderTeamTasksPanel(){const e=document.getElementById("teamTasksPanel");if(!e)return;let t=null,s=null;if(this.activeSessionId){for(const[h,p]of this.teams)if(p.leadSessionId===this.activeSessionId){t=p,s=h;break}}if(!t){e.style.display="none";return}const n=e.style.display==="none";if(e.style.display="flex",n&&!this.teamTasksDragListeners){e.style.left=`${Math.max(10,window.innerWidth-360-20)}px`,e.style.top=`${Math.max(10,window.innerHeight-300-70)}px`;const y=e.querySelector(".team-tasks-header");y&&(this.teamTasksDragListeners=this.makeWindowDraggable(e,y))}const a=this.teamTasks.get(s)||[],i=a.filter(h=>h.status==="completed").length,r=a.length,o=r>0?Math.round(i/r*100):0,l=e.querySelector(".team-tasks-header-text");if(l){const h=t.members.filter(p=>p.agentType!=="team-lead").length;l.textContent=`Team Tasks (${h} teammates)`}const d=e.querySelector(".team-tasks-progress-fill");d&&(d.style.width=`${o}%`);const c=e.querySelector(".team-tasks-progress-text");c&&(c.textContent=`${i}/${r}`);const m=e.querySelector(".team-tasks-list");if(!m)return;if(a.length===0){m.innerHTML='<div class="team-task-empty">No tasks yet</div>';return}const u=a.map(h=>{const p=h.status==="completed"?"\u2713":h.status==="in_progress"?"\u25C9":"\u25CB",y=h.status.replace("_","-"),b=h.owner?`<span class="team-task-owner teammate-color-${this.getTeammateColor(h.owner)}">${escapeHtml(h.owner)}</span>`:"";return`<div class="team-task-item ${y}">
|
|
204
204
|
<span class="team-task-status">${p}</span>
|
|
205
205
|
<span class="team-task-subject">${escapeHtml(h.subject)}</span>
|
|
206
206
|
${b}
|
|
@@ -213,22 +213,22 @@
|
|
|
213
213
|
${m.timeout?`<span class="project-insight-timeout">${escapeHtml(m.timeout)}</span>`:""}
|
|
214
214
|
</div>
|
|
215
215
|
<div class="project-insight-paths">
|
|
216
|
-
`);for(const p of u){const
|
|
216
|
+
`);for(const p of u){const y=p.split("/").pop();c.push(`
|
|
217
217
|
<span class="project-insight-filepath"
|
|
218
218
|
onclick="app.openLogViewerWindow(${escapeHtml(JSON.stringify(p))}, ${escapeHtml(JSON.stringify(m.sessionId))})"
|
|
219
|
-
title="${escapeHtml(p)}">${escapeHtml(
|
|
219
|
+
title="${escapeHtml(p)}">${escapeHtml(y)}</span>
|
|
220
220
|
`)}c.push(`
|
|
221
221
|
</div>
|
|
222
222
|
</div>
|
|
223
|
-
`)}t.innerHTML=c.join("")},closeProjectInsightsPanel(){const e=this.$("projectInsightsPanel");e&&(e.classList.remove("visible"),this.projectInsightsPanelVisible=!1)},async loadFileBrowser(e){if(!e)return;const t=this.$("fileBrowserTree"),s=this.$("fileBrowserStatus");if(t){t.innerHTML='<div class="file-browser-loading">Loading files...</div>';try{const n=await fetch(`/api/sessions/${e}/files?depth=5&showHidden=false`);if(!n.ok)throw new Error("Failed to load files");const a=await n.json();if(!a.success)throw new Error(a.error||"Failed to load files");if(this.fileBrowserData=a.data,this.renderFileBrowserTree(),s){const{totalFiles:i,totalDirectories:r,truncated:o}=a.data;s.textContent=`${i} files, ${r} dirs${o?" (truncated)":""}`}}catch(n){console.error("Failed to load file browser:",n),t.innerHTML=`<div class="file-browser-empty">Failed to load files: ${escapeHtml(n.message)}</div>`}}},renderFileBrowserTree(){const e=this.$("fileBrowserTree");if(!e||!this.fileBrowserData)return;const{tree:t}=this.fileBrowserData;if(!t||t.length===0){e.innerHTML='<div class="file-browser-empty">No files found</div>';return}const s=[],n=this.fileBrowserFilter.toLowerCase(),a=(i,r)=>{const o=i.type==="directory",l=this.fileBrowserExpandedDirs.has(i.path),d=!n||i.name.toLowerCase().includes(n);let c=!1;o&&n&&i.children&&(c=this.hasMatchingChild(i,n));const u=!(d||c)&&n?" hidden-by-filter":"",h=o?l?"\u{1F4C2}":"\u{1F4C1}":this.getFileIcon(i.extension),p=o?`<span class="file-tree-expand${l?" expanded":""}">\u25B6</span>`:'<span class="file-tree-expand"></span>',
|
|
223
|
+
`)}t.innerHTML=c.join("")},closeProjectInsightsPanel(){const e=this.$("projectInsightsPanel");e&&(e.classList.remove("visible"),this.projectInsightsPanelVisible=!1)},async loadFileBrowser(e){if(!e)return;const t=this.$("fileBrowserTree"),s=this.$("fileBrowserStatus");if(t){t.innerHTML='<div class="file-browser-loading">Loading files...</div>';try{const n=await fetch(`/api/sessions/${e}/files?depth=5&showHidden=false`);if(!n.ok)throw new Error("Failed to load files");const a=await n.json();if(!a.success)throw new Error(a.error||"Failed to load files");if(this.fileBrowserData=a.data,this.renderFileBrowserTree(),s){const{totalFiles:i,totalDirectories:r,truncated:o}=a.data;s.textContent=`${i} files, ${r} dirs${o?" (truncated)":""}`}}catch(n){console.error("Failed to load file browser:",n),t.innerHTML=`<div class="file-browser-empty">Failed to load files: ${escapeHtml(n.message)}</div>`}}},renderFileBrowserTree(){const e=this.$("fileBrowserTree");if(!e||!this.fileBrowserData)return;const{tree:t}=this.fileBrowserData;if(!t||t.length===0){e.innerHTML='<div class="file-browser-empty">No files found</div>';return}const s=[],n=this.fileBrowserFilter.toLowerCase(),a=(i,r)=>{const o=i.type==="directory",l=this.fileBrowserExpandedDirs.has(i.path),d=!n||i.name.toLowerCase().includes(n);let c=!1;o&&n&&i.children&&(c=this.hasMatchingChild(i,n));const u=!(d||c)&&n?" hidden-by-filter":"",h=o?l?"\u{1F4C2}":"\u{1F4C1}":this.getFileIcon(i.extension),p=o?`<span class="file-tree-expand${l?" expanded":""}">\u25B6</span>`:'<span class="file-tree-expand"></span>',y=!o&&i.size!==void 0?`<span class="file-tree-size">${this.formatFileSize(i.size)}</span>`:"",b=o?"file-tree-name directory":"file-tree-name",f=o?"":`<a class="file-tree-download" href="/api/sessions/${this.activeSessionId}/file-raw?path=${encodeURIComponent(i.path)}&download=true" title="Download" onclick="event.stopPropagation()">⬇</a>`;if(s.push(`
|
|
224
224
|
<div class="file-tree-item${u}" data-path="${escapeHtml(i.path)}" data-type="${i.type}" data-depth="${r}">
|
|
225
225
|
${p}
|
|
226
226
|
<span class="file-tree-icon">${h}</span>
|
|
227
227
|
<span class="${b}">${escapeHtml(i.name)}</span>
|
|
228
|
-
${
|
|
228
|
+
${y}
|
|
229
229
|
${f}
|
|
230
230
|
</div>
|
|
231
|
-
`),o&&l&&i.children)for(const v of i.children)a(v,r+1)};for(const i of t)a(i,0);e.innerHTML=s.join(""),e.querySelectorAll(".file-tree-item").forEach(i=>{i.addEventListener("click",()=>{const r=i.dataset.path;i.dataset.type==="directory"?this.toggleFileBrowserFolder(r):this.openFilePreview(r)})})},hasMatchingChild(e,t){if(!e.children)return!1;for(const s of e.children)if(s.name.toLowerCase().includes(t)||s.type==="directory"&&this.hasMatchingChild(s,t))return!0;return!1},toggleFileBrowserFolder(e){this.fileBrowserExpandedDirs.has(e)?this.fileBrowserExpandedDirs.delete(e):this.fileBrowserExpandedDirs.add(e),this.renderFileBrowserTree()},filterFileBrowser(e){this.fileBrowserFilter=e,e&&this.expandAllDirectories(this.fileBrowserData?.tree||[]),this.renderFileBrowserTree()},expandAllDirectories(e){for(const t of e)t.type==="directory"&&(this.fileBrowserExpandedDirs.add(t.path),t.children&&this.expandAllDirectories(t.children))},collapseAllDirectories(){this.fileBrowserExpandedDirs.clear()},toggleFileBrowserExpand(){this.fileBrowserAllExpanded=!this.fileBrowserAllExpanded;const e=this.$("fileBrowserExpandBtn");this.fileBrowserAllExpanded?(this.expandAllDirectories(this.fileBrowserData?.tree||[]),e&&(e.innerHTML="\u229F")):(this.collapseAllDirectories(),e&&(e.innerHTML="\u229E")),this.renderFileBrowserTree()},refreshFileBrowser(){if(this.activeSessionId){this.fileBrowserExpandedDirs.clear(),this.fileBrowserFilter="",this.fileBrowserAllExpanded=!1;const e=this.$("fileBrowserSearch");e&&(e.value=""),this.loadFileBrowser(this.activeSessionId)}},toggleFileBrowserButton(){const t=this.$("fileBrowserPanel")?.classList.contains("visible"),s=document.querySelector(".btn-file-viewer");if(t){this.closeFileBrowserPanel(),s&&s.setAttribute("aria-expanded","false");return}if(!this.activeSessionId){this.showToast("Open a session to browse its files","info");return}const n=this.loadAppSettingsFromStorage();n.showFileBrowser=!0,this.saveAppSettingsToStorage(n);const a=document.getElementById("appSettingsShowFileBrowser");a&&(a.checked=!0),this.applyMonitorVisibility(),s&&s.setAttribute("aria-expanded","true")},closeFileBrowserPanel(){const e=this.$("fileBrowserPanel");if(e&&(e.classList.remove("visible"),e.style.left="",e.style.top="",e.style.bottom="",e.style.right=""),this.fileBrowserDragListeners){const a=this.fileBrowserDragListeners;document.removeEventListener("mousemove",a.move),document.removeEventListener("mouseup",a.up),document.removeEventListener("touchmove",a.touchMove),document.removeEventListener("touchend",a.up),document.removeEventListener("touchcancel",a.up),a.handle&&(a.handle.removeEventListener("mousedown",a.handleMouseDown),a.handle.removeEventListener("touchstart",a.handleTouchStart),a._onFirstDrag&&(a.handle.removeEventListener("mousedown",a._onFirstDrag),a.handle.removeEventListener("touchstart",a._onFirstDrag))),this.fileBrowserDragListeners=null}const t=this.loadAppSettingsFromStorage();t.showFileBrowser=!1,this.saveAppSettingsToStorage(t);const s=document.getElementById("appSettingsShowFileBrowser");s&&(s.checked=!1);const n=document.querySelector(".btn-file-viewer");n&&n.setAttribute("aria-expanded","false")},async openFilePreview(e,t=this.activeSessionId,s=null){if(!t||!e)return;const n=this.$("filePreviewOverlay"),a=this.$("filePreviewTitle"),i=this.$("filePreviewBody"),r=this.$("filePreviewFooter");if(!n||!i)return;n.classList.add("visible"),a.textContent=e,i.innerHTML='<div class="binary-message">Loading...</div>',r.textContent="";const o=(e.split(".").pop()||"").toLowerCase();if(s){const l=`/api/sessions/${t}/attachments/${encodeURIComponent(s)}`,d=new Set(["png","jpg","jpeg","gif","webp","bmp","svg"]);if(r.textContent=o.toUpperCase(),d.has(o))i.innerHTML=`<img src="${escapeHtml(`${l}/raw`)}" alt="${escapeHtml(e)}">`;else if(o==="pdf")i.innerHTML=`<iframe src="${escapeHtml(`${l}/raw`)}" title="${escapeHtml(e)}"></iframe>`;else if(o==="docx"||o==="pptx")i.innerHTML=`<iframe src="${escapeHtml(`${l}/preview`)}" title="${escapeHtml(e)}"></iframe>`;else try{const c=await fetch(`${l}/raw`);if(!c.ok)throw new Error("Failed to load attachment");const m=await c.text();i.innerHTML=`<pre><code>${escapeHtml(m)}</code></pre>`}catch(c){i.innerHTML=`<div class="binary-message">Error: ${escapeHtml(c.message)}</div>`}return}if(o==="docx"||o==="pptx"){r.textContent=o.toUpperCase();const l=`/api/sessions/${t}/file-preview?path=${encodeURIComponent(e)}`;i.innerHTML=`<iframe src="${escapeHtml(l)}" title="${escapeHtml(e)}"></iframe>`;return}if(o==="pdf"){r.textContent="PDF";const l=`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}`;i.innerHTML=`<iframe src="${escapeHtml(l)}" title="${escapeHtml(e)}"></iframe>`;return}if(o==="svg"){r.textContent="SVG";try{const l=await fetch(`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}`);if(!l.ok)throw new Error("Failed to load image");const d=URL.createObjectURL(new Blob([await l.text()],{type:"image/svg+xml"}));i.innerHTML=`<img src="${d}" alt="${escapeHtml(e)}">`;const c=i.querySelector("img");c&&(c.onload=()=>URL.revokeObjectURL(d))}catch(l){i.innerHTML=`<div class="binary-message">Error: ${escapeHtml(l.message)}</div>`}return}try{const l=await fetch(`/api/sessions/${t}/file-content?path=${encodeURIComponent(e)}&lines=500`);if(!l.ok)throw new Error("Failed to load file");const d=await l.json();if(!d.success)throw new Error(d.error||"Failed to load file");const c=d.data;if(c.type==="image")i.innerHTML=`<img src="${c.url}" alt="${escapeHtml(e)}">`,r.textContent=`${this.formatFileSize(c.size)} \u2022 ${c.extension}`;else if(c.type==="video")i.innerHTML=`<video src="${c.url}" controls autoplay></video>`,r.textContent=`${this.formatFileSize(c.size)} \u2022 ${c.extension}`;else if(c.type==="audio")i.innerHTML=`<audio src="${c.url}" controls autoplay></audio>`,r.textContent=`${this.formatFileSize(c.size)} \u2022 ${c.extension}`;else if(c.type==="binary"){const m=`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}&download=true`;i.innerHTML=`<div class="binary-message">Binary file (${this.formatFileSize(c.size)})<br>Cannot preview<br><a href="${escapeHtml(m)}" download>Download</a></div>`,r.textContent=c.extension||"binary"}else{this.filePreviewContent=c.content,i.innerHTML=`<pre><code>${escapeHtml(c.content)}</code></pre>`;const m=c.truncated?` (showing 500/${c.totalLines} lines)`:"";r.textContent=`${c.totalLines} lines \u2022 ${this.formatFileSize(c.size)}${m}`}}catch(l){console.error("Failed to preview file:",l),i.innerHTML=`<div class="binary-message">Error: ${escapeHtml(l.message)}</div>`}},closeFilePreview(){const e=this.$("filePreviewOverlay");e&&e.classList.remove("visible"),this.filePreviewContent=""},_onAttachmentDetected(e){if(console.log("[Attachment Detected]",e),this.addAttachmentCard(e),e.sessionId){const t=this.attachmentHistoryCounts.get(e.sessionId)??this.sessions.get(e.sessionId)?.attachmentHistory?.length??0;this.attachmentHistoryCounts.set(e.sessionId,Math.min(t+1,100)),e.sessionId===this.activeSessionId&&(this.updateAttachmentHistoryBadge(),this.attachmentHistoryDrawerOpen&&this._debouncedCall("attachmentHistoryRefresh",()=>{this.attachmentHistoryDrawerOpen&&this.activeSessionId===e.sessionId&&this.loadAttachmentHistory(e.sessionId)},250))}},ensureAttachmentCardStack(){let e=this.attachmentCardStack||document.getElementById("attachmentCardStack");return e||(e=document.createElement("div"),e.id="attachmentCardStack",e.className="attachment-card-stack",document.body.appendChild(e)),this.attachmentCardStack=e,e},openAttachmentInNewTab(e,t,s=null){const n=s?`/api/sessions/${e}/attachments/${encodeURIComponent(s)}/raw`:`/api/sessions/${e}/file-raw?path=${encodeURIComponent(t)}`;window.open(n,"_blank")},addAttachmentCard(e){const{sessionId:t,relativePath:s,fileName:n,timestamp:a,size:i,attachmentType:r,extension:o,attachmentId:l,rawUrl:d,previewUrl:c,thumbnailUrl:m}=e,u=s||n,h=l||`${t}-${a}-${n}`;if(this.attachmentCards.has(h)){this.attachmentCards.get(h).element.focus?.();return}if(this.attachmentCards.size>=10){const I=this.attachmentCards.keys().next().value;I&&this.closeAttachmentCard(I)}const
|
|
231
|
+
`),o&&l&&i.children)for(const v of i.children)a(v,r+1)};for(const i of t)a(i,0);e.innerHTML=s.join(""),e.querySelectorAll(".file-tree-item").forEach(i=>{i.addEventListener("click",()=>{const r=i.dataset.path;i.dataset.type==="directory"?this.toggleFileBrowserFolder(r):this.openFilePreview(r)})})},hasMatchingChild(e,t){if(!e.children)return!1;for(const s of e.children)if(s.name.toLowerCase().includes(t)||s.type==="directory"&&this.hasMatchingChild(s,t))return!0;return!1},toggleFileBrowserFolder(e){this.fileBrowserExpandedDirs.has(e)?this.fileBrowserExpandedDirs.delete(e):this.fileBrowserExpandedDirs.add(e),this.renderFileBrowserTree()},filterFileBrowser(e){this.fileBrowserFilter=e,e&&this.expandAllDirectories(this.fileBrowserData?.tree||[]),this.renderFileBrowserTree()},expandAllDirectories(e){for(const t of e)t.type==="directory"&&(this.fileBrowserExpandedDirs.add(t.path),t.children&&this.expandAllDirectories(t.children))},collapseAllDirectories(){this.fileBrowserExpandedDirs.clear()},toggleFileBrowserExpand(){this.fileBrowserAllExpanded=!this.fileBrowserAllExpanded;const e=this.$("fileBrowserExpandBtn");this.fileBrowserAllExpanded?(this.expandAllDirectories(this.fileBrowserData?.tree||[]),e&&(e.innerHTML="\u229F")):(this.collapseAllDirectories(),e&&(e.innerHTML="\u229E")),this.renderFileBrowserTree()},refreshFileBrowser(){if(this.activeSessionId){this.fileBrowserExpandedDirs.clear(),this.fileBrowserFilter="",this.fileBrowserAllExpanded=!1;const e=this.$("fileBrowserSearch");e&&(e.value=""),this.loadFileBrowser(this.activeSessionId)}},toggleFileBrowserButton(){const t=this.$("fileBrowserPanel")?.classList.contains("visible"),s=document.querySelector(".btn-file-viewer");if(t){this.closeFileBrowserPanel(),s&&s.setAttribute("aria-expanded","false");return}if(!this.activeSessionId){this.showToast("Open a session to browse its files","info");return}const n=this.loadAppSettingsFromStorage();n.showFileBrowser=!0,this.saveAppSettingsToStorage(n);const a=document.getElementById("appSettingsShowFileBrowser");a&&(a.checked=!0),this.applyMonitorVisibility(),s&&s.setAttribute("aria-expanded","true")},closeFileBrowserPanel(){const e=this.$("fileBrowserPanel");if(e&&(e.classList.remove("visible"),e.style.left="",e.style.top="",e.style.bottom="",e.style.right=""),this.fileBrowserDragListeners){const a=this.fileBrowserDragListeners;document.removeEventListener("mousemove",a.move),document.removeEventListener("mouseup",a.up),document.removeEventListener("touchmove",a.touchMove),document.removeEventListener("touchend",a.up),document.removeEventListener("touchcancel",a.up),a.handle&&(a.handle.removeEventListener("mousedown",a.handleMouseDown),a.handle.removeEventListener("touchstart",a.handleTouchStart),a._onFirstDrag&&(a.handle.removeEventListener("mousedown",a._onFirstDrag),a.handle.removeEventListener("touchstart",a._onFirstDrag))),this.fileBrowserDragListeners=null}const t=this.loadAppSettingsFromStorage();t.showFileBrowser=!1,this.saveAppSettingsToStorage(t);const s=document.getElementById("appSettingsShowFileBrowser");s&&(s.checked=!1);const n=document.querySelector(".btn-file-viewer");n&&n.setAttribute("aria-expanded","false")},async openFilePreview(e,t=this.activeSessionId,s=null){if(!t||!e)return;const n=this.$("filePreviewOverlay"),a=this.$("filePreviewTitle"),i=this.$("filePreviewBody"),r=this.$("filePreviewFooter");if(!n||!i)return;n.classList.add("visible"),a.textContent=e,i.innerHTML='<div class="binary-message">Loading...</div>',r.textContent="";const o=(e.split(".").pop()||"").toLowerCase();if(s){const l=`/api/sessions/${t}/attachments/${encodeURIComponent(s)}`,d=new Set(["png","jpg","jpeg","gif","webp","bmp","svg"]);if(r.textContent=o.toUpperCase(),d.has(o))i.innerHTML=`<img src="${escapeHtml(`${l}/raw`)}" alt="${escapeHtml(e)}">`;else if(o==="pdf")i.innerHTML=`<iframe src="${escapeHtml(`${l}/raw`)}" title="${escapeHtml(e)}"></iframe>`;else if(o==="docx"||o==="pptx")i.innerHTML=`<iframe src="${escapeHtml(`${l}/preview`)}" title="${escapeHtml(e)}"></iframe>`;else try{const c=await fetch(`${l}/raw`);if(!c.ok)throw new Error("Failed to load attachment");const m=await c.text();i.innerHTML=`<pre><code>${escapeHtml(m)}</code></pre>`}catch(c){i.innerHTML=`<div class="binary-message">Error: ${escapeHtml(c.message)}</div>`}return}if(o==="docx"||o==="pptx"){r.textContent=o.toUpperCase();const l=`/api/sessions/${t}/file-preview?path=${encodeURIComponent(e)}`;i.innerHTML=`<iframe src="${escapeHtml(l)}" title="${escapeHtml(e)}"></iframe>`;return}if(o==="pdf"){r.textContent="PDF";const l=`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}`;i.innerHTML=`<iframe src="${escapeHtml(l)}" title="${escapeHtml(e)}"></iframe>`;return}if(o==="svg"){r.textContent="SVG";try{const l=await fetch(`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}`);if(!l.ok)throw new Error("Failed to load image");const d=URL.createObjectURL(new Blob([await l.text()],{type:"image/svg+xml"}));i.innerHTML=`<img src="${d}" alt="${escapeHtml(e)}">`;const c=i.querySelector("img");c&&(c.onload=()=>URL.revokeObjectURL(d))}catch(l){i.innerHTML=`<div class="binary-message">Error: ${escapeHtml(l.message)}</div>`}return}try{const l=await fetch(`/api/sessions/${t}/file-content?path=${encodeURIComponent(e)}&lines=500`);if(!l.ok)throw new Error("Failed to load file");const d=await l.json();if(!d.success)throw new Error(d.error||"Failed to load file");const c=d.data;if(c.type==="image")i.innerHTML=`<img src="${c.url}" alt="${escapeHtml(e)}">`,r.textContent=`${this.formatFileSize(c.size)} \u2022 ${c.extension}`;else if(c.type==="video")i.innerHTML=`<video src="${c.url}" controls autoplay></video>`,r.textContent=`${this.formatFileSize(c.size)} \u2022 ${c.extension}`;else if(c.type==="audio")i.innerHTML=`<audio src="${c.url}" controls autoplay></audio>`,r.textContent=`${this.formatFileSize(c.size)} \u2022 ${c.extension}`;else if(c.type==="binary"){const m=`/api/sessions/${t}/file-raw?path=${encodeURIComponent(e)}&download=true`;i.innerHTML=`<div class="binary-message">Binary file (${this.formatFileSize(c.size)})<br>Cannot preview<br><a href="${escapeHtml(m)}" download>Download</a></div>`,r.textContent=c.extension||"binary"}else{this.filePreviewContent=c.content,i.innerHTML=`<pre><code>${escapeHtml(c.content)}</code></pre>`;const m=c.truncated?` (showing 500/${c.totalLines} lines)`:"";r.textContent=`${c.totalLines} lines \u2022 ${this.formatFileSize(c.size)}${m}`}}catch(l){console.error("Failed to preview file:",l),i.innerHTML=`<div class="binary-message">Error: ${escapeHtml(l.message)}</div>`}},closeFilePreview(){const e=this.$("filePreviewOverlay");e&&e.classList.remove("visible"),this.filePreviewContent=""},_onAttachmentDetected(e){if(console.log("[Attachment Detected]",e),this.addAttachmentCard(e),e.sessionId){const t=this.attachmentHistoryCounts.get(e.sessionId)??this.sessions.get(e.sessionId)?.attachmentHistory?.length??0;this.attachmentHistoryCounts.set(e.sessionId,Math.min(t+1,100)),e.sessionId===this.activeSessionId&&(this.updateAttachmentHistoryBadge(),this.attachmentHistoryDrawerOpen&&this._debouncedCall("attachmentHistoryRefresh",()=>{this.attachmentHistoryDrawerOpen&&this.activeSessionId===e.sessionId&&this.loadAttachmentHistory(e.sessionId)},250))}},ensureAttachmentCardStack(){let e=this.attachmentCardStack||document.getElementById("attachmentCardStack");return e||(e=document.createElement("div"),e.id="attachmentCardStack",e.className="attachment-card-stack",document.body.appendChild(e)),this.attachmentCardStack=e,e},openAttachmentInNewTab(e,t,s=null){const n=s?`/api/sessions/${e}/attachments/${encodeURIComponent(s)}/raw`:`/api/sessions/${e}/file-raw?path=${encodeURIComponent(t)}`;window.open(n,"_blank")},addAttachmentCard(e){const{sessionId:t,relativePath:s,fileName:n,timestamp:a,size:i,attachmentType:r,extension:o,attachmentId:l,rawUrl:d,previewUrl:c,thumbnailUrl:m}=e,u=s||n,h=l||`${t}-${a}-${n}`;if(this.attachmentCards.has(h)){this.attachmentCards.get(h).element.focus?.();return}if(this.attachmentCards.size>=10){const I=this.attachmentCards.keys().next().value;I&&this.closeAttachmentCard(I)}const y=this.ensureAttachmentCardStack(),f=this.sessions.get(t)?.name||t.substring(0,8),v=d||(l?`/api/sessions/${t}/attachments/${encodeURIComponent(l)}/raw`:`/api/sessions/${t}/file-raw?path=${encodeURIComponent(u)}`),T=c||(l?`/api/sessions/${t}/attachments/${encodeURIComponent(l)}/preview`:null),g=m||(l?`/api/sessions/${t}/attachments/${encodeURIComponent(l)}/thumbnail`:`/api/sessions/${t}/file-thumbnail?path=${encodeURIComponent(u)}`),S=l?`${v}?download=true`:`${v}&download=true`,$=(o||r||"file").toUpperCase(),w=document.createElement("article");w.className=`attachment-card attachment-${escapeHtml(r||"file")}`,w.tabIndex=0,w.dataset.attachmentId=h,w.dataset.previewUrl=T||"",w.innerHTML=`
|
|
232
232
|
<div class="attachment-thumbnail">
|
|
233
233
|
${g?`<img class="attachment-thumbnail-img" src="${escapeHtml(g)}" alt="">`:""}
|
|
234
234
|
<div class="attachment-thumbnail-fallback ${g?"":"visible"}">${escapeHtml($)}</div>
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
</div>
|
|
247
247
|
</div>
|
|
248
248
|
<button type="button" class="attachment-close-btn" title="Dismiss">×</button>
|
|
249
|
-
`;const D=
|
|
249
|
+
`;const D=w.querySelector(".attachment-thumbnail-img");D&&(D.onerror=()=>{D.remove(),w.querySelector(".attachment-thumbnail-fallback")?.classList.add("visible")}),w.querySelector(".attachment-preview-btn")?.addEventListener("click",()=>{this.openFilePreview(u,t,l||null)}),w.querySelector(".attachment-open-btn")?.addEventListener("click",()=>{this.openAttachmentInNewTab(t,u,l||null)}),w.querySelector(".attachment-close-btn")?.addEventListener("click",()=>{this.closeAttachmentCard(h)}),y.prepend(w),this.attachmentCards.set(h,{element:w,sessionId:t,filePath:u}),this._refreshAttachmentClearAll()},_refreshAttachmentClearAll(){const e=this.attachmentCardStack;if(!e)return;let t=e.querySelector(".attachment-clear-all");if(this.attachmentCards.size<2){t&&(t.hidden=!0);return}t||(t=document.createElement("button"),t.type="button",t.className="attachment-clear-all",t.textContent="Clear all",t.title="Dismiss all attachment cards",t.addEventListener("click",()=>this.closeAllAttachmentCards()),e.prepend(t)),t.hidden=!1},closeAttachmentCard(e){const t=this.attachmentCards.get(e);t&&(t.element.remove(),this.attachmentCards.delete(e),this.attachmentCardStack&&this.attachmentCards.size===0?(this.attachmentCardStack.remove(),this.attachmentCardStack=null):this._refreshAttachmentClearAll())},closeAllAttachmentCards(){for(const e of[...this.attachmentCards.keys()])this.closeAttachmentCard(e)},closeSessionAttachmentCards(e){const t=[];for(const[s,n]of this.attachmentCards)n.sessionId===e&&t.push(s);for(const s of t)this.closeAttachmentCard(s)},updateAttachmentHistoryBadge(e=null){const t=document.getElementById("attachmentHistoryBadge"),s=document.getElementById("attachmentsHistoryBtn"),n=this.activeSessionId,a=e??(n&&this.attachmentHistoryCounts.get(n)||0);t&&(t.textContent=a>99?"99+":String(a),t.style.display=a>0?"":"none"),s&&(s.classList.toggle("active",this.attachmentHistoryDrawerOpen),s.setAttribute("aria-expanded",this.attachmentHistoryDrawerOpen?"true":"false"))},ensureAttachmentHistoryDrawer(){let e=document.getElementById("attachmentHistoryDrawer");return e||(e=document.createElement("aside"),e.id="attachmentHistoryDrawer",e.className="attachment-history-drawer",e.setAttribute("aria-label","Attachment history"),e.innerHTML=`
|
|
250
250
|
<div class="attachment-history-header">
|
|
251
251
|
<div>
|
|
252
252
|
<div class="attachment-history-title">Attachments</div>
|
|
@@ -296,12 +296,12 @@
|
|
|
296
296
|
<div class="log-viewer-window-body" id="log-viewer-body-${s}">
|
|
297
297
|
<div class="log-info">Connecting to ${escapeHtml(e)}...</div>
|
|
298
298
|
</div>
|
|
299
|
-
`,document.body.appendChild(o);const l=this.makeWindowDraggable(o,o.querySelector(".log-viewer-window-header")),d=new EventSource(`/api/sessions/${t}/tail-file?path=${encodeURIComponent(e)}&lines=50`);d.onmessage=c=>{const m=JSON.parse(c.data),u=document.getElementById(`log-viewer-body-${s}`);if(u)switch(m.type){case"connected":u.innerHTML="";break;case"data":const h=u.scrollTop+u.clientHeight>=u.scrollHeight-10,p=escapeHtml(m.content);u.innerHTML+=p,h&&(u.scrollTop=u.scrollHeight),u.innerHTML.length>5e5&&(u.innerHTML=u.innerHTML.slice(-4e5));break;case"end":this.updateLogViewerStatus(s,"disconnected","ended");break;case"error":u.innerHTML+=`<div class="log-error">${escapeHtml(m.error)}</div>`,this.updateLogViewerStatus(s,"error","error");break}},d.onerror=()=>{this.updateLogViewerStatus(s,"disconnected","connection error")},this.logViewerWindows.set(s,{element:o,eventSource:d,filePath:e,sessionId:t,dragListeners:l})},updateLogViewerStatus(e,t,s){const n=document.querySelector(`#log-viewer-window-${e} .status`);n&&(n.className=`status ${t}`,n.textContent=s)},closeLogViewerWindow(e){const t=this.logViewerWindows.get(e);t&&(t.eventSource&&t.eventSource.close(),t.dragListeners&&(document.removeEventListener("mousemove",t.dragListeners.move),document.removeEventListener("mouseup",t.dragListeners.up),t.dragListeners.handle&&(t.dragListeners.handle.removeEventListener("mousedown",t.dragListeners.handleMouseDown),t.dragListeners.handle.removeEventListener("touchstart",t.dragListeners.handleTouchStart))),t.element.remove(),this.logViewerWindows.delete(e))},closeSessionLogViewerWindows(e){const t=[];for(const[s,n]of this.logViewerWindows)n.sessionId===e&&t.push(s);for(const s of t)this.closeLogViewerWindow(s)},openImagePopup(e){const{sessionId:t,filePath:s,relativePath:n,fileName:a,timestamp:i,size:r}=e,o=`${t}-${i}`;if(this.imagePopups.has(o)){const g=this.imagePopups.get(o);g.element.style.zIndex=++this.imagePopupZIndex;return}if(this.imagePopups.size>=20){const g=this.imagePopups.keys().next().value;g&&this.closeImagePopup(g)}const d=this.imagePopups.size,c=(window.innerWidth-600)/2,m=(window.innerHeight-500)/2,u=c+d%5*30,h=m+d%5*30,
|
|
299
|
+
`,document.body.appendChild(o);const l=this.makeWindowDraggable(o,o.querySelector(".log-viewer-window-header")),d=new EventSource(`/api/sessions/${t}/tail-file?path=${encodeURIComponent(e)}&lines=50`);d.onmessage=c=>{const m=JSON.parse(c.data),u=document.getElementById(`log-viewer-body-${s}`);if(u)switch(m.type){case"connected":u.innerHTML="";break;case"data":const h=u.scrollTop+u.clientHeight>=u.scrollHeight-10,p=escapeHtml(m.content);u.innerHTML+=p,h&&(u.scrollTop=u.scrollHeight),u.innerHTML.length>5e5&&(u.innerHTML=u.innerHTML.slice(-4e5));break;case"end":this.updateLogViewerStatus(s,"disconnected","ended");break;case"error":u.innerHTML+=`<div class="log-error">${escapeHtml(m.error)}</div>`,this.updateLogViewerStatus(s,"error","error");break}},d.onerror=()=>{this.updateLogViewerStatus(s,"disconnected","connection error")},this.logViewerWindows.set(s,{element:o,eventSource:d,filePath:e,sessionId:t,dragListeners:l})},updateLogViewerStatus(e,t,s){const n=document.querySelector(`#log-viewer-window-${e} .status`);n&&(n.className=`status ${t}`,n.textContent=s)},closeLogViewerWindow(e){const t=this.logViewerWindows.get(e);t&&(t.eventSource&&t.eventSource.close(),t.dragListeners&&(document.removeEventListener("mousemove",t.dragListeners.move),document.removeEventListener("mouseup",t.dragListeners.up),t.dragListeners.handle&&(t.dragListeners.handle.removeEventListener("mousedown",t.dragListeners.handleMouseDown),t.dragListeners.handle.removeEventListener("touchstart",t.dragListeners.handleTouchStart))),t.element.remove(),this.logViewerWindows.delete(e))},closeSessionLogViewerWindows(e){const t=[];for(const[s,n]of this.logViewerWindows)n.sessionId===e&&t.push(s);for(const s of t)this.closeLogViewerWindow(s)},openImagePopup(e){const{sessionId:t,filePath:s,relativePath:n,fileName:a,timestamp:i,size:r}=e,o=`${t}-${i}`;if(this.imagePopups.has(o)){const g=this.imagePopups.get(o);g.element.style.zIndex=++this.imagePopupZIndex;return}if(this.imagePopups.size>=20){const g=this.imagePopups.keys().next().value;g&&this.closeImagePopup(g)}const d=this.imagePopups.size,c=(window.innerWidth-600)/2,m=(window.innerHeight-500)/2,u=c+d%5*30,h=m+d%5*30,y=this.sessions.get(t)?.name||t.substring(0,8),b=(r/1024).toFixed(1),f=`/api/sessions/${t}/file-raw?path=${encodeURIComponent(n||a)}`,v=document.createElement("div");v.className="image-popup-window",v.id=`image-popup-${o}`,v.style.left=`${u}px`,v.style.top=`${h}px`,v.style.zIndex=++this.imagePopupZIndex,v.innerHTML=`
|
|
300
300
|
<div class="image-popup-header">
|
|
301
301
|
<div class="image-popup-title" title="${escapeHtml(s)}">
|
|
302
302
|
<span class="icon">\u{1F5BC}\uFE0F</span>
|
|
303
303
|
<span class="filename">${escapeHtml(a)}</span>
|
|
304
|
-
<span class="session-badge">${escapeHtml(
|
|
304
|
+
<span class="session-badge">${escapeHtml(y)}</span>
|
|
305
305
|
<span class="size-badge">${b} KB</span>
|
|
306
306
|
</div>
|
|
307
307
|
<div class="image-popup-actions">
|
|
@@ -314,13 +314,13 @@
|
|
|
314
314
|
onerror="this.parentElement.innerHTML='<div class=\\'image-error\\'>Failed to load image</div>'"
|
|
315
315
|
onclick="app.openImageInNewTab(${escapeHtml(JSON.stringify(f))})" />
|
|
316
316
|
</div>
|
|
317
|
-
`,document.body.appendChild(v);const T=this.makeWindowDraggable(v,v.querySelector(".image-popup-header"));v.addEventListener("mousedown",()=>{v.style.zIndex=++this.imagePopupZIndex}),this.imagePopups.set(o,{element:v,sessionId:t,filePath:s,dragListeners:T})},closeImagePopup(e){const t=this.imagePopups.get(e);t&&(t.dragListeners&&(document.removeEventListener("mousemove",t.dragListeners.move),document.removeEventListener("mouseup",t.dragListeners.up),t.dragListeners.touchMove&&(document.removeEventListener("touchmove",t.dragListeners.touchMove),document.removeEventListener("touchend",t.dragListeners.up),document.removeEventListener("touchcancel",t.dragListeners.up)),t.dragListeners.handle&&(t.dragListeners.handle.removeEventListener("mousedown",t.dragListeners.handleMouseDown),t.dragListeners.handle.removeEventListener("touchstart",t.dragListeners.handleTouchStart))),t.element.remove(),this.imagePopups.delete(e))},openImageInNewTab(e){window.open(e,"_blank")},closeSessionImagePopups(e){const t=[];for(const[s,n]of this.imagePopups)n.sessionId===e&&t.push(s);for(const s of t)this.closeImagePopup(s)},async loadMuxSessions(){try{const t=await(await fetch("/api/mux-sessions")).json();this.muxSessions=t.data?.sessions||[],this.renderMuxSessions()}catch(e){console.error("Failed to load mux sessions:",e)}},killAllMuxSessions(){const e=this.muxSessions?.length||0;if(e===0){alert("No sessions to kill");return}document.getElementById("killAllCount").textContent=e;const t=document.getElementById("killAllModal");t.classList.add("active"),this.activeFocusTrap=new FocusTrap(t),this.activeFocusTrap.activate()},closeKillAllModal(){document.getElementById("killAllModal").classList.remove("active"),this.activeFocusTrap&&(this.activeFocusTrap.deactivate(),this.activeFocusTrap=null)},async confirmKillAll(e){this.closeKillAllModal();try{if(e){if((await(await fetch("/api/sessions",{method:"DELETE"})).json()).success){this.sessions.clear(),this.muxSessions=[],this.activeSessionId=null;try{localStorage.removeItem("codeman-active-session")}catch{}this.renderSessionTabs(),this.renderMuxSessions(),this.terminal.clear(),this.terminal.reset(),this.toast("All sessions and tmux killed","success")}}else{this.sessions.clear(),this.activeSessionId=null;try{localStorage.removeItem("codeman-active-session")}catch{}this.renderSessionTabs(),this.terminal.clear(),this.terminal.reset(),this.toast("All tabs removed, tmux still running","info")}}catch(t){console.error("Failed to kill sessions:",t),this.toast("Failed to kill sessions: "+t.message,"error")}},renderMuxSessions(){this._debouncedCall("muxSessions",this._renderMuxSessionsImmediate)},_renderMuxSessionsImmediate(){const e=document.getElementById("muxSessionsBody");if(!this.muxSessions||this.muxSessions.length===0){e.innerHTML='<div class="monitor-empty">No mux sessions</div>';return}let t="";for(const s of this.muxSessions){const n=s.stats||{memoryMB:0,cpuPercent:0,childCount:0},a=this.sessions.get(s.sessionId),i=a?a.status:"unknown",r=a?a.isWorking:!1;let o,l;i==="idle"&&!r?(o="IDLE",l="status-idle"):i==="busy"||r?(o="WORKING",l="status-working"):i==="stopped"?(o="STOPPED",l="status-stopped"):(o=i.toUpperCase(),l="");const d=a&&a.tokens?a.tokens:null,c=a?a.totalCost:0,m=a&&a.cliModel||"",u=m.includes("opus")?"opus":m.includes("sonnet")?"sonnet":m.includes("haiku")?"haiku":"",h=a?a.ralphTodoStats:null;let p="";if(h&&h.total>0){const T=Math.round(h.completed/h.total*100);p=`<span class="process-stat todo-progress">${h.completed}/${h.total} (${T}%)</span>`}let
|
|
317
|
+
`,document.body.appendChild(v);const T=this.makeWindowDraggable(v,v.querySelector(".image-popup-header"));v.addEventListener("mousedown",()=>{v.style.zIndex=++this.imagePopupZIndex}),this.imagePopups.set(o,{element:v,sessionId:t,filePath:s,dragListeners:T})},closeImagePopup(e){const t=this.imagePopups.get(e);t&&(t.dragListeners&&(document.removeEventListener("mousemove",t.dragListeners.move),document.removeEventListener("mouseup",t.dragListeners.up),t.dragListeners.touchMove&&(document.removeEventListener("touchmove",t.dragListeners.touchMove),document.removeEventListener("touchend",t.dragListeners.up),document.removeEventListener("touchcancel",t.dragListeners.up)),t.dragListeners.handle&&(t.dragListeners.handle.removeEventListener("mousedown",t.dragListeners.handleMouseDown),t.dragListeners.handle.removeEventListener("touchstart",t.dragListeners.handleTouchStart))),t.element.remove(),this.imagePopups.delete(e))},openImageInNewTab(e){window.open(e,"_blank")},closeSessionImagePopups(e){const t=[];for(const[s,n]of this.imagePopups)n.sessionId===e&&t.push(s);for(const s of t)this.closeImagePopup(s)},async loadMuxSessions(){try{const t=await(await fetch("/api/mux-sessions")).json();this.muxSessions=t.data?.sessions||[],this.renderMuxSessions()}catch(e){console.error("Failed to load mux sessions:",e)}},killAllMuxSessions(){const e=this.muxSessions?.length||0;if(e===0){alert("No sessions to kill");return}document.getElementById("killAllCount").textContent=e;const t=document.getElementById("killAllModal");t.classList.add("active"),this.activeFocusTrap=new FocusTrap(t),this.activeFocusTrap.activate()},closeKillAllModal(){document.getElementById("killAllModal").classList.remove("active"),this.activeFocusTrap&&(this.activeFocusTrap.deactivate(),this.activeFocusTrap=null)},async confirmKillAll(e){this.closeKillAllModal();try{if(e){if((await(await fetch("/api/sessions",{method:"DELETE"})).json()).success){this.sessions.clear(),this.muxSessions=[],this.activeSessionId=null;try{localStorage.removeItem("codeman-active-session")}catch{}this.renderSessionTabs(),this.renderMuxSessions(),this.terminal.clear(),this.terminal.reset(),this.toast("All sessions and tmux killed","success")}}else{this.sessions.clear(),this.activeSessionId=null;try{localStorage.removeItem("codeman-active-session")}catch{}this.renderSessionTabs(),this.terminal.clear(),this.terminal.reset(),this.toast("All tabs removed, tmux still running","info")}}catch(t){console.error("Failed to kill sessions:",t),this.toast("Failed to kill sessions: "+t.message,"error")}},renderMuxSessions(){this._debouncedCall("muxSessions",this._renderMuxSessionsImmediate)},_renderMuxSessionsImmediate(){const e=document.getElementById("muxSessionsBody");if(!this.muxSessions||this.muxSessions.length===0){e.innerHTML='<div class="monitor-empty">No mux sessions</div>';return}let t="";for(const s of this.muxSessions){const n=s.stats||{memoryMB:0,cpuPercent:0,childCount:0},a=this.sessions.get(s.sessionId),i=a?a.status:"unknown",r=a?a.isWorking:!1;let o,l;i==="idle"&&!r?(o="IDLE",l="status-idle"):i==="busy"||r?(o="WORKING",l="status-working"):i==="stopped"?(o="STOPPED",l="status-stopped"):(o=i.toUpperCase(),l="");const d=a&&a.tokens?a.tokens:null,c=a?a.totalCost:0,m=a&&a.cliModel||"",u=m.includes("opus")?"opus":m.includes("sonnet")?"sonnet":m.includes("haiku")?"haiku":"",h=a?a.ralphTodoStats:null;let p="";if(h&&h.total>0){const T=Math.round(h.completed/h.total*100);p=`<span class="process-stat todo-progress">${h.completed}/${h.total} (${T}%)</span>`}let y="";d&&d.total>0&&(y=`<span class="process-stat tokens">${(d.total/1e3).toFixed(1)}k tok</span>`);let b="";c>0&&(b=`<span class="process-stat cost">$${c.toFixed(2)}</span>`);let f="";u&&(f=`<span class="monitor-model-badge ${u}">${u}</span>`);const v=escapeHtml(JSON.stringify(s.sessionId));t+=`
|
|
318
318
|
<div class="process-item process-item-clickable" onclick="app.selectSession(${v})" title="Switch to session">
|
|
319
319
|
<span class="monitor-status-badge ${l}">${o}</span>
|
|
320
320
|
<div class="process-info">
|
|
321
321
|
<div class="process-name">${f} ${escapeHtml(s.name||s.muxName)}</div>
|
|
322
322
|
<div class="process-meta">
|
|
323
|
-
${
|
|
323
|
+
${y}
|
|
324
324
|
${b}
|
|
325
325
|
${p}
|
|
326
326
|
<span class="process-stat memory">${n.memoryMB}MB</span>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|