impactus-swarm 0.0.32 → 0.0.34
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/package.json +1 -1
- package/server/main.js +9 -8
- package/web/assets/index-Bm9oF2VR.js +2053 -0
- package/web/assets/index-C6U1nTzm.css +32 -0
- package/web/assets/index-CJ1iMK54.css +32 -0
- package/web/assets/index-Ctaw7WbL.js +2053 -0
- package/web/index.html +2 -2
package/package.json
CHANGED
package/server/main.js
CHANGED
|
@@ -33,13 +33,14 @@ set -gx TERM_PROGRAM impactus-swarm
|
|
|
33
33
|
`.trim();default:return""}}static detectShell(e){return e.includes("zsh")?"zsh":e.includes("bash")?"bash":e.includes("fish")?"fish":"unknown"}static getEnvVars(e){return{TERM_PROGRAM:"impactus-swarm",__IMPACTUS_SHELL_INTEGRATION:"1"}}static async createInjectionEnv(e){if(e==="unknown"||e==="fish")return a.getEnvVars(e);try{let t=pe(la(),"impactus-shell-integration");if(await Vt(t,{recursive:!0}),process.platform!=="win32"&&await ca(t,448),e==="zsh"){let r=pe(t,"zsh");await Vt(r,{recursive:!0});let s=["# IMPACTUS Swarm Shell Integration","# Source original zshrc",'if [[ -f "$HOME/.zshrc" ]]; then',' ZDOTDIR="$HOME" source "$HOME/.zshrc"',"fi","",a.getInitScript("zsh")].join(`
|
|
34
34
|
`);await zt(pe(r,".zshrc"),s,"utf-8");let n=["# Source original zshenv",'if [[ -f "$HOME/.zshenv" ]]; then',' ZDOTDIR="$HOME" source "$HOME/.zshenv"',"fi"].join(`
|
|
35
35
|
`);return await zt(pe(r,".zshenv"),n,"utf-8"),{...a.getEnvVars("zsh"),ZDOTDIR:r}}if(e==="bash"){let r=pe(t,"bash");await Vt(r,{recursive:!0});let s=["# IMPACTUS Swarm Shell Integration","# Source original bashrc",'if [[ -f "$HOME/.bashrc" ]]; then',' source "$HOME/.bashrc"',"fi","",a.getInitScript("bash")].join(`
|
|
36
|
-
`),n=pe(r,".bashrc_impactus");return await zt(n,s,"utf-8"),{...a.getEnvVars("bash"),BASH_ENV:n}}}catch{}return a.getEnvVars(e)}};var pa=da(import.meta.url),qr=pa("node-pty");function Hr(){return process.platform==="win32"?process.env.COMSPEC||"cmd.exe":process.env.SHELL||"/bin/zsh"}async function Jt(){let a=Hr(),e=Ie.detectShell(a);return Ie.createInjectionEnv(e)}async function Qt(a){let e=Hr(),t=[],r=await Jt(),{PORT:s,IMPACTUS_WEB_DIR:n,RELAY_URL:i,RELAY_ALLOWED_IPS:o,CLAUDECODE:c,...l}=process.env;return qr.spawn(e,t,{name:"xterm-256color",cols:a.cols,rows:a.rows,cwd:a.cwd,env:{...l,...r,TERM_PROGRAM:"ghostty",TERM_PROGRAM_VERSION:"3.0.0",KITTY_WINDOW_ID:"1",COLORTERM:"truecolor",...a.env}})}function Zt(a,e,t){return qr.spawn("tmux",a,{name:"xterm-256color",cols:e,rows:t,cwd:ua()})}import{execFileSync as
|
|
36
|
+
`),n=pe(r,".bashrc_impactus");return await zt(n,s,"utf-8"),{...a.getEnvVars("bash"),BASH_ENV:n}}}catch{}return a.getEnvVars(e)}};var pa=da(import.meta.url),qr=pa("node-pty");function Hr(){return process.platform==="win32"?process.env.COMSPEC||"cmd.exe":process.env.SHELL||"/bin/zsh"}async function Jt(){let a=Hr(),e=Ie.detectShell(a);return Ie.createInjectionEnv(e)}async function Qt(a){let e=Hr(),t=[],r=await Jt(),{PORT:s,IMPACTUS_WEB_DIR:n,RELAY_URL:i,RELAY_ALLOWED_IPS:o,CLAUDECODE:c,...l}=process.env;return qr.spawn(e,t,{name:"xterm-256color",cols:a.cols,rows:a.rows,cwd:a.cwd,env:{...l,...r,TERM_PROGRAM:"ghostty",TERM_PROGRAM_VERSION:"3.0.0",KITTY_WINDOW_ID:"1",COLORTERM:"truecolor",...a.env}})}function Zt(a,e,t){return qr.spawn("tmux",a,{name:"xterm-256color",cols:e,rows:t,cwd:ua()})}import{execFileSync as N,execFile as ma}from"node:child_process";import{existsSync as ga,writeFileSync as ha,mkdirSync as fa}from"node:fs";import{join as Xr}from"node:path";import{homedir as wa}from"node:os";import{promisify as Sa}from"node:util";var Ta=Sa(ma),L="impactus",Fe="impactus-",R=class{static _available=null;static _configPath=null;static isAvailable(){if(this._available!==null)return this._available;if(process.platform==="win32")return this._available=!1,!1;try{N("tmux",["-V"],{stdio:"pipe"}),this._available=!0}catch{this._available=!1}return this._available}static ensureConfig(){if(this._configPath)return this._configPath;let e=Xr(wa(),".impactus-swarm");ga(e)||fa(e,{recursive:!0});let t=Xr(e,"tmux.conf");return ha(t,["# IMPACTUS Swarm tmux config \u2014 auto-generated, do not edit","set -g status off","set -g history-limit 50000",'set -g default-terminal "xterm-256color"',"set -g escape-time 10","set -g focus-events on","set -g mouse off","# Suppress DA queries \u2014 tell tmux the outer terminal capabilities","# Disable smcup/rmcup so tmux does NOT enter alternate screen in","# xterm.js \u2014 this allows xterm.js scrollback to accumulate normally.","# TUI apps inside tmux still use tmux's internal alternate screen.",'set -as terminal-overrides ",xterm*:Tc:smcup@:rmcup@"'].join(`
|
|
37
37
|
`)+`
|
|
38
|
-
`),this._configPath=t,t}static enablePassthrough(){try{
|
|
39
|
-
`).filter(t=>t.startsWith(Fe)):[]}catch{return[]}}static hasSession(e){try{return
|
|
40
|
-
`)}catch{return""}}static
|
|
41
|
-
|
|
42
|
-
`)[0],10);return isNaN(r)?null:r}catch{return null}}static
|
|
38
|
+
`),this._configPath=t,t}static enablePassthrough(){try{N("tmux",["-L",L,"set-option","-g","allow-passthrough","on"],{stdio:"pipe"})}catch{}try{N("tmux",["-L",L,"set-option","-g","escape-time","10"],{stdio:"pipe"})}catch{}}static sessionName(e){return Fe+e.replace(/[^a-zA-Z0-9_-]/g,"_")}static createSession(e,t,r,s,n,i){let o=this.sessionName(e),c=this.ensureConfig(),l=["-L",L,"-f",c,"new-session","-d","-s",o,"-x",String(t),"-y",String(r),"-c",s];for(let[f,h]of Object.entries(n))h!==void 0&&h!==""&&l.push("-e",`${f}=${h}`);if(i)for(let[f,h]of Object.entries(i))h!==void 0&&l.push("-e",`${f}=${h}`);let{PORT:d,IMPACTUS_WEB_DIR:u,RELAY_URL:m,RELAY_ALLOWED_IPS:p,...g}=process.env;N("tmux",l,{stdio:"pipe",env:g});try{N("tmux",["-L",L,"set-environment","-t",o,"IMPACTUS_TERMINAL_ID",e],{stdio:"pipe"}),N("tmux",["-L",L,"set-environment","-t",o,"IMPACTUS_CREATED_AT",String(Date.now())],{stdio:"pipe"})}catch{}return this.enablePassthrough(),o}static getAttachArgs(e){return["-L",L,"attach-session","-t",e]}static killSession(e){try{N("tmux",["-L",L,"kill-session","-t",e],{stdio:"pipe"})}catch{}}static listSessions(){try{let e=N("tmux",["-L",L,"list-sessions","-F","#{session_name}"],{stdio:"pipe"}).toString().trim();return e?e.split(`
|
|
39
|
+
`).filter(t=>t.startsWith(Fe)):[]}catch{return[]}}static hasSession(e){try{return N("tmux",["-L",L,"has-session","-t",e],{stdio:"pipe"}),!0}catch{return!1}}static getTerminalId(e){try{let r=N("tmux",["-L",L,"show-environment","-t",e,"IMPACTUS_TERMINAL_ID"],{stdio:"pipe"}).toString().trim().match(/^IMPACTUS_TERMINAL_ID=(.+)$/);return r?r[1]:null}catch{return e.startsWith(Fe)?e.slice(Fe.length):null}}static getCreatedAt(e){try{let r=N("tmux",["-L",L,"show-environment","-t",e,"IMPACTUS_CREATED_AT"],{stdio:"pipe"}).toString().trim().match(/^IMPACTUS_CREATED_AT=(\d+)$/);if(r)return parseInt(r[1],10)}catch{}return null}static capturePane(e){try{return N("tmux",["-L",L,"capture-pane","-t",e,"-p","-e"],{stdio:"pipe",maxBuffer:10485760}).toString().replace(/\n+$/,`
|
|
40
|
+
`)}catch{return""}}static capturePaneScrollback(e,t=5e3){try{let s=N("tmux",["-L",L,"capture-pane","-t",e,"-p","-e","-S",String(-t),"-E","-1"],{stdio:"pipe",maxBuffer:10485760}).toString().replace(/^\n+/,"").replace(/\n+$/,"");return s?s+`
|
|
41
|
+
`:""}catch{return""}}static getShellPid(e){try{let t=N("tmux",["-L",L,"list-panes","-t",e,"-F","#{pane_pid}"],{stdio:"pipe"}).toString().trim(),r=parseInt(t.split(`
|
|
42
|
+
`)[0],10);return isNaN(r)?null:r}catch{return null}}static async getShellPidAsync(e){try{let{stdout:t}=await Ta("tmux",["-L",L,"list-panes","-t",e,"-F","#{pane_pid}"]),r=parseInt(t.trim().split(`
|
|
43
|
+
`)[0],10);return isNaN(r)?null:r}catch{return null}}static resizeSession(e,t,r){try{N("tmux",["-L",L,"resize-window","-t",e,"-x",String(t),"-y",String(r)],{stdio:"pipe"})}catch{}}static getCursorPosition(e){try{let r=N("tmux",["-L",L,"display-message","-t",e,"-p","#{cursor_x} #{cursor_y}"],{stdio:"pipe"}).toString().trim().split(" "),s=parseInt(r[0],10),n=parseInt(r[1],10);if(!isNaN(s)&&!isNaN(n))return{x:s,y:n}}catch{}return null}static getSessionSize(e){try{let r=N("tmux",["-L",L,"display-message","-t",e,"-p","#{window_width} #{window_height}"],{stdio:"pipe"}).toString().trim().split(" "),s=parseInt(r[0],10),n=parseInt(r[1],10);if(!isNaN(s)&&!isNaN(n))return{cols:s,rows:n}}catch{}return null}static killAllSessions(){let e=this.listSessions();for(let t of e)this.killSession(t)}static killServer(){try{N("tmux",["-L",L,"kill-server"],{stdio:"pipe"})}catch{}}};import{randomUUID as Ea}from"node:crypto";var Ce=class a{activeBlocks=new Map;lineCounters=new Map;partialBuffers=new Map;static OSC_PROMPT_START=/\x1b\]133;A(?:\x1b\\|\x07)/g;static OSC_COMMAND_EXEC=/\x1b\]133;C(?:\x1b\\|\x07)/g;static OSC_COMMAND_END=/\x1b\]133;D;?(\d*)(?:\x1b\\|\x07)/g;static PARTIAL_OSC=/\x1b(?:\](?:1(?:3(?:3(?:;(?:[A-D](?:;?\d*)?)?)?)?)?)?)?$/;parse(e,t){let r=[],n=(this.partialBuffers.get(t)||"")+e;this.partialBuffers.delete(t);let i=a.PARTIAL_OSC.exec(n),o;i?(this.partialBuffers.set(t,i[0]),o=n.slice(0,i.index)):o=n;let c=(o.match(/\n/g)||[]).length,l=this.lineCounters.get(t)||0,d=[];a.OSC_PROMPT_START.lastIndex=0,a.OSC_COMMAND_EXEC.lastIndex=0,a.OSC_COMMAND_END.lastIndex=0;let u;for(;(u=a.OSC_PROMPT_START.exec(o))!==null;)d.push({type:"A",index:u.index});for(;(u=a.OSC_COMMAND_EXEC.exec(o))!==null;)d.push({type:"C",index:u.index});for(;(u=a.OSC_COMMAND_END.exec(o))!==null;)d.push({type:"D",index:u.index,exitCode:u[1]?parseInt(u[1],10):0});d.sort((m,p)=>m.index-p.index);for(let m of d)switch(m.type){case"A":{let p={id:Ea(),terminalId:t,status:"prompting",startTime:new Date().toISOString(),lineStart:l};this.activeBlocks.set(t,p),r.push({type:"block-start",terminalId:t,block:{...p}});break}case"C":{let p=this.activeBlocks.get(t);p&&(p.status="executing",r.push({type:"block-executing",terminalId:t,block:{...p}}));break}case"D":{let p=this.activeBlocks.get(t);p&&(p.status="completed",p.exitCode=m.exitCode,p.endTime=new Date().toISOString(),p.lineEnd=l+c,r.push({type:"block-end",terminalId:t,block:{...p}}),this.activeBlocks.delete(t));break}}return this.lineCounters.set(t,l+c),r}static stripOSC133(e){return e.replace(/\x1b\]133;[A-D];?\d*(?:\x1b\\|\x07)/g,"")}getActiveBlock(e){return this.activeBlocks.get(e)}cleanup(e){this.activeBlocks.delete(e),this.lineCounters.delete(e),this.partialBuffers.delete(e)}};var ya=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function Yr(a){return a.replace(ya,"")}var Gr=new Set(["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F","\u28FE","\u28FD","\u28FB","\u28BF","\u287F","\u28DF","\u28EF","\u28F7"]),jr=new Set(["\u273B","\u2722","\u26A1","\u25CF","\u25C9","\u25CE","\u25CB","\u25CC","\u23F5"]),va=/^[\s|/\\\-.*]+$/,ka=/^[\s─━═╌╍┄┅┈┉╴╶╸╺│┃║├┤┬┴┼╋]+$/,ba=["\u23F5\u23F5","\u273B ","\u26A1 "];function Kr(a){let e=Yr(a).trim();if(e.length===0)return!0;let t=[...e].filter(r=>r.trim().length>0);if(t.length>0&&t.length<=5&&t.every(s=>Gr.has(s)||jr.has(s))||e.length<=10&&va.test(e)||ka.test(e))return!0;for(let r of ba)if(e.startsWith(r))return!0;if(t.length>=1&&t.length<=30){let r=t[0];if(Gr.has(r)||jr.has(r))return!0}return!1}function Vr(a){if(a.length===0)return!1;if(a.includes("\r")&&!a.includes(`
|
|
43
44
|
`))return a.split("\r").filter(s=>s.length>0).every(s=>Kr(s));let t=a.split(`
|
|
44
45
|
`).filter(r=>Yr(r).trim().length>0);return t.length===0?!0:t.every(r=>Kr(r))}var Ra=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function zr(a){return a.replace(Ra,"")}var Jr=/\/\/|\/\*|^\s*#\s/,Qr=/^[+-][^+-]/,Aa=/\?\s*:|:\s*\?|\?\./,Ia=/\w\)\?\s*$|\w\?\s*;?\s*$/,Ca=/\?[a-zA-Z_]+=\S/,La=/^\s+at\s+/,Ma=/->|=>|::|!=|==/,Na=/^#{1,6}\s/,Zr=/^\s*\d+\s*[|:]\s/,Oa=/\b(?:function|def|fn|func|sub|proc)\s+\w/,es=/^(?:\s{4,}|\t)/,ts=/\b(?:import|require|from|use|include)\b.*['"`]/,Da=/\([^)]*\)\s*\?\s*$/,Pa=/[+\-*/%]=|<<=|>>=/,xa=/:\s*\w+\?\s*[;,)=]/;function rs(a){let e=zr(a).trim();return!(!e.endsWith("?")||e.length<5||Jr.test(e)||Qr.test(e)||Aa.test(e)||Ia.test(e)||Ca.test(e)||La.test(e)||Ma.test(e)||Na.test(e)||Zr.test(e)||Oa.test(e)||es.test(e)||ts.test(e)||Da.test(e)||Pa.test(e)||xa.test(e))}function ss(a){let e=zr(a).trim();return Qr.test(e)||Zr.test(e)||es.test(e)||Jr.test(e)||ts.test(e)}var $e=class{grid;cursorRow=0;cursorCol=0;rows;cols;savedCursor=null;alternateGrid=null;isAlternate=!1;parseState=0;csiParams="";constructor(e=24,t=80){this.rows=e,this.cols=t,this.grid=this.createGrid(e,t)}createGrid(e,t){let r=[];for(let s=0;s<e;s++)r.push(new Array(t).fill(" "));return r}write(e){for(let t=0;t<e.length;t++){let r=e[t],s=e.charCodeAt(t);switch(this.parseState){case 0:this.handleNormal(r,s);break;case 1:this.handleEscStart(r,s);break;case 2:this.handleCsiParam(r,s);break;case 3:s===7?this.parseState=0:s===27&&t+1<e.length&&e.charCodeAt(t+1)===92&&(t++,this.parseState=0);break}}}handleNormal(e,t){if(t===27){this.parseState=1,this.csiParams="";return}if(t===13){this.cursorCol=0;return}if(t===10){this.lineFeed();return}if(t===8){this.cursorCol>0&&this.cursorCol--;return}if(t===9){this.cursorCol=Math.min(this.cols-1,(Math.floor(this.cursorCol/8)+1)*8);return}t<32||(this.cursorRow>=0&&this.cursorRow<this.rows&&this.cursorCol>=0&&this.cursorCol<this.cols&&(this.grid[this.cursorRow][this.cursorCol]=e),this.cursorCol++,this.cursorCol>=this.cols&&(this.cursorCol=0,this.lineFeed()))}handleEscStart(e,t){if(t===91){this.parseState=2,this.csiParams="";return}if(t===93){this.parseState=3;return}if(t===55){this.savedCursor={row:this.cursorRow,col:this.cursorCol},this.parseState=0;return}if(t===56){this.savedCursor&&(this.cursorRow=this.savedCursor.row,this.cursorCol=this.savedCursor.col),this.parseState=0;return}this.parseState=0}handleCsiParam(e,t){if(t>=48&&t<=63){this.csiParams+=e;return}if(t>=32&&t<=47){this.csiParams+=e;return}if(t>=64&&t<=126){this.executeCsi(e,this.csiParams),this.parseState=0;return}this.parseState=0}executeCsi(e,t){let r=t.replace(/^\?/,"").split(";").map(i=>parseInt(i,10)||0),s=t.startsWith("?"),n=r[0]||1;switch(e){case"A":this.cursorRow=Math.max(0,this.cursorRow-n);break;case"B":this.cursorRow=Math.min(this.rows-1,this.cursorRow+n);break;case"C":this.cursorCol=Math.min(this.cols-1,this.cursorCol+n);break;case"D":this.cursorCol=Math.max(0,this.cursorCol-n);break;case"H":case"f":this.cursorRow=Math.min(this.rows-1,Math.max(0,(r[0]||1)-1)),this.cursorCol=Math.min(this.cols-1,Math.max(0,(r[1]||1)-1));break;case"J":this.eraseDisplay(r[0]||0);break;case"K":this.eraseLine(r[0]||0);break;case"m":break;case"s":this.savedCursor={row:this.cursorRow,col:this.cursorCol};break;case"u":this.savedCursor&&(this.cursorRow=this.savedCursor.row,this.cursorCol=this.savedCursor.col);break;case"h":s&&(r[0]===1049||r[0]===47)&&this.enterAlternateScreen();break;case"l":s&&(r[0]===1049||r[0]===47)&&this.leaveAlternateScreen();break;case"r":break;case"G":this.cursorCol=Math.min(this.cols-1,Math.max(0,n-1));break;case"d":this.cursorRow=Math.min(this.rows-1,Math.max(0,n-1));break;case"E":this.cursorRow=Math.min(this.rows-1,this.cursorRow+n),this.cursorCol=0;break;case"F":this.cursorRow=Math.max(0,this.cursorRow-n),this.cursorCol=0;break;default:break}}lineFeed(){this.cursorRow<this.rows-1?this.cursorRow++:(this.grid.shift(),this.grid.push(new Array(this.cols).fill(" ")))}eraseDisplay(e){switch(e){case 0:this.eraseLine(0);for(let t=this.cursorRow+1;t<this.rows;t++)this.grid[t].fill(" ");break;case 1:this.eraseLine(1);for(let t=0;t<this.cursorRow;t++)this.grid[t].fill(" ");break;case 2:case 3:for(let t=0;t<this.rows;t++)this.grid[t].fill(" ");this.cursorRow=0,this.cursorCol=0;break}}eraseLine(e){if(this.cursorRow<0||this.cursorRow>=this.rows)return;let t=this.grid[this.cursorRow];switch(e){case 0:for(let r=this.cursorCol;r<this.cols;r++)t[r]=" ";break;case 1:for(let r=0;r<=this.cursorCol&&r<this.cols;r++)t[r]=" ";break;case 2:t.fill(" ");break}}enterAlternateScreen(){this.isAlternate||(this.alternateGrid=this.grid,this.grid=this.createGrid(this.rows,this.cols),this.isAlternate=!0,this.savedCursor={row:this.cursorRow,col:this.cursorCol},this.cursorRow=0,this.cursorCol=0)}leaveAlternateScreen(){this.isAlternate&&this.alternateGrid&&(this.grid=this.alternateGrid,this.alternateGrid=null,this.isAlternate=!1,this.savedCursor&&(this.cursorRow=this.savedCursor.row,this.cursorCol=this.savedCursor.col,this.savedCursor=null))}getBottomRows(e){let t=[];for(let r=this.rows-1;r>=0&&t.length<e;r--){let s=this.grid[r].join("").trimEnd();s.length>0&&t.unshift(s)}return t}getScreen(){return this.grid.map(e=>e.join("").trimEnd())}resize(e,t){let r=this.createGrid(e,t),s=Math.min(this.rows,e),n=Math.min(this.cols,t);for(let i=0;i<s;i++)for(let o=0;o<n;o++)r[i][o]=this.grid[i][o];this.grid=r,this.rows=e,this.cols=t,this.cursorRow=Math.min(this.cursorRow,e-1),this.cursorCol=Math.min(this.cursorCol,t-1)}containsInBottom(e,t){return this.getBottomRows(t).join(`
|
|
45
46
|
`).includes(e)}};var We=class a{constructor(e,t){this.terminalId=e;this.onStateChange=t;this.startedAt=Date.now()}state="idle";lastRealOutputAt=0;idleCheckHandle=null;debouncedIdleHandle=null;startedAt;static IDLE_THRESHOLD_MS=500;static DEBOUNCE_MS=2e3;static STARTUP_GRACE_MS=1e4;inStartupGrace(){return Date.now()-this.startedAt<a.STARTUP_GRACE_MS}onRealOutput(){this.lastRealOutputAt=Date.now(),this.debouncedIdleHandle!==null&&(clearTimeout(this.debouncedIdleHandle),this.debouncedIdleHandle=null),this.state==="idle"&&(this.state="busy",this.inStartupGrace()||this.onStateChange({terminalId:this.terminalId,state:"busy"})),this.idleCheckHandle!==null&&clearTimeout(this.idleCheckHandle),this.idleCheckHandle=setTimeout(()=>this.checkIdle(),a.IDLE_THRESHOLD_MS)}onChromeOutput(){this.state==="busy"&&(this.debouncedIdleHandle!==null&&(clearTimeout(this.debouncedIdleHandle),this.debouncedIdleHandle=null),this.idleCheckHandle!==null&&clearTimeout(this.idleCheckHandle),this.idleCheckHandle=setTimeout(()=>this.checkIdle(),a.IDLE_THRESHOLD_MS))}getState(){return this.state}dispose(){this.idleCheckHandle!==null&&(clearTimeout(this.idleCheckHandle),this.idleCheckHandle=null),this.debouncedIdleHandle!==null&&(clearTimeout(this.debouncedIdleHandle),this.debouncedIdleHandle=null)}checkIdle(){this.idleCheckHandle=null,Date.now()-this.lastRealOutputAt>=a.IDLE_THRESHOLD_MS&&this.state==="busy"&&(this.debouncedIdleHandle=setTimeout(()=>{this.debouncedIdleHandle=null,Date.now()-this.lastRealOutputAt>=a.IDLE_THRESHOLD_MS&&(this.state="idle",this.inStartupGrace()||this.onStateChange({terminalId:this.terminalId,state:"idle"}))},a.DEBOUNCE_MS))}};var Be=class a{escapeBuffer="";static MAX_ESCAPE_BUFFER=256;process(e){let t=this.escapeBuffer+e;this.escapeBuffer="";let r=this.findIncompleteEscape(t);if(r>=0){if(this.escapeBuffer=t.slice(r),this.escapeBuffer.length>a.MAX_ESCAPE_BUFFER){let s=this.escapeBuffer;return this.escapeBuffer="",t.slice(0,r)+s}return t.slice(0,r)}return t}flush(){let e=this.escapeBuffer;return this.escapeBuffer="",e}hasPending(){return this.escapeBuffer.length>0}findIncompleteEscape(e){let t=e.length;if(t===0)return-1;if(e.charCodeAt(t-1)===27)return t-1;let r=Math.max(0,t-a.MAX_ESCAPE_BUFFER),s=-1;for(let o=t-1;o>=r;o--)if(e.charCodeAt(o)===27){s=o;break}if(s<0)return-1;let n=e.slice(s);if(n.length<2)return s;let i=n.charCodeAt(1);if(i===91){for(let o=2;o<n.length;o++){let c=n.charCodeAt(o);if(c>=64&&c<=126)return-1}return s}if(i===93){for(let o=2;o<n.length;o++)if(n.charCodeAt(o)===7||n.charCodeAt(o)===27&&o+1<n.length&&n.charCodeAt(o+1)===92)return-1;return s}if(i===80){for(let o=2;o<n.length;o++)if(n.charCodeAt(o)===27&&o+1<n.length&&n.charCodeAt(o+1)===92)return-1;return s}return-1}};var _a=[/(?:rate.?limit|too many requests|429|throttl)/i,/(?:overloaded|capacity|RESOURCE_EXHAUSTED)/i,/(?:quota.?exceeded|billing|usage.?limit)/i,/(?:retry.?after|backoff|slow.?down)/i,/(?:requests? per (?:minute|second|hour)|RPM|RPS)/i],Ua=/(?:retry.?after|wait|try again in)\s*[:=]?\s*(\d+)\s*(s(?:ec)?|m(?:in)?|h(?:our)?)?/i;function er(a){for(let e of _a)if(e.test(a)){let t=Ua.exec(a),r;if(t){let s=parseInt(t[1],10),n=t[2]?.toLowerCase()||"s";n.startsWith("m")?r=s*60:n.startsWith("h")?r=s*3600:r=s}return{type:"rate-limit",data:{message:a.trim().slice(0,200),retryAfterSeconds:r}}}return null}var Fa=[/(?:HTTP\s+)?(?:4\d{2}|5\d{2})\b/,/(?:ECONNREFUSED|ENOTFOUND|ETIMEDOUT|ECONNRESET)/,/(?:authentication failed|unauthorized|forbidden|invalid.?(?:api.?)?key)/i,/(?:internal server error|bad gateway|service unavailable|gateway timeout)/i,/(?:APIError|ApiError|API error)/],$a=/(?:HTTP\s+)?([45]\d{2})/;function tr(a){for(let e of Fa)if(e.test(a)){let t=$a.exec(a);return{type:"api-error",data:{message:a.trim().slice(0,300),statusCode:t?parseInt(t[1],10):void 0}}}return null}var Wa=/https?:\/\/(?:github\.com|gitlab\.com|bitbucket\.org)\/[^\s]+\/pull\/(\d+)/gi,Ba=/https?:\/\/gitlab\.com\/[^\s]+\/merge_requests\/(\d+)/gi;function rr(a){let e=[];for(let t of[Wa,Ba]){t.lastIndex=0;let r;for(;(r=t.exec(a))!==null;)e.push(r[0])}return e.length===0?null:{type:"pr-url",data:{urls:e}}}var qa=/(\d{1,3}(?:\.\d+)?)\s*%/,Ha=/(\d+)\s*\/\s*(\d+)/,Xa=/\[([█▓▒░=\->#\s]{4,})\]/;function sr(a){let e=qa.exec(a);if(e){let r=parseFloat(e[1]);if(r>=0&&r<=100)return{type:"progress",data:{percent:r,raw:a.trim().slice(0,100)}}}let t=Ha.exec(a);if(t){let r=parseInt(t[1],10),s=parseInt(t[2],10);if(s>0&&r<=s&&s<=1e4)return{type:"progress",data:{percent:r/s*100,current:r,total:s,raw:a.trim().slice(0,100)}}}return Xa.test(a)?{type:"progress",data:{raw:a.trim().slice(0,100)}}:null}var Ga=/(\d+)\s+(?:tool|sub.?(?:task|agent))s?\s+running/i,ns=/teammate\s+\w+\s+\((?:working|running|busy)\)/gi,ja=/(?:task|step|agent)\s+(\d+)\s*(?:\/|of)\s*(\d+)/i;function nr(a){let e=Ga.exec(a);if(e)return{type:"subtask-count",data:{active:parseInt(e[1],10)}};ns.lastIndex=0;let t=[],r;for(;(r=ns.exec(a))!==null;)t.push(r[0]);if(t.length>0)return{type:"subtask-count",data:{active:t.length,teammates:t}};let s=ja.exec(a);return s?{type:"subtask-count",data:{current:parseInt(s[1],10),total:parseInt(s[2],10)}}:null}var Ka=[er,tr,rr,sr,nr];function as(a){let e=[];for(let t of Ka){let r=t(a);r&&e.push(r)}return e}var Ya=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function Va(a){return a.replace(Ya,"")}var za=[/\[Y\/n\]/i,/\[y\/N\]/i,/\[a\/y\/n\]/i,/\(yes\/no\)/i,/\(y\/n\)/i,/Approve\?/i,/Allow\s/i,/Do you want/i,/Press Enter/i,/Enter to select/i,/Select\s/i,/Choose\s/i,/\bconfirm\b/i,/\bproceed\b.*\?/i,/\bcontinue\b.*\?/i,/\boverwrite\b.*\?/i,/\breplace\b.*\?/i,/\bdelete\b.*\?/i,/\bremove\b.*\?/i],Ja=1e3,Qa=1e4,Za=10,ei=500,ti=1e3,is=5e3,os=5,ri=2e3,qe=class{terminals=new Map;pushHandler;constructor(e){this.pushHandler=e}initTerminal(e,t=24,r=80){this.cleanupTerminal(e);let s={vtBuffer:new $e(t,r),shellState:new We(e,n=>{this.pushHandler("terminal.shell-state",n)}),bufferAssembler:new Be,silenceTimerHandle:setInterval(()=>this.checkSilence(e),Ja),lastRealOutputAt:0,pendingQuestionLine:null,pendingQuestionAt:0,questionEmitted:!1,questionEmittedAt:0,chunksAfterQuestion:0,lastUserInputAt:0,lastResizeAt:0,startedAt:Date.now()};this.terminals.set(e,s)}processOutput(e,t){let r=this.terminals.get(e);if(!r)return t;let s=r.bufferAssembler.process(t);if(s.length===0)return"";r.vtBuffer.write(s),Vr(s)?r.shellState.onChromeOutput():(r.lastRealOutputAt=Date.now(),r.shellState.onRealOutput(),r.pendingQuestionLine!==null&&(r.chunksAfterQuestion++,r.chunksAfterQuestion>=Za&&(r.pendingQuestionLine=null,r.chunksAfterQuestion=0)),r.questionEmitted&&Date.now()-r.questionEmittedAt>=ri&&(r.questionEmitted=!1,r.questionEmittedAt=0,this.pushHandler("terminal.awaiting-input-cleared",{terminalId:e})));let i=Va(s);return this.checkInstantQuestions(e,i,r),this.detectQuestionCandidates(i,r),this.runPatternDetection(e,i),s}onUserInput(e){let t=this.terminals.get(e);t&&(t.lastUserInputAt=Date.now(),t.questionEmitted&&(t.questionEmitted=!1,t.questionEmittedAt=0,this.pushHandler("terminal.awaiting-input-cleared",{terminalId:e})))}onResize(e,t,r){let s=this.terminals.get(e);s&&(s.lastResizeAt=Date.now(),s.vtBuffer.resize(t,r))}cleanupTerminal(e){let t=this.terminals.get(e);if(t){clearInterval(t.silenceTimerHandle),t.shellState.dispose();let r=t.bufferAssembler.flush();r.length>0&&t.vtBuffer.write(r),this.terminals.delete(e)}}dispose(){for(let[e]of this.terminals)this.cleanupTerminal(e)}checkInstantQuestions(e,t,r){if(!(Date.now()-r.startedAt<is))for(let s of t.split(`
|
|
@@ -47,7 +48,7 @@ set -gx TERM_PROGRAM impactus-swarm
|
|
|
47
48
|
`);for(let s=r.length-1;s>=0;s--){let n=r[s].trim();if(n.endsWith("?")&&n.length>=5){t.pendingQuestionLine=n,t.pendingQuestionAt=Date.now(),t.chunksAfterQuestion=0;return}}}checkSilence(e){let t=this.terminals.get(e);if(!t)return;let r=Date.now();if(r-t.startedAt<is||r-t.lastResizeAt<ti||r-t.lastUserInputAt<ei||t.questionEmitted||t.pendingQuestionLine===null||r-t.lastRealOutputAt<Qa||t.lastRealOutputAt===0)return;let n=t.pendingQuestionLine;if(!rs(n)){t.pendingQuestionLine=null;return}if(!t.vtBuffer.containsInBottom(n,os)){let o=t.vtBuffer.getBottomRows(os).join(" "),c=n.split(/\s+/).filter(d=>d.length>3);if(c.filter(d=>o.includes(d)).length<c.length*.5){t.pendingQuestionLine=null;return}}t.questionEmitted=!0,t.questionEmittedAt=Date.now(),t.pendingQuestionLine=null,this.pushHandler("terminal.awaiting-input",{terminalId:e,type:"question",confident:!1,promptText:n.slice(0,200)})}runPatternDetection(e,t){let r=t.split(`
|
|
48
49
|
`);for(let s of r){let n=s.trim();if(n.length===0)continue;let i=as(n);for(let o of i)if(this.pushHandler("terminal.output-event",{terminalId:e,type:o.type,data:o.data}),o.type==="api-error"){let c=this.terminals.get(e);c&&!c.questionEmitted&&(c.questionEmitted=!0,c.questionEmittedAt=Date.now(),this.pushHandler("terminal.awaiting-input",{terminalId:e,type:"error",confident:!0,promptText:o.data.message||"API Error"}))}}}};var He=class{states=new Map;listeners=[];staleTimers=new Map;onStatusChange(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter(t=>t!==e)}}processData(e,t){let r=/\x1b\]([012]);([^\x07\x1b]*?)(?:\x07|\x1b\\)/g,s;for(;(s=r.exec(t))!==null;){let n=s[2];this.handleTitle(e,n)}}handleTitle(e,t){let r=Date.now(),s=this.states.get(e);if(s&&r<s.cooldownUntil)return;let n=this.detectAgent(t);if(n==="unknown"&&!s)return;let i=this.detectStatus(n,t),o=s,c={agent:n!=="unknown"?n:o?.agent??"unknown",status:i,title:t,lastTitleChange:r,cooldownUntil:r};!o||o.status!==c.status||o.agent!==c.agent?(this.states.set(e,c),this.emit(e,c),this.resetStaleTimer(e)):(this.states.set(e,c),this.resetStaleTimer(e))}detectAgent(e){return e.includes("\u2733")||/^[Cc]laude/.test(e)||e.includes("claude-code")?"claude":e.includes("\u2726")||e.includes("\u25C7")||e.includes("\u270B")||/gemini/i.test(e)?"gemini":/codex/i.test(e)?"codex":/aider/i.test(e)?"aider":/opencode/i.test(e)?"opencode":"unknown"}detectStatus(e,t){switch(e){case"claude":return t.includes("\u2733")?"idle":t.startsWith(".")||/[\u2800-\u28FF]/.test(t)?"working":"unknown";case"gemini":return t.includes("\u270B")?"permission":t.includes("\u2726")?"working":t.includes("\u25C7")?"idle":"unknown";default:return/\b(waiting|permission|confirm|approve)\b/i.test(t)?"permission":/\b(thinking|running|working|processing)\b/i.test(t)?"working":/\b(idle|ready|done|complete)\b/i.test(t)?"idle":"unknown"}}emit(e,t){let r={terminalId:e,agent:t.agent,status:t.status,title:t.title};for(let s of this.listeners)s(r)}resetStaleTimer(e){let t=this.staleTimers.get(e);t&&clearTimeout(t),this.staleTimers.set(e,setTimeout(()=>{let r=this.states.get(e);if(r&&r.status==="working"){let s={...r,status:"unknown"};this.states.set(e,s),this.emit(e,s)}},3e3))}getStatus(e){return this.states.get(e)}removeTerminal(e){this.states.delete(e);let t=this.staleTimers.get(e);t&&clearTimeout(t),this.staleTimers.delete(e)}dispose(){for(let e of this.staleTimers.values())clearTimeout(e);this.staleTimers.clear(),this.states.clear(),this.listeners=[]}};var Xe=ii(si),oi=process.platform==="win32",ar=new Set(["zsh","bash","sh","fish","dash","ksh","tcsh","csh","ps","grep","rg","cmd.exe","powershell.exe","pwsh.exe","conhost.exe","cmd","powershell","pwsh","conhost"]),Ge=class a{terminals=new Map;pushHandler;commandBlockParser=new Ce;outputEventParser;agentStatusDetector=new He;processDetectionInterval;processDetectionRunning=!1;useTmux;constructor(e){this.pushHandler=e,this.outputEventParser=new qe(e),this.agentStatusDetector.onStatusChange(t=>{this.pushHandler("terminal.agent-status",t)}),this.useTmux=R.isAvailable(),this.useTmux?console.log("[terminal] tmux available \u2014 persistent sessions enabled"):console.log("[terminal] tmux not available \u2014 sessions will not persist across restarts"),this.processDetectionInterval=setInterval(()=>{this.processDetectionRunning||(this.processDetectionRunning=!0,this.detectProcesses().finally(()=>{this.processDetectionRunning=!1}))},3e3)}async detectProcesses(){for(let[,e]of this.terminals){let t=await this.detectProcessForTerminal(e),r=e.lastProcessInfo;(!r||r.foregroundProcess!==t.foregroundProcess||r.isIdle!==t.isIdle)&&(e.lastProcessInfo=t,this.pushHandler("terminal.process",{id:e.id,process:t}))}}async getEffectivePid(e){if(e.tmuxSession){let t=await R.getShellPidAsync(e.tmuxSession);if(t)return t}return e.pty.pid}async detectProcessForTerminal(e){let t=await this.getEffectivePid(e),r;try{if(oi){let{stdout:s}=await Xe("wmic",["process","where",`(ParentProcessId=${t})`,"get","Name","/format:list"],{timeout:2e3}),n=s.trim().split(`
|
|
49
50
|
`).map(i=>i.replace(/^Name=/,"").trim()).filter(i=>i&&!ar.has(i)&&!ar.has(i.replace(/\.exe$/i,"")));n.length>0&&(r=n[0].replace(/\.exe$/i,""))}else{let{stdout:s}=await Xe("ps",["-p",String(t),"-o","tty="],{timeout:2e3}),n=s.trim();if(n&&n!=="?"){let{stdout:i}=await Xe("ps",["-o","comm=","-t",n],{timeout:2e3}),o=i.trim().split(`
|
|
50
|
-
`).map(c=>{let l=c.trim();return l.split("/").pop()||l}).filter(c=>c&&!ar.has(c));o.length>0&&(r=o[0])}}}catch{}return{id:e.id,pid:t,foregroundProcess:r,isIdle:r===void 0}}dispose(){clearInterval(this.processDetectionInterval),this.outputEventParser.dispose(),this.agentStatusDetector.dispose()}getProcessInfo(e){let t=this.terminals.get(e);return t?t.lastProcessInfo??null:null}getAgentStatus(e){return this.agentStatusDetector.getStatus(e)}getAllProcessInfo(){return Array.from(this.terminals.values()).map(e=>e.lastProcessInfo).filter(e=>e!==null)}async open(e,t){this.terminals.has(e.id)&&this.close(e.id);let r=e.cwd==="~"?cs():e.cwd.startsWith("~/")?ai(cs(),e.cwd.slice(2)):e.cwd,s,n;try{if(this.useTmux){let u=await Jt();n=R.createSession(e.id,e.cols,e.rows,r,u,e.env),s=Zt(R.getAttachArgs(n),e.cols,e.rows)}else s=await Qt({cols:e.cols,rows:e.rows,cwd:r,env:e.env})}catch(u){if(n){console.warn("[terminal] tmux session creation failed, falling back to direct PTY:",u),R.killSession(n),n=void 0;try{s=await Qt({cols:e.cols,rows:e.rows,cwd:r,env:e.env})}catch(m){let p=m instanceof Error?m.message:"Failed to spawn PTY";this.pushHandler("terminal.error",{id:e.id,message:p});return}}else{let m=u instanceof Error?u.message:"Failed to spawn PTY";this.pushHandler("terminal.error",{id:e.id,message:m});return}}let i=new AbortController,o={pty:s,id:e.id,tmuxSession:n,sequenceAbort:i,outputBuffer:"",outputSeq:0,replayChunks:[]};this.terminals.set(e.id,o),this.setupHandlers(o),this.outputEventParser.initTerminal(e.id,e.rows,e.cols);let c={id:e.id,pid:s.pid};this.pushHandler("terminal.started",c);let l=new Set(t?.completedSteps||[]),d=[];e.command&&d.push({command:e.command,delay:300}),e.commandSequence&&e.commandSequence.forEach((u,m)=>{u.runOnce&&l.has(m)||d.push({...u,originalIndex:m})}),d.length>0?this.executeSequence(s,d,i.signal,e.id,t?.onStepCompleted).catch(u=>{console.error("[terminal] executeSequence error:",u)}).then(()=>{e.closeAfterCommand&&!i.signal.aborted&&this.scheduleClose(e.id,e.closeDelay??1e3,e.closeWaitFor,i.signal)}):e.closeAfterCommand&&this.scheduleClose(e.id,e.closeDelay??1e3,e.closeWaitFor,i.signal)}static SESSION_MAX_AGE_MS=1440*60*1e3;recoverSessions(e,t=a.SESSION_MAX_AGE_MS){if(!this.useTmux)return[];let r=R.listSessions();if(r.length===0)return[];let s=Date.now(),n=[],i=0,o=0;for(let c of r){let l=R.getTerminalId(c);if(!l){R.killSession(c),i++;continue}if(e&&!e.has(l)){console.log(`[terminal] Killing orphaned session ${c} (terminal ${l} not in DB)`),R.killSession(c),i++;continue}let d=R.getCreatedAt(c);if(d&&s-d>t){let u=Math.round((s-d)/36e5);console.log(`[terminal] Killing expired session ${c} (age: ${u}h, max: ${t/(3600*1e3)}h)`),R.killSession(c),o++;continue}if(!this.terminals.has(l))try{let u=R.getSessionSize(c)||{cols:80,rows:24},m=Zt(R.getAttachArgs(c),u.cols,u.rows),p=R.capturePane(c),g={pty:m,id:l,tmuxSession:c,outputBuffer:p,outputSeq:0,replayChunks:[]};this.terminals.set(l,g),this.setupHandlers(g),this.outputEventParser.initTerminal(l,u.rows,u.cols),n.push(l)}catch(u){console.error(`[terminal] Failed to recover session ${c}:`,u),R.killSession(c)}}return n.length>0&&console.log(`[terminal] Recovered ${n.length} persistent session(s): ${n.join(", ")}`),(i>0||o>0)&&console.log(`[terminal] GC: killed ${i} orphan(s), ${o} expired session(s)`),n}setupHandlers(e){e.pty.onData(t=>{e.outputBuffer+=t,e.outputBuffer.length>5e6&&(e.outputBuffer=e.outputBuffer.slice(-2e6)),e.outputSeq++,e.replayChunks.push({seq:e.outputSeq,data:t}),e.replayChunks.length>1e4&&e.replayChunks.shift();let r=this.commandBlockParser.parse(t,e.id);for(let i of r)this.pushHandler("terminal.command-block",{terminalId:e.id,event:i});let s=r.length>0?Ce.stripOSC133(t):t,n={id:e.id,data:s,seq:e.outputSeq};this.pushHandler("terminal.output",n),queueMicrotask(()=>{this.agentStatusDetector.processData(e.id,t)}),queueMicrotask(()=>{this.outputEventParser.processOutput(e.id,s)})}),e.pty.onExit(({exitCode:t})=>{e.sequenceAbort?.abort();let r={id:e.id,exitCode:t};this.pushHandler("terminal.exited",r),this.agentStatusDetector.removeTerminal(e.id),this.terminals.delete(e.id)})}async executeSequence(e,t,r,s,n){for(let i of t){if(r.aborted)return;let o=i.delay??500;if(await this.sleep(o,r),r.aborted)return;if(i.waitFor){if(await this.waitForOutput(s||"",i.waitFor,3e4,r),r.aborted)return;let c=i.respond||"",l=c.endsWith("\r")?c:c+"\r";e.write(l),i.runOnce&&i.originalIndex!==void 0&&s&&n&&n(s,i.originalIndex);continue}e.write(i.command+"\r"),i.runOnce&&i.originalIndex!==void 0&&s&&n&&n(s,i.originalIndex)}}async scheduleClose(e,t,r,s){s?.aborted||r&&(await this.waitForOutput(e,r,12e4,s||new AbortController().signal),s?.aborted)||(await this.sleep(Math.max(t,500),s||new AbortController().signal),!s?.aborted&&this.terminals.has(e)&&this.close(e))}sleep(e,t){return new Promise(r=>{let s=setTimeout(r,e);t.addEventListener("abort",()=>{clearTimeout(s),r()},{once:!0})})}stripAnsi(e){return e.replace(/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*\x07|\x1b[()][AB012]|\x1b[>=]/g," ").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g,"")}waitForOutput(e,t,r,s){return new Promise(n=>{let i=this.terminals.get(e);if(!i){n();return}let o=i.outputBuffer.length,c=setInterval(()=>{let d=i.outputBuffer;this.stripAnsi(d.slice(o)).includes(t)&&(clearInterval(c),clearTimeout(l),n())},200),l=setTimeout(()=>{clearInterval(c),n()},r);s.addEventListener("abort",()=>{clearInterval(c),clearTimeout(l),n()},{once:!0})})}async waitForPattern(e,t,r){let s=this.terminals.get(e);if(!s)return{met:!1};let n=s.outputBuffer.length;return new Promise(i=>{let o=setInterval(()=>{let l=s.outputBuffer;this.stripAnsi(l.slice(n)).includes(t)&&(clearInterval(o),clearTimeout(c),i({met:!0}))},200),c=setTimeout(()=>{clearInterval(o),i({met:!1})},r)})}async waitForExit(e,t){let r=this.terminals.get(e);return r?new Promise(s=>{let n=setTimeout(()=>{o(),s({met:!1})},t),i=!1,o=()=>{clearTimeout(n)},c=r.pty.onExit(({exitCode:l})=>{i||(i=!0,o(),c.dispose(),s({met:!0,exitCode:l}))})}):{met:!1}}async waitForIdle(e,t){let r=Date.now();return new Promise(s=>{let n=setInterval(()=>{let i=this.getProcessInfo(e);if(!i){clearInterval(n),s({met:!1});return}if(i.isIdle){clearInterval(n),s({met:!0});return}Date.now()-r>=t&&(clearInterval(n),s({met:!1}))},200)})}write(e,t){let r=this.terminals.get(e);if(!r){this.pushHandler("terminal.error",{id:e,message:`Terminal ${e} not found`});return}try{this.outputEventParser.onUserInput(e),r.pty.write(t)}catch(s){let n=s instanceof Error?s.message:"Failed to write to PTY";this.pushHandler("terminal.error",{id:e,message:n})}}resize(e,t,r){let s=this.terminals.get(e);s&&(s.pty.resize(t,r),s.tmuxSession&&R.resizeSession(s.tmuxSession,t,r),this.outputEventParser.onResize(e,r,t))}close(e){let t=this.terminals.get(e);t&&(t.sequenceAbort?.abort(),t.tmuxSession&&R.killSession(t.tmuxSession),t.pty.kill(),this.commandBlockParser.cleanup(e),this.outputEventParser.cleanupTerminal(e),this.agentStatusDetector.removeTerminal(e),this.terminals.delete(e))}detachAll(){this.dispose();for(let[e,t]of this.terminals)t.sequenceAbort?.abort(),t.pty.kill(),this.commandBlockParser.cleanup(e);this.terminals.clear()}closeAll(){this.dispose();for(let[e]of this.terminals)this.close(e)}getOutputBuffer(e){let t=this.terminals.get(e);if(!t)return null;if(t.tmuxSession){let r=R.getSessionSize(t.tmuxSession),s=R.capturePane(t.tmuxSession);if(s){let n=R.getCursorPosition(t.tmuxSession),i=n?s+`\x1B[${n.y+1};${n.x+1}H`:s,o=
|
|
51
|
+
`).map(c=>{let l=c.trim();return l.split("/").pop()||l}).filter(c=>c&&!ar.has(c));o.length>0&&(r=o[0])}}}catch{}return{id:e.id,pid:t,foregroundProcess:r,isIdle:r===void 0}}dispose(){clearInterval(this.processDetectionInterval),this.outputEventParser.dispose(),this.agentStatusDetector.dispose()}getProcessInfo(e){let t=this.terminals.get(e);return t?t.lastProcessInfo??null:null}getAgentStatus(e){return this.agentStatusDetector.getStatus(e)}getAllProcessInfo(){return Array.from(this.terminals.values()).map(e=>e.lastProcessInfo).filter(e=>e!==null)}async open(e,t){this.terminals.has(e.id)&&this.close(e.id);let r=e.cwd==="~"?cs():e.cwd.startsWith("~/")?ai(cs(),e.cwd.slice(2)):e.cwd,s,n;try{if(this.useTmux){let u=await Jt();n=R.createSession(e.id,e.cols,e.rows,r,u,e.env),s=Zt(R.getAttachArgs(n),e.cols,e.rows)}else s=await Qt({cols:e.cols,rows:e.rows,cwd:r,env:e.env})}catch(u){if(n){console.warn("[terminal] tmux session creation failed, falling back to direct PTY:",u),R.killSession(n),n=void 0;try{s=await Qt({cols:e.cols,rows:e.rows,cwd:r,env:e.env})}catch(m){let p=m instanceof Error?m.message:"Failed to spawn PTY";this.pushHandler("terminal.error",{id:e.id,message:p});return}}else{let m=u instanceof Error?u.message:"Failed to spawn PTY";this.pushHandler("terminal.error",{id:e.id,message:m});return}}let i=new AbortController,o={pty:s,id:e.id,tmuxSession:n,sequenceAbort:i,outputBuffer:"",outputSeq:0,replayChunks:[]};this.terminals.set(e.id,o),this.setupHandlers(o),this.outputEventParser.initTerminal(e.id,e.rows,e.cols);let c={id:e.id,pid:s.pid};this.pushHandler("terminal.started",c);let l=new Set(t?.completedSteps||[]),d=[];e.command&&d.push({command:e.command,delay:300}),e.commandSequence&&e.commandSequence.forEach((u,m)=>{u.runOnce&&l.has(m)||d.push({...u,originalIndex:m})}),d.length>0?this.executeSequence(s,d,i.signal,e.id,t?.onStepCompleted).catch(u=>{console.error("[terminal] executeSequence error:",u)}).then(()=>{e.closeAfterCommand&&!i.signal.aborted&&this.scheduleClose(e.id,e.closeDelay??1e3,e.closeWaitFor,i.signal)}):e.closeAfterCommand&&this.scheduleClose(e.id,e.closeDelay??1e3,e.closeWaitFor,i.signal)}static SESSION_MAX_AGE_MS=1440*60*1e3;recoverSessions(e,t=a.SESSION_MAX_AGE_MS){if(!this.useTmux)return[];let r=R.listSessions();if(r.length===0)return[];let s=Date.now(),n=[],i=0,o=0;for(let c of r){let l=R.getTerminalId(c);if(!l){R.killSession(c),i++;continue}if(e&&!e.has(l)){console.log(`[terminal] Killing orphaned session ${c} (terminal ${l} not in DB)`),R.killSession(c),i++;continue}let d=R.getCreatedAt(c);if(d&&s-d>t){let u=Math.round((s-d)/36e5);console.log(`[terminal] Killing expired session ${c} (age: ${u}h, max: ${t/(3600*1e3)}h)`),R.killSession(c),o++;continue}if(!this.terminals.has(l))try{let u=R.getSessionSize(c)||{cols:80,rows:24},m=Zt(R.getAttachArgs(c),u.cols,u.rows),p=R.capturePane(c),g={pty:m,id:l,tmuxSession:c,outputBuffer:p,outputSeq:0,replayChunks:[]};this.terminals.set(l,g),this.setupHandlers(g),this.outputEventParser.initTerminal(l,u.rows,u.cols),n.push(l)}catch(u){console.error(`[terminal] Failed to recover session ${c}:`,u),R.killSession(c)}}return n.length>0&&console.log(`[terminal] Recovered ${n.length} persistent session(s): ${n.join(", ")}`),(i>0||o>0)&&console.log(`[terminal] GC: killed ${i} orphan(s), ${o} expired session(s)`),n}setupHandlers(e){e.pty.onData(t=>{e.outputBuffer+=t,e.outputBuffer.length>5e6&&(e.outputBuffer=e.outputBuffer.slice(-2e6)),e.outputSeq++,e.replayChunks.push({seq:e.outputSeq,data:t}),e.replayChunks.length>1e4&&e.replayChunks.shift();let r=this.commandBlockParser.parse(t,e.id);for(let i of r)this.pushHandler("terminal.command-block",{terminalId:e.id,event:i});let s=r.length>0?Ce.stripOSC133(t):t,n={id:e.id,data:s,seq:e.outputSeq};this.pushHandler("terminal.output",n),queueMicrotask(()=>{this.agentStatusDetector.processData(e.id,t)}),queueMicrotask(()=>{this.outputEventParser.processOutput(e.id,s)})}),e.pty.onExit(({exitCode:t})=>{e.sequenceAbort?.abort();let r={id:e.id,exitCode:t};this.pushHandler("terminal.exited",r),this.agentStatusDetector.removeTerminal(e.id),this.terminals.delete(e.id)})}async executeSequence(e,t,r,s,n){for(let i of t){if(r.aborted)return;let o=i.delay??500;if(await this.sleep(o,r),r.aborted)return;if(i.waitFor){if(await this.waitForOutput(s||"",i.waitFor,3e4,r),r.aborted)return;let c=i.respond||"",l=c.endsWith("\r")?c:c+"\r";e.write(l),i.runOnce&&i.originalIndex!==void 0&&s&&n&&n(s,i.originalIndex);continue}e.write(i.command+"\r"),i.runOnce&&i.originalIndex!==void 0&&s&&n&&n(s,i.originalIndex)}}async scheduleClose(e,t,r,s){s?.aborted||r&&(await this.waitForOutput(e,r,12e4,s||new AbortController().signal),s?.aborted)||(await this.sleep(Math.max(t,500),s||new AbortController().signal),!s?.aborted&&this.terminals.has(e)&&this.close(e))}sleep(e,t){return new Promise(r=>{let s=setTimeout(r,e);t.addEventListener("abort",()=>{clearTimeout(s),r()},{once:!0})})}stripAnsi(e){return e.replace(/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*\x07|\x1b[()][AB012]|\x1b[>=]/g," ").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g,"")}waitForOutput(e,t,r,s){return new Promise(n=>{let i=this.terminals.get(e);if(!i){n();return}let o=i.outputBuffer.length,c=setInterval(()=>{let d=i.outputBuffer;this.stripAnsi(d.slice(o)).includes(t)&&(clearInterval(c),clearTimeout(l),n())},200),l=setTimeout(()=>{clearInterval(c),n()},r);s.addEventListener("abort",()=>{clearInterval(c),clearTimeout(l),n()},{once:!0})})}async waitForPattern(e,t,r){let s=this.terminals.get(e);if(!s)return{met:!1};let n=s.outputBuffer.length;return new Promise(i=>{let o=setInterval(()=>{let l=s.outputBuffer;this.stripAnsi(l.slice(n)).includes(t)&&(clearInterval(o),clearTimeout(c),i({met:!0}))},200),c=setTimeout(()=>{clearInterval(o),i({met:!1})},r)})}async waitForExit(e,t){let r=this.terminals.get(e);return r?new Promise(s=>{let n=setTimeout(()=>{o(),s({met:!1})},t),i=!1,o=()=>{clearTimeout(n)},c=r.pty.onExit(({exitCode:l})=>{i||(i=!0,o(),c.dispose(),s({met:!0,exitCode:l}))})}):{met:!1}}async waitForIdle(e,t){let r=Date.now();return new Promise(s=>{let n=setInterval(()=>{let i=this.getProcessInfo(e);if(!i){clearInterval(n),s({met:!1});return}if(i.isIdle){clearInterval(n),s({met:!0});return}Date.now()-r>=t&&(clearInterval(n),s({met:!1}))},200)})}write(e,t){let r=this.terminals.get(e);if(!r){this.pushHandler("terminal.error",{id:e,message:`Terminal ${e} not found`});return}try{this.outputEventParser.onUserInput(e),r.pty.write(t)}catch(s){let n=s instanceof Error?s.message:"Failed to write to PTY";this.pushHandler("terminal.error",{id:e,message:n})}}resize(e,t,r){let s=this.terminals.get(e);s&&(s.pty.resize(t,r),s.tmuxSession&&R.resizeSession(s.tmuxSession,t,r),this.outputEventParser.onResize(e,r,t))}close(e){let t=this.terminals.get(e);t&&(t.sequenceAbort?.abort(),t.tmuxSession&&R.killSession(t.tmuxSession),t.pty.kill(),this.commandBlockParser.cleanup(e),this.outputEventParser.cleanupTerminal(e),this.agentStatusDetector.removeTerminal(e),this.terminals.delete(e))}detachAll(){this.dispose();for(let[e,t]of this.terminals)t.sequenceAbort?.abort(),t.pty.kill(),this.commandBlockParser.cleanup(e);this.terminals.clear()}closeAll(){this.dispose();for(let[e]of this.terminals)this.close(e)}getOutputBuffer(e){let t=this.terminals.get(e);if(!t)return null;if(t.tmuxSession){let r=R.getSessionSize(t.tmuxSession),s=R.capturePane(t.tmuxSession);if(s){let n=R.getCursorPosition(t.tmuxSession),i=n?s+`\x1B[${n.y+1};${n.x+1}H`:s,o=R.capturePaneScrollback(t.tmuxSession,5e3)||void 0;return{data:i,scrollback:o,cols:r?.cols,rows:r?.rows}}}return t.outputBuffer?{data:t.outputBuffer}:{data:""}}getOutputSince(e,t){let r=this.terminals.get(e);if(!r)return null;let s=r.replayChunks.findIndex(i=>i.seq>t);return s===-1?{chunks:[],currentSeq:r.outputSeq}:r.replayChunks.length>0&&r.replayChunks[0].seq>t+1?null:{chunks:r.replayChunks.slice(s).map(i=>i.data),currentSeq:r.outputSeq}}outputContains(e,t){let r=this.terminals.get(e);return r?this.stripAnsi(r.outputBuffer).includes(t):!1}has(e){return this.terminals.has(e)}async getCwd(e){let t=this.terminals.get(e);if(!t)return null;let r=await this.getEffectivePid(t);try{if(process.platform==="darwin"){let{stdout:s}=await Xe("lsof",["-a","-p",String(r),"-d","cwd","-Fn"],{timeout:3e3}),n=s.trim().split(`
|
|
51
52
|
`);for(let i of n)if(i.startsWith("n"))return i.slice(1)}else if(process.platform==="linux")return ni(`/proc/${r}/cwd`)}catch{}return null}get size(){return this.terminals.size}listTerminals(){let e=[];for(let[t,r]of this.terminals)e.push({id:t,pid:r.pty.pid});return e}};import{randomUUID as ci}from"node:crypto";var je=class{db;areaManager;constructor(e,t){this.db=e,this.areaManager=t}list(){return this.db.prepare('SELECT * FROM workspaces ORDER BY "order" ASC, createdAt ASC').all().map(r=>this.hydrateWorkspace(r))}get(e){let r=this.db.prepare("SELECT * FROM workspaces WHERE id = ?").get(e);return r?this.hydrateWorkspace(r):null}create(e){let t=ci(),r=new Date().toISOString(),s=e.icon||e.name.split(" ").map(m=>m[0]).join("").slice(0,2).toUpperCase(),o=this.db.prepare('SELECT MAX("order") as m FROM workspaces').get()?.m||0;this.db.prepare(`INSERT INTO workspaces (id, name, icon, imageUrl, color, rootDirectory, initGit, defaultCommand, terminalCount, layout, "order", stackId, createdAt, updatedAt)
|
|
52
53
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(t,e.name,s,e.imageUrl??null,e.color||"#7C3AED",e.rootDirectory,e.initGit!==void 0?e.initGit?1:0:1,e.defaultCommand||"",e.terminalCount,e.layout||"auto",o+1,e.stackId??null,r,r),this.db.prepare("INSERT INTO workspace_state (workspaceId) VALUES (?)").run(t);let d=this.areaManager.create({workspaceId:t,name:e.defaultAreaName?.trim()||"Principal",color:e.defaultAreaColor||e.color||"#7C3AED",defaultCommand:e.defaultCommand,terminalCount:e.terminalCount,layout:e.layout,terminals:e.terminals,templateId:e.templateId,ignoreOnLaunchAll:e.defaultAreaIgnoreOnLaunchAll});return this.db.prepare("UPDATE areas SET isDefault = 1 WHERE id = ?").run(d.id),this.get(t)}update(e){let t=this.get(e.id);if(!t)return null;let r=new Date().toISOString(),s=this.db.prepare(`UPDATE workspaces SET
|
|
53
54
|
name = ?, icon = ?, imageUrl = ?, color = ?, rootDirectory = ?, initGit = ?,
|
|
@@ -313,7 +314,7 @@ _No file content available._`)}let o=i.join(`
|
|
|
313
314
|
`)}generateClaudeMd(e,t,r){let s=[`# Agent: ${t.name}`,`## Role: ${t.role}`,"","## Mission",e.description,""];return r&&s.push("## Working Directory",r.directory,""),t.systemPrompt&&s.push("## System Prompt",t.systemPrompt,""),t.workScope&&t.workScope.length>0&&s.push("## Work Scope",...t.workScope.map(n=>`- ${n}`),""),s.push("## Current Task",""),s.push(`- **ID:** ${e.id}`),s.push(`- **Title:** ${e.title}`),s.push(`- **Approval Mode:** ${e.approvalMode}`),s.push(""),t.role==="coordinator"&&r&&s.push("## Coordinator Instructions",`You are the coordinator of a swarm of ${r.agents.length} agents.`,"Your job is to orchestrate the other agents to complete the mission.","Monitor their outputs, delegate tasks, and ensure quality.","","## Agents in this Swarm",...r.agents.map(n=>`- ${n.name} (${n.role}): ${n.systemPrompt||"No specific prompt"}`),""),s.join(`
|
|
314
315
|
`)}async buildStandaloneContext(e){let{task:t,prompt:r,workspaceDir:s}=e,n=ee(s,".swarm","tasks",t.id);await Rr(n,{recursive:!0});let i=this.generateTaskMd(t);await $t(ee(n,"TASK.md"),i,"utf-8");let o=ee(n,"CLAUDE.md"),c=[`# Task: ${t.title}`,"","## Mission",r,"","## Current Task",`- **ID:** ${t.id}`,`- **Title:** ${t.title}`,`- **Approval Mode:** ${t.approvalMode}`,""].join(`
|
|
315
316
|
`);return await $t(o,c,"utf-8"),{contextDir:n,prompt:r,claudeMdPath:o}}generateTaskMd(e,t){let r=[`# Task: ${e.title}`,"",`- **ID:** ${e.id}`,`- **Status:** ${e.status}`,`- **Approval Mode:** ${e.approvalMode}`,`- **Created:** ${e.createdAt}`,"","## Description","",e.description,""];if(t&&t.length>0){r.push("## Dependencies","");for(let s of t){if(r.push(`### ${s.title}`),r.push(`- **ID:** ${s.id}`),r.push(`- **Status:** ${s.status}`),s.output&&r.push("- **Output:**","",s.output),s.filesChanged&&s.filesChanged.length>0){r.push("- **Files Changed:**");for(let n of s.filesChanged)r.push(` - ${n}`)}r.push("")}}return r.join(`
|
|
316
|
-
`)}};function hn(){return{"task.create":(a,e)=>{let t=a;return e.services.taskManager.create(t)},"task.update":(a,e)=>{let t=a;return e.services.taskManager.update(t.id,t.updates)},"task.delete":(a,e)=>{let t=a;return{deleted:e.services.taskManager.delete(t.id)}},"task.list":(a,e)=>{let t=a;return e.services.taskManager.list(t)},"task.move":(a,e)=>{let t=a;return e.services.taskManager.move(t.id,t.status)},"task.assign":(a,e)=>{let t=a;return e.services.taskManager.assign(t.id,t.agentId)},"task.run":async(a,e)=>{let t=a,{taskManager:r,terminalManager:s,workspaceManager:n,swarmManager:i,providerRegistry:o}=e.services,c=r.get(t.taskId);if(!c)return e.respondError(`Task ${t.taskId} not found`),null;if(t.terminals&&t.terminals.length>0){let $=c.workspaceId?n.get(c.workspaceId):null,b=t.workspaceDir||$?.rootDirectory||process.cwd(),Ue=[];for(let de=0;de<t.terminals.length;de++){let A=t.terminals[de],K=`task-${c.id}-${de}-${Date.now()}`,W;if(A.command)W=A.command;else if(A.cli){let ne=await new Oe().buildStandaloneContext({task:c,cli:A.cli,prompt:A.prompt,workspaceDir:b}),X=o.get(A.cli);W=X?X.buildCommand({mission:ne.prompt,cwd:"",autoApprove:A.autoApprove??!1}):A.cli,A.cli==="claude"&&W.startsWith("claude")&&(W=W.replace(/^claude/,"claude -p"))}else W="bash";if(await s.open({id:K,cwd:b,command:W,env:t.env,cols:120,rows:30}),A.command){let Ae=A.promptDelay??3e3;if(A.commandSequence&&A.commandSequence.length>0){let ne=0;for(let X of A.commandSequence)ne+=X.delay,setTimeout(()=>{s.write(K,X.command+"\r")},ne);A.prompt&&setTimeout(()=>{s.write(K,A.prompt+"\r")},ne+Ae)}else A.prompt&&setTimeout(()=>{s.write(K,A.prompt+"\r")},Ae)}let Kt=A.cli||A.command||"shell";r.addTerminal(c.id,K,Kt,A.prompt,A.autoApprove??!1),Ue.push(K)}return r.move(c.id,"running"),{taskId:c.id,terminalIds:Ue,workDir:b}}let l=t.agentId||c.assignedAgentId;if(!l)return e.respondError(`No agent assigned to task ${t.taskId}`),null;if(!c.swarmId)return e.respondError(`Task ${t.taskId} has no swarm`),null;let d=i.get(c.swarmId);if(!d)return e.respondError(`Swarm ${c.swarmId} not found`),null;let u=d.agents.find($=>$.id===l);if(!u)return e.respondError(`Agent ${l} not found in swarm`),null;let p=t.includeKnowledge!==!1?d.knowledge:void 0,g;t.includeDependencies&&c.dependencies.length>0&&(g=c.dependencies.map($=>r.get($)).filter($=>$!==null));let h=await new Oe().buildContext({task:c,agent:u,swarm:d,knowledgeEntries:p,dependencyTasks:g,workspaceDir:d.directory}),w=o.get(u.cli),S=w?w.buildCommand({mission:h.prompt,cwd:"",autoApprove:u.autoApprove||d.autoApprove}):u.cli,T=`task-${c.id}-${l.slice(0,8)}`,_=u.worktreePath||d.directory;return await s.open({id:T,cwd:_,command:S,env:t.env,cols:120,rows:30}),r.update(c.id,{}),r.move(c.id,"running"),r.updateTerminalId(c.id,T),{terminalId:T,terminalIds:[T],taskId:c.id,agentId:l,workDir:d.directory,cwd:_}},"task.stop":(a,e)=>{let t=a,{taskManager:r,terminalManager:s}=e.services,n=r.getTaskTerminals(t.taskId),i=[];for(let o of n)if(o.status==="running"){try{s.close(o.terminalId)}catch{}r.markTerminalExited(t.taskId,o.terminalId,-1),i.push(o.terminalId)}return r.move(t.taskId,"blocked"),e.services.broadcast("task.stopped",{taskId:t.taskId,terminalIds:i}),{taskId:t.taskId,killedTerminals:i}},"task.archive":(a,e)=>{let t=a;return e.services.taskManager.move(t.taskId,"archived")},"task.terminals":(a,e)=>{let t=a;return e.services.taskManager.getTaskTerminals(t.taskId)}}}function fn(){return{"knowledge.add":(a,e)=>{let t=a;return e.services.swarmManager.getKnowledgeManager().addEntry(t)},"knowledge.update":(a,e)=>{let t=a;return e.services.swarmManager.getKnowledgeManager().updateEntry(t)},"knowledge.delete":(a,e)=>{let t=a;return e.services.swarmManager.getKnowledgeManager().deleteEntry(t.entryId)},"knowledge.verify":(a,e)=>{let t=a;return e.services.swarmManager.getKnowledgeManager().verifyEntry(t.entryId,t.verified)},"knowledge.search":(a,e)=>{let t=a;return e.services.swarmManager.getKnowledgeManager().search(t)},"knowledge.get-all":(a,e)=>{let t=a;return e.services.swarmManager.getKnowledgeManager().getAllForSwarm(t.swarmId,t.limit)},"mailbox.post":(a,e)=>{let t=a;return e.services.swarmManager.getMailboxManager().post(t)},"mailbox.list":(a,e)=>{let t=a;return e.services.swarmManager.getMailboxManager().list(t)},"mailbox.mark-read":(a,e)=>{let t=a;return e.services.swarmManager.getMailboxManager().markRead(t.messageId,t.agentId),{ok:!0}},"mailbox.get-thread":(a,e)=>{let t=a;return e.services.swarmManager.getMailboxManager().getThread(t.parentMessageId)}}}function wn(){return{"settings.list":(a,e)=>{let t=a;return e.services.settingsManager.list(t.category)},"settings.get":(a,e)=>{let t=a;return e.services.settingsManager.get(t.key)},"settings.set":(a,e)=>{let t=a;return e.services.settingsManager.set(t)},"settings.delete":(a,e)=>{let t=a;return{deleted:e.services.settingsManager.delete(t.key)}},"settings.get-secret":(a,e)=>{let t=a;return{value:e.services.settingsManager.getSecret(t.key)}},"workspace.settings.list":(a,e)=>{let t=a;return e.services.settingsManager.listWorkspaceSettings(t.workspaceId)},"workspace.settings.set":(a,e)=>{let t=a;return e.services.settingsManager.setWorkspaceSetting(t)},"workspace.settings.delete":(a,e)=>{let t=a;return{deleted:e.services.settingsManager.deleteWorkspaceSetting(t.workspaceId,t.key)}},"workspace.settings.get-secret":(a,e)=>{let t=a;return{value:e.services.settingsManager.getWorkspaceSecret(t.workspaceId,t.key)}},"workspace.settings.resolved":(a,e)=>{let t=a;return e.services.settingsManager.getResolvedApiKeys(t.workspaceId)},"cli-tools.list":(a,e)=>{let t=a;return e.services.cliToolsManager.list(t.category)},"cli-tools.create":(a,e)=>{let t=a;return e.services.cliToolsManager.create(t)},"cli-tools.update":(a,e)=>{let t=a;return e.services.cliToolsManager.update(t)},"cli-tools.delete":(a,e)=>{let t=a;return{deleted:e.services.cliToolsManager.delete(t.id)}},"cli-tools.health-check":async(a,e)=>{let t=a;return await e.services.cliToolsManager.healthCheck(t.id)},"cli-tools.health-check-all":async(a,e)=>{let t=a;return await e.services.cliToolsManager.healthCheckAll(t.category)}}}function Sn(){return{"registry.list-skills":(a,e)=>{let t=a;return e.services.skillsRegistry.listSkills(t.projectDir)},"registry.search-skills":(a,e)=>{let t=a;return e.services.skillsRegistry.searchSkills(t.query)},"registry.install-skill":(a,e)=>{let t=a;return e.services.skillsRegistry.installSkill(t.name,t.projectDir)},"registry.remove-skill":(a,e)=>{let t=a;return e.services.skillsRegistry.removeSkill(t.name,t.projectDir)},"registry.list-bundles":(a,e)=>e.services.skillsRegistry.listBundles(),"registry.install-bundle":(a,e)=>{let t=a;return e.services.skillsRegistry.installBundle(t.bundleId,t.projectDir),{ok:!0}},"registry.list-mcps":(a,e)=>{let t=a;return e.services.skillsRegistry.listMcps(t.projectDir)},"registry.configure-mcp":(a,e)=>{let t=a;return e.services.skillsRegistry.configureMcp(t)}}}function Tn(){return{"prd.start":(a,e)=>{let t=a;return e.services.prdBuilder.startSession(t)},"prd.send-message":(a,e)=>{let t=a;return e.services.prdBuilder.sendMessage(t.sessionId,t.message)},"prd.select-engine":(a,e)=>{let t=a;return e.services.prdBuilder.selectEngine(t.sessionId,t.engine)},"prd.select-stack":(a,e)=>{let t=a;return e.services.prdBuilder.selectStack(t.sessionId,t.techs)},"prd.generate":(a,e)=>{let t=a;return e.services.prdBuilder.generate(t.sessionId)},"prd.get":(a,e)=>{let t=a;return e.services.prdBuilder.getSession(t.sessionId)}}}function En(){return{"browser.session.open":async(a,e)=>{let t=a;return await e.services.browserManager.openSession(t.url)},"browser.session.close":async(a,e)=>{let t=a;return await e.services.browserManager.closeSession(t.sessionId),{ok:!0}},"browser.tab.open":async(a,e)=>{let t=a;return await e.services.browserManager.openTab(t.sessionId,t.url)},"browser.tab.close":async(a,e)=>{let t=a;return await e.services.browserManager.closeTab(t.sessionId,t.tabId),{ok:!0}},"browser.tab.navigate":async(a,e)=>{let t=a;return await e.services.browserManager.navigateTab(t.sessionId,t.tabId,t.url),{ok:!0}},"browser.tab.activate":async(a,e)=>{let t=a;return await e.services.browserManager.activateTab(t.sessionId,t.tabId),{ok:!0}},"browser.tab.back":async(a,e)=>{let t=a;return await e.services.browserManager.goBack(t.sessionId,t.tabId),{ok:!0}},"browser.tab.forward":async(a,e)=>{let t=a;return await e.services.browserManager.goForward(t.sessionId,t.tabId),{ok:!0}},"browser.tab.refresh":async(a,e)=>{let t=a;return await e.services.browserManager.refresh(t.sessionId,t.tabId),{ok:!0}},"browser.input":async(a,e)=>{let t=a;return await e.services.browserManager.sendInput(t.sessionId,t.tabId,t.event),{ok:!0}},"browser.screencast.ack":async(a,e)=>{let t=a;return await e.services.browserManager.ackFrame(t.sessionId,t.tabId,t.frameNumber),{ok:!0}}}}import*as te from"node:fs";import*as Wt from"node:os";import*as P from"node:path";import yn from"node:fs";import vn from"node:path";import{spawn as Mo}from"node:child_process";var No={"Cursor.app":"cursor","Visual Studio Code.app":"vscode","Visual Studio Code - Insiders.app":"vscode-insiders","VSCodium.app":"vscodium","Zed.app":"zed","Windsurf.app":"windsurf","Sublime Text.app":"sublime"},Ar=class{detectInstalledEditors(){let e=new Set,t=(process.env.PATH||"").split(vn.delimiter),r=process.platform==="darwin";for(let s of hr){if(s.command===null){s.id==="finder"&&r&&e.add("finder"),s.id==="terminal"&&e.add("terminal");continue}for(let n of t)try{if(yn.existsSync(vn.join(n,s.command))){e.add(s.id);break}}catch{}}if(r)try{let s=yn.readdirSync("/Applications");for(let n of s){let i=No[n];i&&!e.has(i)&&e.add(i)}}catch{}return Array.from(e)}openInEditor(e,t){try{let r=hr.find(o=>o.id===e);if(!r)return{ok:!1,error:`Unknown editor: ${e}`};let s,n;return e==="finder"?process.platform==="win32"?(s="explorer",n=[t]):process.platform==="linux"?(s="xdg-open",n=[t]):(s="open",n=[t]):e==="terminal"?process.platform==="win32"?(s="cmd",n=["/c","start","cmd","/k",`cd /d "${t}"`]):process.platform==="linux"?(s="xdg-open",n=[t]):(s="open",n=["-a","Terminal",t]):(s=r.command,n=[t]),Mo(s,n,{detached:!0,stdio:"ignore"}).unref(),{ok:!0}}catch(r){return{ok:!1,error:r instanceof Error?r.message:String(r)}}}},Ir=new Ar;function kn(){return{"tunnel.status":async(a,e)=>await e.services.tunnel.getStatus(),"tunnel.start":async(a,e)=>{let t=a;return await e.services.tunnel.startTunnel(t.config),{ok:!0}},"tunnel.stop":(a,e)=>(e.services.tunnel.stopTunnel(),{ok:!0}),"tunnel.url":(a,e)=>({url:e.services.tunnel.getUrl()}),"portTunnels.start":async(a,e)=>{let t=a;return await e.services.portTunnelManager.startTunnel(t.port,t.protocol),{ok:!0}},"portTunnels.stop":(a,e)=>{let t=a;return e.services.portTunnelManager.stopTunnel(t.port),{ok:!0}},"portTunnels.list":async(a,e)=>{let t=await e.services.portTunnelManager.checkInstalled();return{tunnels:e.services.portTunnelManager.getTunnels(),isInstalled:t}},"ports.list":(a,e)=>{let t=a;return e.services.portMonitor.listPorts(t.workspaceId)},"ports.list-all":(a,e)=>e.services.portMonitor.listAllWorkspacePorts(),"ports.list-system":async(a,e)=>await e.services.portMonitor.listSystemPorts(),"ports.kill":async(a,e)=>{let t=a;return await e.services.portMonitor.killPort(t.port,t.pid)},"ports.start-monitor":async(a,e)=>{let t=a;return await e.services.portMonitor.startMonitoring(t.workspaceId,t.terminalIds||[]),{ok:!0}},"ports.stop-monitor":(a,e)=>{let t=a;return e.services.portMonitor.stopMonitoring(t.workspaceId),{ok:!0}},"system.listDir":a=>{let e=a,t=Wt.homedir(),r=e.path||t;r==="~"?r=t:r.startsWith("~/")&&(r=P.join(t,r.slice(2))),r=P.resolve(r);try{let s=te.readdirSync(r),n=[];for(let i of s){if(!e.showHidden&&i.startsWith("."))continue;let o=P.join(r,i);try{te.statSync(o).isDirectory()&&n.push({name:i,path:o})}catch{}}return n.sort((i,o)=>i.name.localeCompare(o.name)),{current:r,parent:P.dirname(r),home:t,dirs:n}}catch(s){return{current:r,parent:P.dirname(r),home:t,dirs:[],error:s.message}}},"system.createDir":a=>{let t=a.path,r=Wt.homedir();t.startsWith("~/")&&(t=P.join(r,t.slice(2))),t=P.resolve(t);try{return te.mkdirSync(t,{recursive:!0}),{ok:!0,path:t}}catch(s){return{ok:!1,error:s.message}}},"system.homeDir":()=>{let a=Wt.homedir(),e=[{name:"Home",path:a},{name:"Desktop",path:P.join(a,"Desktop")},{name:"Documents",path:P.join(a,"Documents")},{name:"Downloads",path:P.join(a,"Downloads")},{name:"Development",path:P.join(a,"Development")},{name:"Development",path:P.join(a,"Documents","Development")},{name:"Projects",path:P.join(a,"Projects")},{name:"/",path:"/"}],t=[],r=new Set;for(let s of e){if(r.has(s.name)){if(!t.find(n=>n.name===s.name))try{te.statSync(s.path),t.push(s),r.add(s.name)}catch{}continue}try{te.statSync(s.path),t.push(s),r.add(s.name)}catch{}}return t.find(s=>s.path==="/")||t.push({name:"/",path:"/"}),{home:a,shortcuts:t}},"system.detect-clis":async(a,e)=>{let t=new Map,r=e.services.settingsManager.list();for(let s of r){let n=s.key.match(/^providers\.(.+)\.config$/);if(n)try{let i=JSON.parse(s.value);t.set(n[1],i)}catch{}}return e.services.providerRegistry.setCustomConfigs(t),await e.services.providerRegistry.detectInstalled()},"system.update-provider-config":(a,e)=>{let t=a,r=JSON.stringify({...t.customPath!==void 0?{path:t.customPath}:{},...t.startupCommand!==void 0?{startupCommand:t.startupCommand}:{}});e.services.settingsManager.set({key:`providers.${t.cli}.config`,value:r,category:"general",label:`Provider config for ${t.cli}`});let s=new Map,n=e.services.settingsManager.list();for(let i of n){let o=i.key.match(/^providers\.(.+)\.config$/);if(o)try{let c=JSON.parse(i.value);s.set(o[1],c)}catch{}}return e.services.providerRegistry.setCustomConfigs(s),{ok:!0}},"system.load-provider-configs":(a,e)=>{let t={},r=e.services.settingsManager.list();for(let s of r){let n=s.key.match(/^providers\.(.+)\.config$/);if(n)try{let i=JSON.parse(s.value);t[n[1]]=i}catch{}}return{configs:t}},"system.health-check":async(a,e)=>{let t=a;return t?.cli?{providers:[await e.services.healthCheckService.checkOne(t.cli)],checkedAt:new Date().toISOString()}:await e.services.healthCheckService.checkAll()},"notifications.list":(a,e)=>e.services.notificationService.list(),"notifications.clear":(a,e)=>{let t=a;return e.services.notificationService.clear(t?.id),{ok:!0}},"notifications.mark-read":(a,e)=>{let t=a;return e.services.notificationService.markRead(t.id),{ok:!0}},"ide.list":()=>({editors:Ir.detectInstalledEditors()}),"ide.open":a=>{let e=a;return Ir.openInEditor(e.editor,e.cwd)},ping:()=>({ok:!0,ts:Date.now()})}}function bn(){return{"wireframe.list":(a,e)=>{let t=a;return e.services.wireframeManager.list(t.projectDir)},"wireframe.get":(a,e)=>{let t=a;return e.services.wireframeManager.get(t.projectDir,t.id)},"wireframe.create":(a,e)=>{let t=a;return e.services.wireframeManager.create(t.projectDir,{name:t.name,content:t.content,description:t.description})},"wireframe.update":(a,e)=>{let t=a;return e.services.wireframeManager.update(t.projectDir,t.id,t.content)},"wireframe.delete":(a,e)=>{let t=a;return e.services.wireframeManager.delete(t.projectDir,t.id),{ok:!0}},"wireframe.generate":(a,e)=>{let t=a;return e.services.wireframeManager.generate(t.projectDir,t.id,t.description)},"template.list":(a,e)=>e.services.templateManager.list(),"template.create":(a,e)=>{let t=a;return e.services.templateManager.create(t)},"template.update":(a,e)=>{let t=a;return e.services.templateManager.update(t)},"template.delete":(a,e)=>{let t=a;return{deleted:e.services.templateManager.delete(t.id)}},"promptTemplate.list":(a,e)=>e.services.promptTemplateManager.list(),"promptTemplate.create":(a,e)=>{let t=a;return e.services.promptTemplateManager.create(t)},"promptTemplate.update":(a,e)=>{let t=a;return e.services.promptTemplateManager.update(t)},"promptTemplate.delete":(a,e)=>{let t=a;return{deleted:e.services.promptTemplateManager.delete(t.id)}},"workspaceTemplate.list":(a,e)=>e.services.workspaceTemplateManager.list(),"workspaceTemplate.create":(a,e)=>{let t=a;return e.services.workspaceTemplateManager.create(t)},"workspaceTemplate.update":(a,e)=>{let t=a;return e.services.workspaceTemplateManager.update(t)},"workspaceTemplate.delete":(a,e)=>{let t=a;return{deleted:e.services.workspaceTemplateManager.delete(t.id)}},"stack.list":(a,e)=>e.services.stackManager.list(),"stack.create":(a,e)=>{let t=a;return e.services.stackManager.create(t)},"stack.update":(a,e)=>{let t=a;return e.services.stackManager.update(t)},"stack.delete":(a,e)=>{let t=a;return{deleted:e.services.stackManager.delete(t.id)}},"stack.apply":async(a,e)=>{let t=a,{services:r}=e,s=r.stackManager.get(t.stackId);if(!s)throw new Error(`Stack not found: ${t.stackId}`);let n=r.workspaceManager.create({name:t.workspaceName,color:t.workspaceColor,rootDirectory:t.rootDirectory,initGit:t.initGit,terminalCount:1,stackId:s.id}),i=r.areaManager.getDefaultArea(n.id);if(!i)throw new Error("Default area not created for workspace");return e.respond({workspace:n,areaId:i.id}),r.stackOrchestrator.applyStack({stack:s,workspaceId:n.id,defaultAreaId:i.id,broadcast:r.broadcast},r).catch(o=>{console.error("[stack.apply] Orchestration error:",o)}),null},"layout.list":(a,e)=>{let t=a;return e.services.layoutManager.list(t.workspaceId,t.areaId)},"layout.save":(a,e)=>{let t=a;return e.services.layoutManager.save(t)},"layout.update":(a,e)=>{let t=a;return e.services.layoutManager.update(t.id,t)},"layout.delete":(a,e)=>{let t=a;return{ok:e.services.layoutManager.delete(t.id)}},"layout.setDefault":(a,e)=>{let t=a;return e.services.layoutManager.setDefault(t.workspaceId,t.layoutId,t.areaId),{ok:!0}}}}import{readdir as An,stat as De,readFile as Bt,writeFile as Cr,mkdir as Pe,access as In,rm as Oo,rename as Do}from"node:fs/promises";import{join as qt,resolve as L,relative as Po,dirname as Cn,sep as re}from"node:path";function Ln(){return{"workspace.file.glob":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=new Set(["node_modules",".git","dist","build",".swarm","__pycache__",".next",".turbo"]),i=new Set([".png",".jpg",".jpeg",".gif",".ico",".woff",".woff2",".ttf",".eot",".pdf",".zip",".tar",".gz",".bz2",".mp3",".mp4",".mov",".avi",".webm",".webp",".svg"]),o=t.limit??50,c=t.pattern?.toLowerCase()||"",l=[];async function d(u){if(l.length>=o*5)return;let m;try{m=await An(u,{withFileTypes:!0})}catch{return}for(let p of m){if(l.length>=o*5)return;if(n.has(p.name)||p.isSymbolicLink())continue;let g=qt(u,p.name);if(p.isDirectory())await d(g);else if(p.isFile()){let f="."+(p.name.split(".").pop()?.toLowerCase()||"");if(i.has(f))continue;let h=Po(s,g);if(c&&!h.toLowerCase().includes(c)&&!p.name.toLowerCase().includes(c))continue;try{let w=await De(g);l.push({path:h,basename:p.name,size:w.size,modifiedAt:w.mtime.toISOString()})}catch{}}}}return await d(s),l.sort((u,m)=>m.modifiedAt.localeCompare(u.modifiedAt)),{files:l.slice(0,o)}},"workspace.file.read":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=t.maxSize??1048576,i=L(s,t.filePath);if(!i.startsWith(L(s)+re)&&i!==L(s))return e.respondError("Path traversal not allowed"),null;try{let o=await De(i),c=pr(i),l=gr(i),u=l?10485760:n;return o.size>u?(e.respondError(`File too large: ${o.size} bytes (max ${u})`),null):l?{content:(await Bt(i)).toString("base64"),language:c,size:o.size,path:t.filePath,encoding:"base64",mimeType:mr(i)}:{content:await Bt(i,"utf-8"),language:c,size:o.size,path:t.filePath,encoding:"utf-8",mimeType:mr(i)}}catch(o){let c=o instanceof Error?o.message:"Failed to read file";return e.respondError(c),null}},"workspace.file.tree":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=t.path??".",i=t.depth??3,o=L(s,n);if(!o.startsWith(L(s)+re)&&o!==L(s))return e.respondError("Path traversal not allowed"),null;let c=new Set(["node_modules",".git","dist","build","coverage",".next","__pycache__",".cache",".turbo",".DS_Store"]);async function l(d,u,m){if(m<=0)return[];let p;try{p=await An(d,{withFileTypes:!0})}catch{return[]}let g=[],f=[],h=[];for(let w of p)c.has(w.name)||w.isSymbolicLink()||(w.isDirectory()?f.push(w):w.isFile()&&h.push(w));f.sort((w,S)=>w.name.toLowerCase().localeCompare(S.name.toLowerCase())),h.sort((w,S)=>w.name.toLowerCase().localeCompare(S.name.toLowerCase()));for(let w of[...f,...h]){let S=qt(d,w.name),T=u?`${u}/${w.name}`:w.name;if(w.isDirectory()){let _=await l(S,T,m-1);g.push({name:w.name,path:T,type:"directory",children:_})}else{let _;try{_=(await De(S)).size}catch{}g.push({name:w.name,path:T,type:"file",size:_})}}return g}try{let d=n==="."?"":n.replace(/^\/+/,"");return{entries:await l(o,d,i)}}catch(d){let u=d instanceof Error?d.message:"Failed to read directory";return e.respondError(u),null}},"workspace.file.write":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=L(s,t.filePath);if(!n.startsWith(L(s)+re)&&n!==L(s))return e.respondError("Path traversal not allowed"),null;let i=5242880;if(t.content.length>i)return e.respondError(`Content too large: ${t.content.length} bytes (max ${i})`),null;try{let o=qt(n,"..");return await Pe(o,{recursive:!0}),await Cr(n,t.content,"utf-8"),{ok:!0,size:t.content.length,path:t.filePath}}catch(o){let c=o instanceof Error?o.message:"Failed to write file";return e.respondError(c),null}},"workspace.file.upload":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;if(t.encoding!=="base64")return e.respondError("Only base64 encoding is supported for uploads"),null;let s=r.rootDirectory,n=L(s,t.filePath);if(!n.startsWith(L(s)+re)&&n!==L(s))return e.respondError("Path traversal not allowed"),null;let i;try{i=Buffer.from(t.content,"base64")}catch{return e.respondError("Invalid base64 content"),null}if(i.length>52428800)return e.respondError(`File too large: ${i.length} bytes (max ${52428800})`),null;if(!t.overwrite)try{return await In(n),e.respondError(`File already exists: ${t.filePath}`),null}catch{}try{let o=qt(n,"..");return await Pe(o,{recursive:!0}),await Cr(n,i),{ok:!0,size:i.length,path:t.filePath}}catch(o){let c=o instanceof Error?o.message:"Failed to upload file";return e.respondError(c),null}},"workspace.file.delete":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=L(s,t.filePath),i=L(s);if(!n.startsWith(i+re))return e.respondError("Path traversal not allowed"),null;if(n===i)return e.respondError("Cannot delete workspace root"),null;let o;try{o=(await De(n)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.filePath}`),null}let c=t.recursive??!0,l,d;if(o==="file")try{gr(n)?(l=(await Bt(n)).toString("base64"),d="base64"):(l=await Bt(n,"utf-8"),d="utf-8")}catch{}try{return await Oo(n,{recursive:c,force:!1}),{ok:!0,path:t.filePath,type:o,content:l,encoding:d}}catch(u){let m=u instanceof Error?u.message:"Failed to delete";return e.respondError(m),null}},"workspace.file.move":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=L(s),i=L(s,t.sourcePath),o=L(s,t.destinationPath);if(!i.startsWith(n+re)||!o.startsWith(n+re))return e.respondError("Path traversal not allowed"),null;let c;try{c=(await De(i)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.sourcePath}`),null}try{let l=Cn(o);return await Pe(l,{recursive:!0}),await Do(i,o),{ok:!0,sourcePath:t.sourcePath,destinationPath:t.destinationPath,type:c}}catch(l){let d=l instanceof Error?l.message:"Failed to move";return e.respondError(d),null}},"workspace.file.create":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=L(s,t.filePath),i=L(s);if(!n.startsWith(i+re))return e.respondError("Path traversal not allowed"),null;try{return await In(n),e.respondError(`Already exists: ${t.filePath}`),null}catch{}try{if(t.type==="directory")await Pe(n,{recursive:!0});else{let o=Cn(n);await Pe(o,{recursive:!0}),await Cr(n,"","utf-8")}return{ok:!0,path:t.filePath,type:t.type}}catch(o){let c=o instanceof Error?o.message:"Failed to create";return e.respondError(c),null}}}}function Mn(){return{"git.isGitRepo":async(a,e)=>{let t=a;return{isGitRepo:await e.services.gitManager.isGitRepo(t.cwd)}},"git.init":async(a,e)=>{let t=a;return e.services.gitManager.init(t.cwd)},"git.status":async(a,e)=>{let t=a;return e.services.gitManager.status(t.cwd)},"git.diff":async(a,e)=>{let t=a;return e.services.gitManager.diff(t.cwd,t.staged)},"git.commit":async(a,e)=>{let t=a;return e.services.gitManager.commit(t)},"git.push":async(a,e)=>{let t=a;return e.services.gitManager.push(t)},"git.branches":async(a,e)=>{let t=a;return e.services.gitManager.branches(t.cwd)},"git.createBranch":async(a,e)=>{let t=a;return e.services.gitManager.createBranch(t.cwd,t.name)},"git.checkout":async(a,e)=>{let t=a;return e.services.gitManager.checkoutBranch(t.cwd,t.name)},"git.log":async(a,e)=>{let t=a;return e.services.gitManager.log(t.cwd,t.limit)},"git.fetch":async(a,e)=>{let t=a;return await e.services.gitManager.fetch(t),{ok:!0}},"git.pull":async(a,e)=>{let t=a;return e.services.gitManager.pull(t)},"git.merge":async(a,e)=>{let t=a;return e.services.gitManager.merge(t)},"git.abortMerge":async(a,e)=>{let t=a;return await e.services.gitManager.abortMerge(t.cwd),{ok:!0}},"git.continueMerge":async(a,e)=>{let t=a;return await e.services.gitManager.continueMerge(t.cwd),{ok:!0}},"git.stash":async(a,e)=>{let t=a;return e.services.gitManager.stash(t)},"git.stage":async(a,e)=>{let t=a;return await e.services.gitManager.stage(t),{ok:!0}},"git.unstage":async(a,e)=>{let t=a;return await e.services.gitManager.unstage(t),{ok:!0}},"git.discard":async(a,e)=>{let t=a;return await e.services.gitManager.discard(t),{ok:!0}},"git.conflicts":async(a,e)=>{let t=a;return e.services.gitManager.detectConflicts(t.cwd)},"github.prForBranch":async(a,e)=>{let t=a;return e.services.gitHubCliManager.getPRForBranch(t.cwd,t.branch)},"github.prChecks":async(a,e)=>{let t=a;return e.services.gitHubCliManager.getPRChecks(t.cwd,t.prNumber)},"github.prComments":async(a,e)=>{let t=a;return e.services.gitHubCliManager.getPRComments(t.cwd,t.prNumber)},"github.mergePR":async(a,e)=>{let t=a;return e.services.gitHubCliManager.mergePR(t)},"github.resolveThread":async(a,e)=>{let t=a;return{ok:await e.services.gitHubCliManager.resolveReviewThread(t.cwd,t.threadId,t.resolve)}},"github.authStatus":async(a,e)=>e.services.gitHubCliManager.checkAuth(),"github.listRepos":async(a,e)=>{let t=a;return e.services.gitHubCliManager.listRepos(t)},"github.createRepo":async(a,e)=>{let t=a;return e.services.gitHubCliManager.createRepo(t.name,t.isPrivate)},"github.createPR":async(a,e)=>{let t=a;return e.services.gitHubCliManager.createPR(t)},"github.listPRs":async(a,e)=>{let t=a;return e.services.gitHubCliManager.listPRs(t.cwd)},"github.getConfig":(a,e)=>{let t=a;return e.services.gitHubCliManager.getConfig(t.workspaceId)},"github.saveConfig":(a,e)=>{let t=a;return e.services.gitHubCliManager.saveConfig({workspaceId:t.workspaceId,repoNameWithOwner:t.repoNameWithOwner,repoUrl:t.repoUrl,defaultBranch:t.defaultBranch,connectedAt:new Date().toISOString()}),{ok:!0}},"github.removeConfig":(a,e)=>{let t=a;return e.services.gitHubCliManager.removeConfig(t.workspaceId),{ok:!0}}}}function Nn(){return{"browser.design.inspect":async(a,e)=>{let t=a;return await e.services.browserManager.inspectElementAt(t.sessionId,t.tabId,t.x,t.y)},"browser.design.highlight":async(a,e)=>{let t=a;return await e.services.browserManager.highlightElementAt(t.sessionId,t.tabId,t.x,t.y,t.enabled),{ok:!0}},"browser.design.screenshot":async(a,e)=>{let t=a;return await e.services.browserManager.screenshotRegion(t.sessionId,t.tabId,t.clip)}}}function On(){return{"relay.status":(a,e)=>{let t=e.services.relayClient;return t?{active:!0,...t.getStatus()}:{active:!1,code:null,connected:!1,connectedAt:null,relayUrl:null}},"relay.reconnect":async(a,e)=>{let t=e.services.relayClient;if(!t)throw new Error("Relay is not configured");return{code:await t.reconnect()}}}}function Dn(){return{"skillStore.list":(a,e)=>e.services.skillStoreManager.list(),"skillStore.get":(a,e)=>{let t=a;return e.services.skillStoreManager.get(t.id)},"skillStore.save":(a,e)=>{let t=a;return e.services.skillStoreManager.save(t)},"skillStore.update":(a,e)=>{let t=a;return e.services.skillStoreManager.update(t)},"skillStore.delete":(a,e)=>{let t=a;return e.services.skillStoreManager.delete(t.id)},"skillStore.saveFile":(a,e)=>{let t=a;return e.services.skillStoreManager.saveFile(t.id,t.content)},"skillStore.readFile":(a,e)=>{let t=a;return e.services.skillStoreManager.readFile(t.id)},"skillStore.openFolder":(a,e)=>{let t=a;return e.services.skillStoreManager.openFolder(t.id)},"skillStore.duplicate":(a,e)=>{let t=a;return e.services.skillStoreManager.duplicate(t.id,t.newName)},"skillStore.merge":(a,e)=>{let t=a;return e.services.skillStoreManager.merge(t.skillIds,t.name,t.displayName,t.description)},"skillStore.browseRemote":(a,e)=>e.services.skillStoreManager.browseRemote(a),"skillStore.fetchContent":(a,e)=>{let t=a;return e.services.skillStoreManager.fetchRemoteContent(t.owner,t.repo,t.skillId)},"skillStore.listFiles":(a,e)=>{let t=a;return e.services.skillStoreManager.listSkillFiles(t.id)},"skillStore.readSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.readSkillFile(t.id,t.relativePath)},"skillStore.writeSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.writeSkillFile(t.id,t.relativePath,t.content)},"skillStore.deleteSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.deleteSkillFile(t.id,t.relativePath)},"skillStore.createSkillFolder":(a,e)=>{let t=a;return e.services.skillStoreManager.createSkillFolder(t.id,t.relativePath)},"skillStore.renameSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.renameSkillFile(t.id,t.oldPath,t.newPath)}}}function Pn(){return{"commandStore.list":(a,e)=>e.services.commandStoreManager.list(),"commandStore.get":(a,e)=>{let t=a;return e.services.commandStoreManager.get(t.id)},"commandStore.save":(a,e)=>{let t=a;return e.services.commandStoreManager.save(t)},"commandStore.update":(a,e)=>{let t=a;return e.services.commandStoreManager.update(t)},"commandStore.delete":(a,e)=>{let t=a;return e.services.commandStoreManager.delete(t.id)},"commandStore.readFile":(a,e)=>{let t=a;return e.services.commandStoreManager.readFile(t.id)},"commandStore.writeFile":(a,e)=>{let t=a;return e.services.commandStoreManager.writeFile(t.id,t.content)},"commandStore.duplicate":(a,e)=>{let t=a;return e.services.commandStoreManager.duplicate(t.id,t.newName)}}}function xn(){return{"hookStore.list":(a,e)=>e.services.hookStoreManager.list(),"hookStore.get":(a,e)=>{let t=a;return e.services.hookStoreManager.get(t.id)},"hookStore.save":(a,e)=>{let t=a;return e.services.hookStoreManager.save(t)},"hookStore.update":(a,e)=>{let t=a;return e.services.hookStoreManager.update(t)},"hookStore.delete":(a,e)=>{let t=a;return e.services.hookStoreManager.delete(t.id)},"hookStore.duplicate":(a,e)=>{let t=a;return e.services.hookStoreManager.duplicate(t.id,t.newName)}}}function _n(){return{"agentStore.list":(a,e)=>e.services.agentStoreManager.list(),"agentStore.get":(a,e)=>{let t=a;return e.services.agentStoreManager.get(t.id)},"agentStore.save":(a,e)=>{let t=a;return e.services.agentStoreManager.save(t)},"agentStore.update":(a,e)=>{let t=a;return e.services.agentStoreManager.update(t)},"agentStore.delete":(a,e)=>{let t=a;return e.services.agentStoreManager.delete(t.id)},"agentStore.readFile":(a,e)=>{let t=a;return e.services.agentStoreManager.readFile(t.id)},"agentStore.writeFile":(a,e)=>{let t=a;return e.services.agentStoreManager.writeFile(t.id,t.content)},"agentStore.duplicate":(a,e)=>{let t=a;return e.services.agentStoreManager.duplicate(t.id,t.newName)}}}function Un(){return{"worktree.list":async(a,e)=>{let t=a;return e.services.worktreeManager.listWithMetadata(t.baseDir)},"worktree.create":async(a,e)=>{let t=a;return t.mode==="agent"&&t.swarmId?e.services.worktreeManager.createForAgent(t.baseDir,t.swarmId,t.name,t.workspaceId):e.services.worktreeManager.createForArea(t.baseDir,t.workspaceId||"",t.name,t.branch)},"worktree.remove":async(a,e)=>{let t=a;return e.services.worktreeManager.remove(t.baseDir,t.worktreePath),{ok:!0}},"worktree.updateMeta":async(a,e)=>{let t=a;return e.services.worktreeManager.updateMetadata(t.id,t.updates),{ok:!0}},"worktree.archive":async(a,e)=>{let t=a;return e.services.worktreeManager.updateMetadata(t.id,{isArchived:t.archived}),{ok:!0}},"worktree.getSetupScript":async(a,e)=>{let t=a;return e.services.worktreeManager.getSetupScript(t.workspaceId)},"worktree.setSetupScript":async(a,e)=>{let t=a;return e.services.worktreeManager.setSetupScript(t.script,t.enabled,t.workspaceId),{ok:!0}}}}function Fn(){return{...un(),...pn(),...mn(),...gn(),...hn(),...fn(),...wn(),...Sn(),...Tn(),...En(),...kn(),...bn(),...Ln(),...Mn(),...Nn(),...On(),...Dn(),...Pn(),...xn(),..._n(),...Un()}}var Uo=new Set(["127.0.0.1","::1","::ffff:127.0.0.1","localhost"]);function Fo(a){let e=a.socket.remoteAddress;return e?Uo.has(e):!1}function $o(a){try{return new URL(a.url||"/",`http://${a.headers.host||"localhost"}`).searchParams.get("token")}catch{return null}}function $n(a,e){let t={fn:()=>{}},r={mgr:null},s=new ht((y,k)=>t.fn(y,k)),n=new xo({server:a,path:"/ws",verifyClient:(y,k)=>{if(Fo(y.req)){k(!0);return}if(s.isActive()){let N=$o(y.req);s.validateToken(N)?k(!0):k(!1,401,"Unauthorized: invalid or missing token");return}k(!1,403,"Remote connections not allowed without tunnel")}}),i=[],o=new Set,c=new WeakMap,l=2,d,u,m=setInterval(()=>{for(let y of o){let k=(c.get(y)??0)+1;if(k>l){y.terminate();continue}c.set(y,k),y.ping()}},3e4);n.on("close",()=>{clearInterval(m),$r.dispose()});function p(y,k){let U=JSON.stringify({type:"push",channel:y,data:k});for(let v of o)v.readyState===_o.OPEN&&v.send(U);for(let v of i)try{v(U)}catch{}if(y==="terminal.output"){let v=k;b.onTerminalOutput(v.id,v.data)}if(y==="terminal.exited"){let v=k,C=H.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let{allDone:G,hasError:Y}=H.markTerminalExited(C.id,v.id,v.exitCode);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:v.exitCode,allDone:G}),G){let ue=Y?"blocked":"waiting";H.move(C.id,ue)}}}if(y==="ports.update"&&r.mgr)try{let v=k;r.mgr.cleanupStaleTunnels(v.ports.map(C=>C.port))}catch(v){console.error("[PortTunnelManager] cleanup error:",v)}if(y==="terminal.process"){let v=k;if(v.process.isIdle){let C=H.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let Y=H.getTaskTerminals(C.id).find(ue=>ue.terminalId===v.id);if(Y&&Y.status==="running"){let{allDone:ue,hasError:ia}=H.markTerminalExited(C.id,v.id,0);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:0,allDone:ue}),ue){let oa=ia?"blocked":"waiting";H.move(C.id,oa)}}}}}}e.prepare("UPDATE workspace_state SET isRunning = 0").run(),e.prepare("UPDATE area_state SET isRunning = 0").run();let g=new Ge(p),f=e.prepare("SELECT id FROM terminal_configs").all(),h=new Set(f.map(y=>y.id));try{let y=e.prepare("SELECT data FROM area_runtime_state").all();for(let k of y){let N=JSON.parse(k.data);if(N.terminals)for(let U of N.terminals)h.add(U.id)}}catch{}let w=g.recoverSessions(h);if(w.length>0){let y=e.prepare("SELECT workspaceId, areaId FROM terminal_configs WHERE id = ?"),k=e.prepare("INSERT INTO workspace_state (workspaceId, isRunning) VALUES (?, 1) ON CONFLICT(workspaceId) DO UPDATE SET isRunning = 1"),N=e.prepare("INSERT INTO area_state (areaId, isRunning) VALUES (?, 1) ON CONFLICT(areaId) DO UPDATE SET isRunning = 1"),U=new Map;try{let v=e.prepare("SELECT areaId, data FROM area_runtime_state").all();for(let C of v){let G=JSON.parse(C.data);if(G.terminals)for(let Y of G.terminals)U.set(Y.id,C.areaId)}}catch{}for(let v of w){let C=y.get(v);if(C)k.run(C.workspaceId),C.areaId&&N.run(C.areaId);else{let G=U.get(v);if(G){let Y=e.prepare("SELECT workspaceId FROM areas WHERE id = ?").get(G);Y&&(k.run(Y.workspaceId),N.run(G))}}}console.log("[server] Restored running state for workspaces with recovered terminals")}let S=new Ke(e),T=new je(e,S),_=new at,Q=new dt(e),$=new ut(e),b=new tt(e,g,p,_),Ue=new rt,H=new st(e,p),de=new ct(p),A=new mt(p),K=new gt(p,y=>{let k=g.getProcessInfo(y);return k&&k.pid>0?k.pid:null});t.fn=p;let W=new ft((y,k)=>t.fn(y,k));r.mgr=W;let Kt=new Tt(p),Ae=new Et(e),ne=new yt(e),X=new vt(e);X.seed();let Yt=new bt(e);Yt.seed(X);let Jn=new Rt({terminalManager:g,areaManager:S,workspaceTemplateManager:X,workspaceManager:T}),Qn=new kt(e),Fr=new It(p),$r=new At((y,k)=>{if(p(y,k),y==="notification.new"){let N=k;Fr.add(N.type,N.title,N.message,N.source)}}),Zn=new Lt,ea=new Mt(e),ta=new Dt(e),ra=new xt(e),sa=new _t(e),na=new Ft(e),aa=new me(e);b.setTaskManager(H),b.setSettingsManager(Q);let Wr={terminalManager:g,workspaceManager:T,areaManager:S,swarmManager:b,skillsRegistry:Ue,taskManager:H,providerRegistry:_,prdBuilder:de,settingsManager:Q,cliToolsManager:$,browserManager:A,tunnel:s,portTunnelManager:W,wireframeManager:Kt,templateManager:Ae,promptTemplateManager:ne,workspaceTemplateManager:X,stackManager:Yt,stackOrchestrator:Jn,layoutManager:Qn,healthCheckService:$r,notificationService:Fr,portMonitor:K,gitManager:Zn,gitHubCliManager:ea,relayClient:null,skillStoreManager:ta,commandStoreManager:ra,hookStoreManager:sa,agentStoreManager:na,worktreeManager:aa,broadcast:p},Br=Fn();return n.on("connection",(y,k)=>{o.add(y),c.set(y,0),y.on("pong",()=>{c.set(y,0)});let N=!1;d&&(clearTimeout(d),d=void 0,N=!0),u&&(clearTimeout(u),u=void 0,N=!0),N&&console.log("[server] Client reconnected \u2014 cancelling cleanup timers"),y.on("message",U=>{let v;try{v=JSON.parse(U.toString())}catch{return}Lr(v,y,Wr,Br)}),y.on("close",()=>{if(o.delete(y),o.size===0){console.log("[server] All clients disconnected \u2014 starting grace periods"),d=setTimeout(()=>{console.log("[server] 30s grace expired \u2014 cleaning up non-critical resources"),A.stopAll(),K.dispose(),W.stopAll(),d=void 0},3e4);let U=g.useTmux?1440*60*1e3:14400*1e3;u=setTimeout(()=>{let v=U/36e5;console.log(`[server] ${v}h timeout \u2014 closing all terminals`),g.closeAll(),e.prepare("UPDATE workspace_state SET isRunning = 0").run(),e.prepare("UPDATE area_state SET isRunning = 0").run(),e.prepare("DELETE FROM area_runtime_state").run(),u=void 0},U)}})}),{wss:n,terminalManager:g,workspaceManager:T,swarmManager:b,settingsManager:Q,broadcast:p,externalSenders:i,services:Wr,routes:Br,getClientCount:()=>o.size}}async function Lr(a,e,t,r){let{id:s,method:n,params:i}=a,o=r[n];if(!o){ye(e,{id:s,error:{message:`Unknown method: ${n}`}});return}let c=!1,l={ws:e,id:s,services:t,respond:d=>{c=!0,ye(e,{id:s,result:d})},respondError:d=>{c=!0,ye(e,{id:s,error:{message:d}})}};try{let d=await o(i,l);!c&&d!==null&&d!==void 0&&ye(e,{id:s,result:d})}catch(d){if(!c){let u=d instanceof Error?d.message.replace(/\/Users\/[^\s]+/g,"[path]").replace(/\/home\/[^\s]+/g,"[path]"):"Unknown error";ye(e,{id:s,error:{message:u}})}}}import{DatabaseSync as Wo}from"node:sqlite";import{mkdirSync as Bo,existsSync as qo}from"node:fs";import{join as Wn}from"node:path";import{homedir as Ho}from"node:os";import{randomUUID as Xo}from"node:crypto";var Mr=Wn(Ho(),".impactus-swarm"),Go=Wn(Mr,"swarm.db");function Bn(){qo(Mr)||Bo(Mr,{recursive:!0});let a=new Wo(Go);a.exec("PRAGMA journal_mode = WAL"),a.exec("PRAGMA foreign_keys = ON"),a.exec(`
|
|
317
|
+
`)}};function hn(){return{"task.create":(a,e)=>{let t=a;return e.services.taskManager.create(t)},"task.update":(a,e)=>{let t=a;return e.services.taskManager.update(t.id,t.updates)},"task.delete":(a,e)=>{let t=a;return{deleted:e.services.taskManager.delete(t.id)}},"task.list":(a,e)=>{let t=a;return e.services.taskManager.list(t)},"task.move":(a,e)=>{let t=a;return e.services.taskManager.move(t.id,t.status)},"task.assign":(a,e)=>{let t=a;return e.services.taskManager.assign(t.id,t.agentId)},"task.run":async(a,e)=>{let t=a,{taskManager:r,terminalManager:s,workspaceManager:n,swarmManager:i,providerRegistry:o}=e.services,c=r.get(t.taskId);if(!c)return e.respondError(`Task ${t.taskId} not found`),null;if(t.terminals&&t.terminals.length>0){let $=c.workspaceId?n.get(c.workspaceId):null,b=t.workspaceDir||$?.rootDirectory||process.cwd(),Ue=[];for(let de=0;de<t.terminals.length;de++){let A=t.terminals[de],K=`task-${c.id}-${de}-${Date.now()}`,W;if(A.command)W=A.command;else if(A.cli){let ne=await new Oe().buildStandaloneContext({task:c,cli:A.cli,prompt:A.prompt,workspaceDir:b}),X=o.get(A.cli);W=X?X.buildCommand({mission:ne.prompt,cwd:"",autoApprove:A.autoApprove??!1}):A.cli,A.cli==="claude"&&W.startsWith("claude")&&(W=W.replace(/^claude/,"claude -p"))}else W="bash";if(await s.open({id:K,cwd:b,command:W,env:t.env,cols:120,rows:30}),A.command){let Ae=A.promptDelay??3e3;if(A.commandSequence&&A.commandSequence.length>0){let ne=0;for(let X of A.commandSequence)ne+=X.delay,setTimeout(()=>{s.write(K,X.command+"\r")},ne);A.prompt&&setTimeout(()=>{s.write(K,A.prompt+"\r")},ne+Ae)}else A.prompt&&setTimeout(()=>{s.write(K,A.prompt+"\r")},Ae)}let Kt=A.cli||A.command||"shell";r.addTerminal(c.id,K,Kt,A.prompt,A.autoApprove??!1),Ue.push(K)}return r.move(c.id,"running"),{taskId:c.id,terminalIds:Ue,workDir:b}}let l=t.agentId||c.assignedAgentId;if(!l)return e.respondError(`No agent assigned to task ${t.taskId}`),null;if(!c.swarmId)return e.respondError(`Task ${t.taskId} has no swarm`),null;let d=i.get(c.swarmId);if(!d)return e.respondError(`Swarm ${c.swarmId} not found`),null;let u=d.agents.find($=>$.id===l);if(!u)return e.respondError(`Agent ${l} not found in swarm`),null;let p=t.includeKnowledge!==!1?d.knowledge:void 0,g;t.includeDependencies&&c.dependencies.length>0&&(g=c.dependencies.map($=>r.get($)).filter($=>$!==null));let h=await new Oe().buildContext({task:c,agent:u,swarm:d,knowledgeEntries:p,dependencyTasks:g,workspaceDir:d.directory}),w=o.get(u.cli),S=w?w.buildCommand({mission:h.prompt,cwd:"",autoApprove:u.autoApprove||d.autoApprove}):u.cli,T=`task-${c.id}-${l.slice(0,8)}`,_=u.worktreePath||d.directory;return await s.open({id:T,cwd:_,command:S,env:t.env,cols:120,rows:30}),r.update(c.id,{}),r.move(c.id,"running"),r.updateTerminalId(c.id,T),{terminalId:T,terminalIds:[T],taskId:c.id,agentId:l,workDir:d.directory,cwd:_}},"task.stop":(a,e)=>{let t=a,{taskManager:r,terminalManager:s}=e.services,n=r.getTaskTerminals(t.taskId),i=[];for(let o of n)if(o.status==="running"){try{s.close(o.terminalId)}catch{}r.markTerminalExited(t.taskId,o.terminalId,-1),i.push(o.terminalId)}return r.move(t.taskId,"blocked"),e.services.broadcast("task.stopped",{taskId:t.taskId,terminalIds:i}),{taskId:t.taskId,killedTerminals:i}},"task.archive":(a,e)=>{let t=a;return e.services.taskManager.move(t.taskId,"archived")},"task.terminals":(a,e)=>{let t=a;return e.services.taskManager.getTaskTerminals(t.taskId)}}}function fn(){return{"knowledge.add":(a,e)=>{let t=a;return e.services.swarmManager.getKnowledgeManager().addEntry(t)},"knowledge.update":(a,e)=>{let t=a;return e.services.swarmManager.getKnowledgeManager().updateEntry(t)},"knowledge.delete":(a,e)=>{let t=a;return e.services.swarmManager.getKnowledgeManager().deleteEntry(t.entryId)},"knowledge.verify":(a,e)=>{let t=a;return e.services.swarmManager.getKnowledgeManager().verifyEntry(t.entryId,t.verified)},"knowledge.search":(a,e)=>{let t=a;return e.services.swarmManager.getKnowledgeManager().search(t)},"knowledge.get-all":(a,e)=>{let t=a;return e.services.swarmManager.getKnowledgeManager().getAllForSwarm(t.swarmId,t.limit)},"mailbox.post":(a,e)=>{let t=a;return e.services.swarmManager.getMailboxManager().post(t)},"mailbox.list":(a,e)=>{let t=a;return e.services.swarmManager.getMailboxManager().list(t)},"mailbox.mark-read":(a,e)=>{let t=a;return e.services.swarmManager.getMailboxManager().markRead(t.messageId,t.agentId),{ok:!0}},"mailbox.get-thread":(a,e)=>{let t=a;return e.services.swarmManager.getMailboxManager().getThread(t.parentMessageId)}}}function wn(){return{"settings.list":(a,e)=>{let t=a;return e.services.settingsManager.list(t.category)},"settings.get":(a,e)=>{let t=a;return e.services.settingsManager.get(t.key)},"settings.set":(a,e)=>{let t=a;return e.services.settingsManager.set(t)},"settings.delete":(a,e)=>{let t=a;return{deleted:e.services.settingsManager.delete(t.key)}},"settings.get-secret":(a,e)=>{let t=a;return{value:e.services.settingsManager.getSecret(t.key)}},"workspace.settings.list":(a,e)=>{let t=a;return e.services.settingsManager.listWorkspaceSettings(t.workspaceId)},"workspace.settings.set":(a,e)=>{let t=a;return e.services.settingsManager.setWorkspaceSetting(t)},"workspace.settings.delete":(a,e)=>{let t=a;return{deleted:e.services.settingsManager.deleteWorkspaceSetting(t.workspaceId,t.key)}},"workspace.settings.get-secret":(a,e)=>{let t=a;return{value:e.services.settingsManager.getWorkspaceSecret(t.workspaceId,t.key)}},"workspace.settings.resolved":(a,e)=>{let t=a;return e.services.settingsManager.getResolvedApiKeys(t.workspaceId)},"cli-tools.list":(a,e)=>{let t=a;return e.services.cliToolsManager.list(t.category)},"cli-tools.create":(a,e)=>{let t=a;return e.services.cliToolsManager.create(t)},"cli-tools.update":(a,e)=>{let t=a;return e.services.cliToolsManager.update(t)},"cli-tools.delete":(a,e)=>{let t=a;return{deleted:e.services.cliToolsManager.delete(t.id)}},"cli-tools.health-check":async(a,e)=>{let t=a;return await e.services.cliToolsManager.healthCheck(t.id)},"cli-tools.health-check-all":async(a,e)=>{let t=a;return await e.services.cliToolsManager.healthCheckAll(t.category)}}}function Sn(){return{"registry.list-skills":(a,e)=>{let t=a;return e.services.skillsRegistry.listSkills(t.projectDir)},"registry.search-skills":(a,e)=>{let t=a;return e.services.skillsRegistry.searchSkills(t.query)},"registry.install-skill":(a,e)=>{let t=a;return e.services.skillsRegistry.installSkill(t.name,t.projectDir)},"registry.remove-skill":(a,e)=>{let t=a;return e.services.skillsRegistry.removeSkill(t.name,t.projectDir)},"registry.list-bundles":(a,e)=>e.services.skillsRegistry.listBundles(),"registry.install-bundle":(a,e)=>{let t=a;return e.services.skillsRegistry.installBundle(t.bundleId,t.projectDir),{ok:!0}},"registry.list-mcps":(a,e)=>{let t=a;return e.services.skillsRegistry.listMcps(t.projectDir)},"registry.configure-mcp":(a,e)=>{let t=a;return e.services.skillsRegistry.configureMcp(t)}}}function Tn(){return{"prd.start":(a,e)=>{let t=a;return e.services.prdBuilder.startSession(t)},"prd.send-message":(a,e)=>{let t=a;return e.services.prdBuilder.sendMessage(t.sessionId,t.message)},"prd.select-engine":(a,e)=>{let t=a;return e.services.prdBuilder.selectEngine(t.sessionId,t.engine)},"prd.select-stack":(a,e)=>{let t=a;return e.services.prdBuilder.selectStack(t.sessionId,t.techs)},"prd.generate":(a,e)=>{let t=a;return e.services.prdBuilder.generate(t.sessionId)},"prd.get":(a,e)=>{let t=a;return e.services.prdBuilder.getSession(t.sessionId)}}}function En(){return{"browser.session.open":async(a,e)=>{let t=a;return await e.services.browserManager.openSession(t.url)},"browser.session.close":async(a,e)=>{let t=a;return await e.services.browserManager.closeSession(t.sessionId),{ok:!0}},"browser.tab.open":async(a,e)=>{let t=a;return await e.services.browserManager.openTab(t.sessionId,t.url)},"browser.tab.close":async(a,e)=>{let t=a;return await e.services.browserManager.closeTab(t.sessionId,t.tabId),{ok:!0}},"browser.tab.navigate":async(a,e)=>{let t=a;return await e.services.browserManager.navigateTab(t.sessionId,t.tabId,t.url),{ok:!0}},"browser.tab.activate":async(a,e)=>{let t=a;return await e.services.browserManager.activateTab(t.sessionId,t.tabId),{ok:!0}},"browser.tab.back":async(a,e)=>{let t=a;return await e.services.browserManager.goBack(t.sessionId,t.tabId),{ok:!0}},"browser.tab.forward":async(a,e)=>{let t=a;return await e.services.browserManager.goForward(t.sessionId,t.tabId),{ok:!0}},"browser.tab.refresh":async(a,e)=>{let t=a;return await e.services.browserManager.refresh(t.sessionId,t.tabId),{ok:!0}},"browser.input":async(a,e)=>{let t=a;return await e.services.browserManager.sendInput(t.sessionId,t.tabId,t.event),{ok:!0}},"browser.screencast.ack":async(a,e)=>{let t=a;return await e.services.browserManager.ackFrame(t.sessionId,t.tabId,t.frameNumber),{ok:!0}}}}import*as te from"node:fs";import*as Wt from"node:os";import*as P from"node:path";import yn from"node:fs";import vn from"node:path";import{spawn as Mo}from"node:child_process";var No={"Cursor.app":"cursor","Visual Studio Code.app":"vscode","Visual Studio Code - Insiders.app":"vscode-insiders","VSCodium.app":"vscodium","Zed.app":"zed","Windsurf.app":"windsurf","Sublime Text.app":"sublime"},Ar=class{detectInstalledEditors(){let e=new Set,t=(process.env.PATH||"").split(vn.delimiter),r=process.platform==="darwin";for(let s of hr){if(s.command===null){s.id==="finder"&&r&&e.add("finder"),s.id==="terminal"&&e.add("terminal");continue}for(let n of t)try{if(yn.existsSync(vn.join(n,s.command))){e.add(s.id);break}}catch{}}if(r)try{let s=yn.readdirSync("/Applications");for(let n of s){let i=No[n];i&&!e.has(i)&&e.add(i)}}catch{}return Array.from(e)}openInEditor(e,t){try{let r=hr.find(o=>o.id===e);if(!r)return{ok:!1,error:`Unknown editor: ${e}`};let s,n;return e==="finder"?process.platform==="win32"?(s="explorer",n=[t]):process.platform==="linux"?(s="xdg-open",n=[t]):(s="open",n=[t]):e==="terminal"?process.platform==="win32"?(s="cmd",n=["/c","start","cmd","/k",`cd /d "${t}"`]):process.platform==="linux"?(s="xdg-open",n=[t]):(s="open",n=["-a","Terminal",t]):(s=r.command,n=[t]),Mo(s,n,{detached:!0,stdio:"ignore"}).unref(),{ok:!0}}catch(r){return{ok:!1,error:r instanceof Error?r.message:String(r)}}}},Ir=new Ar;function kn(){return{"tunnel.status":async(a,e)=>await e.services.tunnel.getStatus(),"tunnel.start":async(a,e)=>{let t=a;return await e.services.tunnel.startTunnel(t.config),{ok:!0}},"tunnel.stop":(a,e)=>(e.services.tunnel.stopTunnel(),{ok:!0}),"tunnel.url":(a,e)=>({url:e.services.tunnel.getUrl()}),"portTunnels.start":async(a,e)=>{let t=a;return await e.services.portTunnelManager.startTunnel(t.port,t.protocol),{ok:!0}},"portTunnels.stop":(a,e)=>{let t=a;return e.services.portTunnelManager.stopTunnel(t.port),{ok:!0}},"portTunnels.list":async(a,e)=>{let t=await e.services.portTunnelManager.checkInstalled();return{tunnels:e.services.portTunnelManager.getTunnels(),isInstalled:t}},"ports.list":(a,e)=>{let t=a;return e.services.portMonitor.listPorts(t.workspaceId)},"ports.list-all":(a,e)=>e.services.portMonitor.listAllWorkspacePorts(),"ports.list-system":async(a,e)=>await e.services.portMonitor.listSystemPorts(),"ports.kill":async(a,e)=>{let t=a;return await e.services.portMonitor.killPort(t.port,t.pid)},"ports.start-monitor":async(a,e)=>{let t=a;return await e.services.portMonitor.startMonitoring(t.workspaceId,t.terminalIds||[]),{ok:!0}},"ports.stop-monitor":(a,e)=>{let t=a;return e.services.portMonitor.stopMonitoring(t.workspaceId),{ok:!0}},"system.listDir":a=>{let e=a,t=Wt.homedir(),r=e.path||t;r==="~"?r=t:r.startsWith("~/")&&(r=P.join(t,r.slice(2))),r=P.resolve(r);try{let s=te.readdirSync(r),n=[];for(let i of s){if(!e.showHidden&&i.startsWith("."))continue;let o=P.join(r,i);try{te.statSync(o).isDirectory()&&n.push({name:i,path:o})}catch{}}return n.sort((i,o)=>i.name.localeCompare(o.name)),{current:r,parent:P.dirname(r),home:t,dirs:n}}catch(s){return{current:r,parent:P.dirname(r),home:t,dirs:[],error:s.message}}},"system.createDir":a=>{let t=a.path,r=Wt.homedir();t.startsWith("~/")&&(t=P.join(r,t.slice(2))),t=P.resolve(t);try{return te.mkdirSync(t,{recursive:!0}),{ok:!0,path:t}}catch(s){return{ok:!1,error:s.message}}},"system.homeDir":()=>{let a=Wt.homedir(),e=[{name:"Home",path:a},{name:"Desktop",path:P.join(a,"Desktop")},{name:"Documents",path:P.join(a,"Documents")},{name:"Downloads",path:P.join(a,"Downloads")},{name:"Development",path:P.join(a,"Development")},{name:"Development",path:P.join(a,"Documents","Development")},{name:"Projects",path:P.join(a,"Projects")},{name:"/",path:"/"}],t=[],r=new Set;for(let s of e){if(r.has(s.name)){if(!t.find(n=>n.name===s.name))try{te.statSync(s.path),t.push(s),r.add(s.name)}catch{}continue}try{te.statSync(s.path),t.push(s),r.add(s.name)}catch{}}return t.find(s=>s.path==="/")||t.push({name:"/",path:"/"}),{home:a,shortcuts:t}},"system.detect-clis":async(a,e)=>{let t=new Map,r=e.services.settingsManager.list();for(let s of r){let n=s.key.match(/^providers\.(.+)\.config$/);if(n)try{let i=JSON.parse(s.value);t.set(n[1],i)}catch{}}return e.services.providerRegistry.setCustomConfigs(t),await e.services.providerRegistry.detectInstalled()},"system.update-provider-config":(a,e)=>{let t=a,r=JSON.stringify({...t.customPath!==void 0?{path:t.customPath}:{},...t.startupCommand!==void 0?{startupCommand:t.startupCommand}:{}});e.services.settingsManager.set({key:`providers.${t.cli}.config`,value:r,category:"general",label:`Provider config for ${t.cli}`});let s=new Map,n=e.services.settingsManager.list();for(let i of n){let o=i.key.match(/^providers\.(.+)\.config$/);if(o)try{let c=JSON.parse(i.value);s.set(o[1],c)}catch{}}return e.services.providerRegistry.setCustomConfigs(s),{ok:!0}},"system.load-provider-configs":(a,e)=>{let t={},r=e.services.settingsManager.list();for(let s of r){let n=s.key.match(/^providers\.(.+)\.config$/);if(n)try{let i=JSON.parse(s.value);t[n[1]]=i}catch{}}return{configs:t}},"system.health-check":async(a,e)=>{let t=a;return t?.cli?{providers:[await e.services.healthCheckService.checkOne(t.cli)],checkedAt:new Date().toISOString()}:await e.services.healthCheckService.checkAll()},"notifications.list":(a,e)=>e.services.notificationService.list(),"notifications.clear":(a,e)=>{let t=a;return e.services.notificationService.clear(t?.id),{ok:!0}},"notifications.mark-read":(a,e)=>{let t=a;return e.services.notificationService.markRead(t.id),{ok:!0}},"ide.list":()=>({editors:Ir.detectInstalledEditors()}),"ide.open":a=>{let e=a;return Ir.openInEditor(e.editor,e.cwd)},ping:()=>({ok:!0,ts:Date.now()})}}function bn(){return{"wireframe.list":(a,e)=>{let t=a;return e.services.wireframeManager.list(t.projectDir)},"wireframe.get":(a,e)=>{let t=a;return e.services.wireframeManager.get(t.projectDir,t.id)},"wireframe.create":(a,e)=>{let t=a;return e.services.wireframeManager.create(t.projectDir,{name:t.name,content:t.content,description:t.description})},"wireframe.update":(a,e)=>{let t=a;return e.services.wireframeManager.update(t.projectDir,t.id,t.content)},"wireframe.delete":(a,e)=>{let t=a;return e.services.wireframeManager.delete(t.projectDir,t.id),{ok:!0}},"wireframe.generate":(a,e)=>{let t=a;return e.services.wireframeManager.generate(t.projectDir,t.id,t.description)},"template.list":(a,e)=>e.services.templateManager.list(),"template.create":(a,e)=>{let t=a;return e.services.templateManager.create(t)},"template.update":(a,e)=>{let t=a;return e.services.templateManager.update(t)},"template.delete":(a,e)=>{let t=a;return{deleted:e.services.templateManager.delete(t.id)}},"promptTemplate.list":(a,e)=>e.services.promptTemplateManager.list(),"promptTemplate.create":(a,e)=>{let t=a;return e.services.promptTemplateManager.create(t)},"promptTemplate.update":(a,e)=>{let t=a;return e.services.promptTemplateManager.update(t)},"promptTemplate.delete":(a,e)=>{let t=a;return{deleted:e.services.promptTemplateManager.delete(t.id)}},"workspaceTemplate.list":(a,e)=>e.services.workspaceTemplateManager.list(),"workspaceTemplate.create":(a,e)=>{let t=a;return e.services.workspaceTemplateManager.create(t)},"workspaceTemplate.update":(a,e)=>{let t=a;return e.services.workspaceTemplateManager.update(t)},"workspaceTemplate.delete":(a,e)=>{let t=a;return{deleted:e.services.workspaceTemplateManager.delete(t.id)}},"stack.list":(a,e)=>e.services.stackManager.list(),"stack.create":(a,e)=>{let t=a;return e.services.stackManager.create(t)},"stack.update":(a,e)=>{let t=a;return e.services.stackManager.update(t)},"stack.delete":(a,e)=>{let t=a;return{deleted:e.services.stackManager.delete(t.id)}},"stack.apply":async(a,e)=>{let t=a,{services:r}=e,s=r.stackManager.get(t.stackId);if(!s)throw new Error(`Stack not found: ${t.stackId}`);let n=r.workspaceManager.create({name:t.workspaceName,color:t.workspaceColor,rootDirectory:t.rootDirectory,initGit:t.initGit,terminalCount:1,stackId:s.id}),i=r.areaManager.getDefaultArea(n.id);if(!i)throw new Error("Default area not created for workspace");return e.respond({workspace:n,areaId:i.id}),r.stackOrchestrator.applyStack({stack:s,workspaceId:n.id,defaultAreaId:i.id,broadcast:r.broadcast},r).catch(o=>{console.error("[stack.apply] Orchestration error:",o)}),null},"layout.list":(a,e)=>{let t=a;return e.services.layoutManager.list(t.workspaceId,t.areaId)},"layout.save":(a,e)=>{let t=a;return e.services.layoutManager.save(t)},"layout.update":(a,e)=>{let t=a;return e.services.layoutManager.update(t.id,t)},"layout.delete":(a,e)=>{let t=a;return{ok:e.services.layoutManager.delete(t.id)}},"layout.setDefault":(a,e)=>{let t=a;return e.services.layoutManager.setDefault(t.workspaceId,t.layoutId,t.areaId),{ok:!0}}}}import{readdir as An,stat as De,readFile as Bt,writeFile as Cr,mkdir as Pe,access as In,rm as Oo,rename as Do}from"node:fs/promises";import{join as qt,resolve as M,relative as Po,dirname as Cn,sep as re}from"node:path";function Ln(){return{"workspace.file.glob":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=new Set(["node_modules",".git","dist","build",".swarm","__pycache__",".next",".turbo"]),i=new Set([".png",".jpg",".jpeg",".gif",".ico",".woff",".woff2",".ttf",".eot",".pdf",".zip",".tar",".gz",".bz2",".mp3",".mp4",".mov",".avi",".webm",".webp",".svg"]),o=t.limit??50,c=t.pattern?.toLowerCase()||"",l=[];async function d(u){if(l.length>=o*5)return;let m;try{m=await An(u,{withFileTypes:!0})}catch{return}for(let p of m){if(l.length>=o*5)return;if(n.has(p.name)||p.isSymbolicLink())continue;let g=qt(u,p.name);if(p.isDirectory())await d(g);else if(p.isFile()){let f="."+(p.name.split(".").pop()?.toLowerCase()||"");if(i.has(f))continue;let h=Po(s,g);if(c&&!h.toLowerCase().includes(c)&&!p.name.toLowerCase().includes(c))continue;try{let w=await De(g);l.push({path:h,basename:p.name,size:w.size,modifiedAt:w.mtime.toISOString()})}catch{}}}}return await d(s),l.sort((u,m)=>m.modifiedAt.localeCompare(u.modifiedAt)),{files:l.slice(0,o)}},"workspace.file.read":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=t.maxSize??1048576,i=M(s,t.filePath);if(!i.startsWith(M(s)+re)&&i!==M(s))return e.respondError("Path traversal not allowed"),null;try{let o=await De(i),c=pr(i),l=gr(i),u=l?10485760:n;return o.size>u?(e.respondError(`File too large: ${o.size} bytes (max ${u})`),null):l?{content:(await Bt(i)).toString("base64"),language:c,size:o.size,path:t.filePath,encoding:"base64",mimeType:mr(i)}:{content:await Bt(i,"utf-8"),language:c,size:o.size,path:t.filePath,encoding:"utf-8",mimeType:mr(i)}}catch(o){let c=o instanceof Error?o.message:"Failed to read file";return e.respondError(c),null}},"workspace.file.tree":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=t.path??".",i=t.depth??3,o=M(s,n);if(!o.startsWith(M(s)+re)&&o!==M(s))return e.respondError("Path traversal not allowed"),null;let c=new Set(["node_modules",".git","dist","build","coverage",".next","__pycache__",".cache",".turbo",".DS_Store"]);async function l(d,u,m){if(m<=0)return[];let p;try{p=await An(d,{withFileTypes:!0})}catch{return[]}let g=[],f=[],h=[];for(let w of p)c.has(w.name)||w.isSymbolicLink()||(w.isDirectory()?f.push(w):w.isFile()&&h.push(w));f.sort((w,S)=>w.name.toLowerCase().localeCompare(S.name.toLowerCase())),h.sort((w,S)=>w.name.toLowerCase().localeCompare(S.name.toLowerCase()));for(let w of[...f,...h]){let S=qt(d,w.name),T=u?`${u}/${w.name}`:w.name;if(w.isDirectory()){let _=await l(S,T,m-1);g.push({name:w.name,path:T,type:"directory",children:_})}else{let _;try{_=(await De(S)).size}catch{}g.push({name:w.name,path:T,type:"file",size:_})}}return g}try{let d=n==="."?"":n.replace(/^\/+/,"");return{entries:await l(o,d,i)}}catch(d){let u=d instanceof Error?d.message:"Failed to read directory";return e.respondError(u),null}},"workspace.file.write":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=M(s,t.filePath);if(!n.startsWith(M(s)+re)&&n!==M(s))return e.respondError("Path traversal not allowed"),null;let i=5242880;if(t.content.length>i)return e.respondError(`Content too large: ${t.content.length} bytes (max ${i})`),null;try{let o=qt(n,"..");return await Pe(o,{recursive:!0}),await Cr(n,t.content,"utf-8"),{ok:!0,size:t.content.length,path:t.filePath}}catch(o){let c=o instanceof Error?o.message:"Failed to write file";return e.respondError(c),null}},"workspace.file.upload":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;if(t.encoding!=="base64")return e.respondError("Only base64 encoding is supported for uploads"),null;let s=r.rootDirectory,n=M(s,t.filePath);if(!n.startsWith(M(s)+re)&&n!==M(s))return e.respondError("Path traversal not allowed"),null;let i;try{i=Buffer.from(t.content,"base64")}catch{return e.respondError("Invalid base64 content"),null}if(i.length>52428800)return e.respondError(`File too large: ${i.length} bytes (max ${52428800})`),null;if(!t.overwrite)try{return await In(n),e.respondError(`File already exists: ${t.filePath}`),null}catch{}try{let o=qt(n,"..");return await Pe(o,{recursive:!0}),await Cr(n,i),{ok:!0,size:i.length,path:t.filePath}}catch(o){let c=o instanceof Error?o.message:"Failed to upload file";return e.respondError(c),null}},"workspace.file.delete":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=M(s,t.filePath),i=M(s);if(!n.startsWith(i+re))return e.respondError("Path traversal not allowed"),null;if(n===i)return e.respondError("Cannot delete workspace root"),null;let o;try{o=(await De(n)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.filePath}`),null}let c=t.recursive??!0,l,d;if(o==="file")try{gr(n)?(l=(await Bt(n)).toString("base64"),d="base64"):(l=await Bt(n,"utf-8"),d="utf-8")}catch{}try{return await Oo(n,{recursive:c,force:!1}),{ok:!0,path:t.filePath,type:o,content:l,encoding:d}}catch(u){let m=u instanceof Error?u.message:"Failed to delete";return e.respondError(m),null}},"workspace.file.move":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=M(s),i=M(s,t.sourcePath),o=M(s,t.destinationPath);if(!i.startsWith(n+re)||!o.startsWith(n+re))return e.respondError("Path traversal not allowed"),null;let c;try{c=(await De(i)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.sourcePath}`),null}try{let l=Cn(o);return await Pe(l,{recursive:!0}),await Do(i,o),{ok:!0,sourcePath:t.sourcePath,destinationPath:t.destinationPath,type:c}}catch(l){let d=l instanceof Error?l.message:"Failed to move";return e.respondError(d),null}},"workspace.file.create":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=M(s,t.filePath),i=M(s);if(!n.startsWith(i+re))return e.respondError("Path traversal not allowed"),null;try{return await In(n),e.respondError(`Already exists: ${t.filePath}`),null}catch{}try{if(t.type==="directory")await Pe(n,{recursive:!0});else{let o=Cn(n);await Pe(o,{recursive:!0}),await Cr(n,"","utf-8")}return{ok:!0,path:t.filePath,type:t.type}}catch(o){let c=o instanceof Error?o.message:"Failed to create";return e.respondError(c),null}}}}function Mn(){return{"git.isGitRepo":async(a,e)=>{let t=a;return{isGitRepo:await e.services.gitManager.isGitRepo(t.cwd)}},"git.init":async(a,e)=>{let t=a;return e.services.gitManager.init(t.cwd)},"git.status":async(a,e)=>{let t=a;return e.services.gitManager.status(t.cwd)},"git.diff":async(a,e)=>{let t=a;return e.services.gitManager.diff(t.cwd,t.staged)},"git.commit":async(a,e)=>{let t=a;return e.services.gitManager.commit(t)},"git.push":async(a,e)=>{let t=a;return e.services.gitManager.push(t)},"git.branches":async(a,e)=>{let t=a;return e.services.gitManager.branches(t.cwd)},"git.createBranch":async(a,e)=>{let t=a;return e.services.gitManager.createBranch(t.cwd,t.name)},"git.checkout":async(a,e)=>{let t=a;return e.services.gitManager.checkoutBranch(t.cwd,t.name)},"git.log":async(a,e)=>{let t=a;return e.services.gitManager.log(t.cwd,t.limit)},"git.fetch":async(a,e)=>{let t=a;return await e.services.gitManager.fetch(t),{ok:!0}},"git.pull":async(a,e)=>{let t=a;return e.services.gitManager.pull(t)},"git.merge":async(a,e)=>{let t=a;return e.services.gitManager.merge(t)},"git.abortMerge":async(a,e)=>{let t=a;return await e.services.gitManager.abortMerge(t.cwd),{ok:!0}},"git.continueMerge":async(a,e)=>{let t=a;return await e.services.gitManager.continueMerge(t.cwd),{ok:!0}},"git.stash":async(a,e)=>{let t=a;return e.services.gitManager.stash(t)},"git.stage":async(a,e)=>{let t=a;return await e.services.gitManager.stage(t),{ok:!0}},"git.unstage":async(a,e)=>{let t=a;return await e.services.gitManager.unstage(t),{ok:!0}},"git.discard":async(a,e)=>{let t=a;return await e.services.gitManager.discard(t),{ok:!0}},"git.conflicts":async(a,e)=>{let t=a;return e.services.gitManager.detectConflicts(t.cwd)},"github.prForBranch":async(a,e)=>{let t=a;return e.services.gitHubCliManager.getPRForBranch(t.cwd,t.branch)},"github.prChecks":async(a,e)=>{let t=a;return e.services.gitHubCliManager.getPRChecks(t.cwd,t.prNumber)},"github.prComments":async(a,e)=>{let t=a;return e.services.gitHubCliManager.getPRComments(t.cwd,t.prNumber)},"github.mergePR":async(a,e)=>{let t=a;return e.services.gitHubCliManager.mergePR(t)},"github.resolveThread":async(a,e)=>{let t=a;return{ok:await e.services.gitHubCliManager.resolveReviewThread(t.cwd,t.threadId,t.resolve)}},"github.authStatus":async(a,e)=>e.services.gitHubCliManager.checkAuth(),"github.listRepos":async(a,e)=>{let t=a;return e.services.gitHubCliManager.listRepos(t)},"github.createRepo":async(a,e)=>{let t=a;return e.services.gitHubCliManager.createRepo(t.name,t.isPrivate)},"github.createPR":async(a,e)=>{let t=a;return e.services.gitHubCliManager.createPR(t)},"github.listPRs":async(a,e)=>{let t=a;return e.services.gitHubCliManager.listPRs(t.cwd)},"github.getConfig":(a,e)=>{let t=a;return e.services.gitHubCliManager.getConfig(t.workspaceId)},"github.saveConfig":(a,e)=>{let t=a;return e.services.gitHubCliManager.saveConfig({workspaceId:t.workspaceId,repoNameWithOwner:t.repoNameWithOwner,repoUrl:t.repoUrl,defaultBranch:t.defaultBranch,connectedAt:new Date().toISOString()}),{ok:!0}},"github.removeConfig":(a,e)=>{let t=a;return e.services.gitHubCliManager.removeConfig(t.workspaceId),{ok:!0}}}}function Nn(){return{"browser.design.inspect":async(a,e)=>{let t=a;return await e.services.browserManager.inspectElementAt(t.sessionId,t.tabId,t.x,t.y)},"browser.design.highlight":async(a,e)=>{let t=a;return await e.services.browserManager.highlightElementAt(t.sessionId,t.tabId,t.x,t.y,t.enabled),{ok:!0}},"browser.design.screenshot":async(a,e)=>{let t=a;return await e.services.browserManager.screenshotRegion(t.sessionId,t.tabId,t.clip)}}}function On(){return{"relay.status":(a,e)=>{let t=e.services.relayClient;return t?{active:!0,...t.getStatus()}:{active:!1,code:null,connected:!1,connectedAt:null,relayUrl:null}},"relay.reconnect":async(a,e)=>{let t=e.services.relayClient;if(!t)throw new Error("Relay is not configured");return{code:await t.reconnect()}}}}function Dn(){return{"skillStore.list":(a,e)=>e.services.skillStoreManager.list(),"skillStore.get":(a,e)=>{let t=a;return e.services.skillStoreManager.get(t.id)},"skillStore.save":(a,e)=>{let t=a;return e.services.skillStoreManager.save(t)},"skillStore.update":(a,e)=>{let t=a;return e.services.skillStoreManager.update(t)},"skillStore.delete":(a,e)=>{let t=a;return e.services.skillStoreManager.delete(t.id)},"skillStore.saveFile":(a,e)=>{let t=a;return e.services.skillStoreManager.saveFile(t.id,t.content)},"skillStore.readFile":(a,e)=>{let t=a;return e.services.skillStoreManager.readFile(t.id)},"skillStore.openFolder":(a,e)=>{let t=a;return e.services.skillStoreManager.openFolder(t.id)},"skillStore.duplicate":(a,e)=>{let t=a;return e.services.skillStoreManager.duplicate(t.id,t.newName)},"skillStore.merge":(a,e)=>{let t=a;return e.services.skillStoreManager.merge(t.skillIds,t.name,t.displayName,t.description)},"skillStore.browseRemote":(a,e)=>e.services.skillStoreManager.browseRemote(a),"skillStore.fetchContent":(a,e)=>{let t=a;return e.services.skillStoreManager.fetchRemoteContent(t.owner,t.repo,t.skillId)},"skillStore.listFiles":(a,e)=>{let t=a;return e.services.skillStoreManager.listSkillFiles(t.id)},"skillStore.readSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.readSkillFile(t.id,t.relativePath)},"skillStore.writeSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.writeSkillFile(t.id,t.relativePath,t.content)},"skillStore.deleteSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.deleteSkillFile(t.id,t.relativePath)},"skillStore.createSkillFolder":(a,e)=>{let t=a;return e.services.skillStoreManager.createSkillFolder(t.id,t.relativePath)},"skillStore.renameSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.renameSkillFile(t.id,t.oldPath,t.newPath)}}}function Pn(){return{"commandStore.list":(a,e)=>e.services.commandStoreManager.list(),"commandStore.get":(a,e)=>{let t=a;return e.services.commandStoreManager.get(t.id)},"commandStore.save":(a,e)=>{let t=a;return e.services.commandStoreManager.save(t)},"commandStore.update":(a,e)=>{let t=a;return e.services.commandStoreManager.update(t)},"commandStore.delete":(a,e)=>{let t=a;return e.services.commandStoreManager.delete(t.id)},"commandStore.readFile":(a,e)=>{let t=a;return e.services.commandStoreManager.readFile(t.id)},"commandStore.writeFile":(a,e)=>{let t=a;return e.services.commandStoreManager.writeFile(t.id,t.content)},"commandStore.duplicate":(a,e)=>{let t=a;return e.services.commandStoreManager.duplicate(t.id,t.newName)}}}function xn(){return{"hookStore.list":(a,e)=>e.services.hookStoreManager.list(),"hookStore.get":(a,e)=>{let t=a;return e.services.hookStoreManager.get(t.id)},"hookStore.save":(a,e)=>{let t=a;return e.services.hookStoreManager.save(t)},"hookStore.update":(a,e)=>{let t=a;return e.services.hookStoreManager.update(t)},"hookStore.delete":(a,e)=>{let t=a;return e.services.hookStoreManager.delete(t.id)},"hookStore.duplicate":(a,e)=>{let t=a;return e.services.hookStoreManager.duplicate(t.id,t.newName)}}}function _n(){return{"agentStore.list":(a,e)=>e.services.agentStoreManager.list(),"agentStore.get":(a,e)=>{let t=a;return e.services.agentStoreManager.get(t.id)},"agentStore.save":(a,e)=>{let t=a;return e.services.agentStoreManager.save(t)},"agentStore.update":(a,e)=>{let t=a;return e.services.agentStoreManager.update(t)},"agentStore.delete":(a,e)=>{let t=a;return e.services.agentStoreManager.delete(t.id)},"agentStore.readFile":(a,e)=>{let t=a;return e.services.agentStoreManager.readFile(t.id)},"agentStore.writeFile":(a,e)=>{let t=a;return e.services.agentStoreManager.writeFile(t.id,t.content)},"agentStore.duplicate":(a,e)=>{let t=a;return e.services.agentStoreManager.duplicate(t.id,t.newName)}}}function Un(){return{"worktree.list":async(a,e)=>{let t=a;return e.services.worktreeManager.listWithMetadata(t.baseDir)},"worktree.create":async(a,e)=>{let t=a;return t.mode==="agent"&&t.swarmId?e.services.worktreeManager.createForAgent(t.baseDir,t.swarmId,t.name,t.workspaceId):e.services.worktreeManager.createForArea(t.baseDir,t.workspaceId||"",t.name,t.branch)},"worktree.remove":async(a,e)=>{let t=a;return e.services.worktreeManager.remove(t.baseDir,t.worktreePath),{ok:!0}},"worktree.updateMeta":async(a,e)=>{let t=a;return e.services.worktreeManager.updateMetadata(t.id,t.updates),{ok:!0}},"worktree.archive":async(a,e)=>{let t=a;return e.services.worktreeManager.updateMetadata(t.id,{isArchived:t.archived}),{ok:!0}},"worktree.getSetupScript":async(a,e)=>{let t=a;return e.services.worktreeManager.getSetupScript(t.workspaceId)},"worktree.setSetupScript":async(a,e)=>{let t=a;return e.services.worktreeManager.setSetupScript(t.script,t.enabled,t.workspaceId),{ok:!0}}}}function Fn(){return{...un(),...pn(),...mn(),...gn(),...hn(),...fn(),...wn(),...Sn(),...Tn(),...En(),...kn(),...bn(),...Ln(),...Mn(),...Nn(),...On(),...Dn(),...Pn(),...xn(),..._n(),...Un()}}var Uo=new Set(["127.0.0.1","::1","::ffff:127.0.0.1","localhost"]);function Fo(a){let e=a.socket.remoteAddress;return e?Uo.has(e):!1}function $o(a){try{return new URL(a.url||"/",`http://${a.headers.host||"localhost"}`).searchParams.get("token")}catch{return null}}function $n(a,e){let t={fn:()=>{}},r={mgr:null},s=new ht((y,k)=>t.fn(y,k)),n=new xo({server:a,path:"/ws",verifyClient:(y,k)=>{if(Fo(y.req)){k(!0);return}if(s.isActive()){let O=$o(y.req);s.validateToken(O)?k(!0):k(!1,401,"Unauthorized: invalid or missing token");return}k(!1,403,"Remote connections not allowed without tunnel")}}),i=[],o=new Set,c=new WeakMap,l=2,d,u,m=setInterval(()=>{for(let y of o){let k=(c.get(y)??0)+1;if(k>l){y.terminate();continue}c.set(y,k),y.ping()}},3e4);n.on("close",()=>{clearInterval(m),$r.dispose()});function p(y,k){let U=JSON.stringify({type:"push",channel:y,data:k});for(let v of o)v.readyState===_o.OPEN&&v.send(U);for(let v of i)try{v(U)}catch{}if(y==="terminal.output"){let v=k;b.onTerminalOutput(v.id,v.data)}if(y==="terminal.exited"){let v=k,C=H.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let{allDone:G,hasError:Y}=H.markTerminalExited(C.id,v.id,v.exitCode);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:v.exitCode,allDone:G}),G){let ue=Y?"blocked":"waiting";H.move(C.id,ue)}}}if(y==="ports.update"&&r.mgr)try{let v=k;r.mgr.cleanupStaleTunnels(v.ports.map(C=>C.port))}catch(v){console.error("[PortTunnelManager] cleanup error:",v)}if(y==="terminal.process"){let v=k;if(v.process.isIdle){let C=H.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let Y=H.getTaskTerminals(C.id).find(ue=>ue.terminalId===v.id);if(Y&&Y.status==="running"){let{allDone:ue,hasError:ia}=H.markTerminalExited(C.id,v.id,0);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:0,allDone:ue}),ue){let oa=ia?"blocked":"waiting";H.move(C.id,oa)}}}}}}e.prepare("UPDATE workspace_state SET isRunning = 0").run(),e.prepare("UPDATE area_state SET isRunning = 0").run();let g=new Ge(p),f=e.prepare("SELECT id FROM terminal_configs").all(),h=new Set(f.map(y=>y.id));try{let y=e.prepare("SELECT data FROM area_runtime_state").all();for(let k of y){let O=JSON.parse(k.data);if(O.terminals)for(let U of O.terminals)h.add(U.id)}}catch{}let w=g.recoverSessions(h);if(w.length>0){let y=e.prepare("SELECT workspaceId, areaId FROM terminal_configs WHERE id = ?"),k=e.prepare("INSERT INTO workspace_state (workspaceId, isRunning) VALUES (?, 1) ON CONFLICT(workspaceId) DO UPDATE SET isRunning = 1"),O=e.prepare("INSERT INTO area_state (areaId, isRunning) VALUES (?, 1) ON CONFLICT(areaId) DO UPDATE SET isRunning = 1"),U=new Map;try{let v=e.prepare("SELECT areaId, data FROM area_runtime_state").all();for(let C of v){let G=JSON.parse(C.data);if(G.terminals)for(let Y of G.terminals)U.set(Y.id,C.areaId)}}catch{}for(let v of w){let C=y.get(v);if(C)k.run(C.workspaceId),C.areaId&&O.run(C.areaId);else{let G=U.get(v);if(G){let Y=e.prepare("SELECT workspaceId FROM areas WHERE id = ?").get(G);Y&&(k.run(Y.workspaceId),O.run(G))}}}console.log("[server] Restored running state for workspaces with recovered terminals")}let S=new Ke(e),T=new je(e,S),_=new at,Q=new dt(e),$=new ut(e),b=new tt(e,g,p,_),Ue=new rt,H=new st(e,p),de=new ct(p),A=new mt(p),K=new gt(p,y=>{let k=g.getProcessInfo(y);return k&&k.pid>0?k.pid:null});t.fn=p;let W=new ft((y,k)=>t.fn(y,k));r.mgr=W;let Kt=new Tt(p),Ae=new Et(e),ne=new yt(e),X=new vt(e);X.seed();let Yt=new bt(e);Yt.seed(X);let Jn=new Rt({terminalManager:g,areaManager:S,workspaceTemplateManager:X,workspaceManager:T}),Qn=new kt(e),Fr=new It(p),$r=new At((y,k)=>{if(p(y,k),y==="notification.new"){let O=k;Fr.add(O.type,O.title,O.message,O.source)}}),Zn=new Lt,ea=new Mt(e),ta=new Dt(e),ra=new xt(e),sa=new _t(e),na=new Ft(e),aa=new me(e);b.setTaskManager(H),b.setSettingsManager(Q);let Wr={terminalManager:g,workspaceManager:T,areaManager:S,swarmManager:b,skillsRegistry:Ue,taskManager:H,providerRegistry:_,prdBuilder:de,settingsManager:Q,cliToolsManager:$,browserManager:A,tunnel:s,portTunnelManager:W,wireframeManager:Kt,templateManager:Ae,promptTemplateManager:ne,workspaceTemplateManager:X,stackManager:Yt,stackOrchestrator:Jn,layoutManager:Qn,healthCheckService:$r,notificationService:Fr,portMonitor:K,gitManager:Zn,gitHubCliManager:ea,relayClient:null,skillStoreManager:ta,commandStoreManager:ra,hookStoreManager:sa,agentStoreManager:na,worktreeManager:aa,broadcast:p},Br=Fn();return n.on("connection",(y,k)=>{o.add(y),c.set(y,0),y.on("pong",()=>{c.set(y,0)});let O=!1;d&&(clearTimeout(d),d=void 0,O=!0),u&&(clearTimeout(u),u=void 0,O=!0),O&&console.log("[server] Client reconnected \u2014 cancelling cleanup timers"),y.on("message",U=>{let v;try{v=JSON.parse(U.toString())}catch{return}Lr(v,y,Wr,Br)}),y.on("close",()=>{if(o.delete(y),o.size===0){console.log("[server] All clients disconnected \u2014 starting grace periods"),d=setTimeout(()=>{console.log("[server] 30s grace expired \u2014 cleaning up non-critical resources"),A.stopAll(),K.dispose(),W.stopAll(),d=void 0},3e4);let U=g.useTmux?1440*60*1e3:14400*1e3;u=setTimeout(()=>{let v=U/36e5;console.log(`[server] ${v}h timeout \u2014 closing all terminals`),g.closeAll(),e.prepare("UPDATE workspace_state SET isRunning = 0").run(),e.prepare("UPDATE area_state SET isRunning = 0").run(),e.prepare("DELETE FROM area_runtime_state").run(),u=void 0},U)}})}),{wss:n,terminalManager:g,workspaceManager:T,swarmManager:b,settingsManager:Q,broadcast:p,externalSenders:i,services:Wr,routes:Br,getClientCount:()=>o.size}}async function Lr(a,e,t,r){let{id:s,method:n,params:i}=a,o=r[n];if(!o){ye(e,{id:s,error:{message:`Unknown method: ${n}`}});return}let c=!1,l={ws:e,id:s,services:t,respond:d=>{c=!0,ye(e,{id:s,result:d})},respondError:d=>{c=!0,ye(e,{id:s,error:{message:d}})}};try{let d=await o(i,l);!c&&d!==null&&d!==void 0&&ye(e,{id:s,result:d})}catch(d){if(!c){let u=d instanceof Error?d.message.replace(/\/Users\/[^\s]+/g,"[path]").replace(/\/home\/[^\s]+/g,"[path]"):"Unknown error";ye(e,{id:s,error:{message:u}})}}}import{DatabaseSync as Wo}from"node:sqlite";import{mkdirSync as Bo,existsSync as qo}from"node:fs";import{join as Wn}from"node:path";import{homedir as Ho}from"node:os";import{randomUUID as Xo}from"node:crypto";var Mr=Wn(Ho(),".impactus-swarm"),Go=Wn(Mr,"swarm.db");function Bn(){qo(Mr)||Bo(Mr,{recursive:!0});let a=new Wo(Go);a.exec("PRAGMA journal_mode = WAL"),a.exec("PRAGMA foreign_keys = ON"),a.exec(`
|
|
317
318
|
CREATE TABLE IF NOT EXISTS workspaces (
|
|
318
319
|
id TEXT PRIMARY KEY,
|
|
319
320
|
name TEXT NOT NULL,
|