impactus-swarm 0.0.13 → 0.0.14

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/server/main.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createRequire } from 'module'; const require = createRequire(import.meta.url);
2
- import{createServer as Di}from"node:http";import{readFileSync as Vs,existsSync as zs}from"node:fs";import{join as cr,extname as Pi}from"node:path";import{WebSocketServer as di,WebSocket as ui}from"ws";import{homedir as Fr}from"node:os";import{execSync as De}from"node:child_process";import{readlinkSync as zn}from"node:fs";import{createRequire as on}from"node:module";import{homedir as cn}from"node:os";import{chmod as nn,mkdir as Ct,writeFile as Lt}from"node:fs/promises";import{join as le}from"node:path";import{tmpdir as an}from"node:os";var Ee=class a{static getInitScript(e){switch(e){case"zsh":return`
2
+ import{createServer as Pi}from"node:http";import{readFileSync as Vs,existsSync as zs}from"node:fs";import{join as cr,extname as xi}from"node:path";import{WebSocketServer as ui,WebSocket as pi}from"ws";import{homedir as Fr}from"node:os";import{execSync as De}from"node:child_process";import{readlinkSync as Jn}from"node:fs";import{createRequire as on}from"node:module";import{homedir as cn}from"node:os";import{chmod as nn,mkdir as Ct,writeFile as Lt}from"node:fs/promises";import{join as le}from"node:path";import{tmpdir as an}from"node:os";var Ee=class a{static getInitScript(e){switch(e){case"zsh":return`
3
3
  # IMPACTUS Swarm Shell Integration (OSC 133)
4
4
  __impactus_precmd() {
5
5
  local exit_code=$?
@@ -33,34 +33,34 @@ 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=le(an(),"impactus-shell-integration");if(await Ct(t,{recursive:!0}),await nn(t,448),e==="zsh"){let r=le(t,"zsh");await Ct(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 Lt(le(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 Lt(le(r,".zshenv"),n,"utf-8"),{...a.getEnvVars("zsh"),ZDOTDIR:r}}if(e==="bash"){let r=le(t,"bash");await Ct(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=le(r,".bashrc_impactus");return await Lt(n,s,"utf-8"),{...a.getEnvVars("bash"),BASH_ENV:n}}}catch{}return a.getEnvVars(e)}};var ln=on(import.meta.url),Er=ln("node-pty");function Tr(){return process.platform==="win32"?process.env.COMSPEC||"cmd.exe":process.env.SHELL||"/bin/zsh"}async function Mt(){let a=Tr(),e=Ee.detectShell(a);return Ee.createInjectionEnv(e)}async function Ot(a){let e=Tr(),t=[],r=await Mt(),{PORT:s,IMPACTUS_WEB_DIR:n,RELAY_URL:i,RELAY_ALLOWED_IPS:o,CLAUDECODE:c,...l}=process.env;return Er.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 Nt(a,e,t){return Er.spawn("tmux",a,{name:"xterm-256color",cols:e,rows:t,cwd:cn()})}import{execFileSync as O}from"node:child_process";import{existsSync as dn,writeFileSync as un,mkdirSync as pn}from"node:fs";import{join as Sr}from"node:path";import{homedir as mn}from"node:os";var N="impactus",Ce="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{O("tmux",["-V"],{stdio:"pipe"}),this._available=!0}catch{this._available=!1}return this._available}static ensureConfig(){if(this._configPath)return this._configPath;let e=Sr(mn(),".impactus-swarm");dn(e)||pn(e,{recursive:!0});let t=Sr(e,"tmux.conf");return un(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 switch the outer terminal","# to alternate screen \u2014 this lets xterm.js accumulate scrollback",'set -as terminal-overrides ",xterm*:Tc:smcup@:rmcup@"'].join(`
36
+ `),n=le(r,".bashrc_impactus");return await Lt(n,s,"utf-8"),{...a.getEnvVars("bash"),BASH_ENV:n}}}catch{}return a.getEnvVars(e)}};var ln=on(import.meta.url),Er=ln("node-pty");function Tr(){return process.platform==="win32"?process.env.COMSPEC||"cmd.exe":process.env.SHELL||"/bin/zsh"}async function Mt(){let a=Tr(),e=Ee.detectShell(a);return Ee.createInjectionEnv(e)}async function Ot(a){let e=Tr(),t=[],r=await Mt(),{PORT:s,IMPACTUS_WEB_DIR:n,RELAY_URL:i,RELAY_ALLOWED_IPS:o,CLAUDECODE:c,...l}=process.env;return Er.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 Nt(a,e,t){return Er.spawn("tmux",a,{name:"xterm-256color",cols:e,rows:t,cwd:cn()})}import{execFileSync as O}from"node:child_process";import{existsSync as dn,writeFileSync as un,mkdirSync as pn}from"node:fs";import{join as Sr}from"node:path";import{homedir as mn}from"node:os";var N="impactus",Ce="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{O("tmux",["-V"],{stdio:"pipe"}),this._available=!0}catch{this._available=!1}return this._available}static ensureConfig(){if(this._configPath)return this._configPath;let e=Sr(mn(),".impactus-swarm");dn(e)||pn(e,{recursive:!0});let t=Sr(e,"tmux.conf");return un(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","# Allow smcup/rmcup so TUI apps (like Claude Code plan mode) use","# the alternate screen properly \u2014 this keeps xterm.js scrollback","# clean by preventing TUI rendering artifacts from polluting it.",'set -as terminal-overrides ",xterm*:Tc"'].join(`
37
37
  `)+`
38
38
  `),this._configPath=t,t}static enablePassthrough(){try{O("tmux",["-L",N,"set-option","-g","allow-passthrough","on"],{stdio:"pipe"})}catch{}try{O("tmux",["-L",N,"set-option","-g","escape-time","10"],{stdio:"pipe"})}catch{}}static sessionName(e){return Ce+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",N,"-f",c,"new-session","-d","-s",o,"-x",String(t),"-y",String(r),"-c",s];for(let[f,g]of Object.entries(n))g!==void 0&&g!==""&&l.push("-e",`${f}=${g}`);if(i)for(let[f,g]of Object.entries(i))g!==void 0&&l.push("-e",`${f}=${g}`);let{PORT:d,IMPACTUS_WEB_DIR:u,RELAY_URL:p,RELAY_ALLOWED_IPS:m,...h}=process.env;O("tmux",l,{stdio:"pipe",env:h});try{O("tmux",["-L",N,"set-environment","-t",o,"IMPACTUS_TERMINAL_ID",e],{stdio:"pipe"}),O("tmux",["-L",N,"set-environment","-t",o,"IMPACTUS_CREATED_AT",String(Date.now())],{stdio:"pipe"})}catch{}return this.enablePassthrough(),o}static getAttachArgs(e){return["-L",N,"attach-session","-t",e]}static killSession(e){try{O("tmux",["-L",N,"kill-session","-t",e],{stdio:"pipe"})}catch{}}static listSessions(){try{let e=O("tmux",["-L",N,"list-sessions","-F","#{session_name}"],{stdio:"pipe"}).toString().trim();return e?e.split(`
39
39
  `).filter(t=>t.startsWith(Ce)):[]}catch{return[]}}static hasSession(e){try{return O("tmux",["-L",N,"has-session","-t",e],{stdio:"pipe"}),!0}catch{return!1}}static getTerminalId(e){try{let r=O("tmux",["-L",N,"show-environment","-t",e,"IMPACTUS_TERMINAL_ID"],{stdio:"pipe"}).toString().trim().match(/^IMPACTUS_TERMINAL_ID=(.+)$/);return r?r[1]:null}catch{return e.startsWith(Ce)?e.slice(Ce.length):null}}static getCreatedAt(e){try{let r=O("tmux",["-L",N,"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 O("tmux",["-L",N,"capture-pane","-t",e,"-p","-e","-J","-S","-"],{stdio:"pipe",maxBuffer:10*1024*1024}).toString()}catch{return""}}static getShellPid(e){try{let t=O("tmux",["-L",N,"list-panes","-t",e,"-F","#{pane_pid}"],{stdio:"pipe"}).toString().trim(),r=parseInt(t.split(`
40
40
  `)[0],10);return isNaN(r)?null:r}catch{return null}}static resizeSession(e,t,r){try{O("tmux",["-L",N,"resize-window","-t",e,"-x",String(t),"-y",String(r)],{stdio:"pipe"})}catch{}}static getSessionSize(e){try{let r=O("tmux",["-L",N,"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{O("tmux",["-L",N,"kill-server"],{stdio:"pipe"})}catch{}}};import{randomUUID as gn}from"node:crypto";var Te=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((p,m)=>p.index-m.index);for(let p of d)switch(p.type){case"A":{let m={id:gn(),terminalId:t,status:"prompting",startTime:new Date().toISOString(),lineStart:l};this.activeBlocks.set(t,m),r.push({type:"block-start",terminalId:t,block:{...m}});break}case"C":{let m=this.activeBlocks.get(t);m&&(m.status="executing",r.push({type:"block-executing",terminalId:t,block:{...m}}));break}case"D":{let m=this.activeBlocks.get(t);m&&(m.status="completed",m.exitCode=p.exitCode,m.endTime=new Date().toISOString(),m.lineEnd=l+c,r.push({type:"block-end",terminalId:t,block:{...m}}),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 hn=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function kr(a){return a.replace(hn,"")}var yr=new Set(["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F","\u28FE","\u28FD","\u28FB","\u28BF","\u287F","\u28DF","\u28EF","\u28F7"]),vr=new Set(["\u273B","\u2722","\u26A1","\u25CF","\u25C9","\u25CE","\u25CB","\u25CC","\u23F5"]),fn=/^[\s|/\\\-.*]+$/,wn=/^[\s─━═╌╍┄┅┈┉╴╶╸╺│┃║├┤┬┴┼╋]+$/,En=["\u23F5\u23F5","\u273B ","\u26A1 "];function br(a){let e=kr(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=>yr.has(s)||vr.has(s))||e.length<=10&&fn.test(e)||wn.test(e))return!0;for(let r of En)if(e.startsWith(r))return!0;if(t.length>=1&&t.length<=30){let r=t[0];if(yr.has(r)||vr.has(r))return!0}return!1}function Ir(a){if(a.length===0)return!1;if(a.includes("\r")&&!a.includes(`
41
41
  `))return a.split("\r").filter(s=>s.length>0).every(s=>br(s));let t=a.split(`
42
42
  `).filter(r=>kr(r).trim().length>0);return t.length===0?!0:t.every(r=>br(r))}var Tn=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function Rr(a){return a.replace(Tn,"")}var Ar=/\/\/|\/\*|^\s*#\s/,Cr=/^[+-][^+-]/,Sn=/\?\s*:|:\s*\?|\?\./,yn=/\w\)\?\s*$|\w\?\s*;?\s*$/,vn=/\?[a-zA-Z_]+=\S/,bn=/^\s+at\s+/,kn=/->|=>|::|!=|==/,In=/^#{1,6}\s/,Lr=/^\s*\d+\s*[|:]\s/,Rn=/\b(?:function|def|fn|func|sub|proc)\s+\w/,Mr=/^(?:\s{4,}|\t)/,Or=/\b(?:import|require|from|use|include)\b.*['"`]/,An=/\([^)]*\)\s*\?\s*$/,Cn=/[+\-*/%]=|<<=|>>=/,Ln=/:\s*\w+\?\s*[;,)=]/;function Nr(a){let e=Rr(a).trim();return!(!e.endsWith("?")||e.length<5||Ar.test(e)||Cr.test(e)||Sn.test(e)||yn.test(e)||vn.test(e)||bn.test(e)||kn.test(e)||In.test(e)||Lr.test(e)||Rn.test(e)||Mr.test(e)||Or.test(e)||An.test(e)||Cn.test(e)||Ln.test(e))}function Dr(a){let e=Rr(a).trim();return Cr.test(e)||Lr.test(e)||Mr.test(e)||Ar.test(e)||Or.test(e)}var Le=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(`
43
- `).includes(e)}};var Me=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(){}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 Oe=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 Mn=[/(?: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],On=/(?:retry.?after|wait|try again in)\s*[:=]?\s*(\d+)\s*(s(?:ec)?|m(?:in)?|h(?:our)?)?/i;function Dt(a){for(let e of Mn)if(e.test(a)){let t=On.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 Nn=[/(?: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)/],Dn=/(?:HTTP\s+)?([45]\d{2})/;function Pt(a){for(let e of Nn)if(e.test(a)){let t=Dn.exec(a);return{type:"api-error",data:{message:a.trim().slice(0,300),statusCode:t?parseInt(t[1],10):void 0}}}return null}var Pn=/https?:\/\/(?:github\.com|gitlab\.com|bitbucket\.org)\/[^\s]+\/pull\/(\d+)/gi,xn=/https?:\/\/gitlab\.com\/[^\s]+\/merge_requests\/(\d+)/gi;function xt(a){let e=[];for(let t of[Pn,xn]){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 _n=/(\d{1,3}(?:\.\d+)?)\s*%/,Un=/(\d+)\s*\/\s*(\d+)/,Fn=/\[([█▓▒░=\->#\s]{4,})\]/;function _t(a){let e=_n.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=Un.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 Fn.test(a)?{type:"progress",data:{raw:a.trim().slice(0,100)}}:null}var Bn=/(\d+)\s+(?:tool|sub.?(?:task|agent))s?\s+running/i,Pr=/teammate\s+\w+\s+\((?:working|running|busy)\)/gi,Wn=/(?:task|step|agent)\s+(\d+)\s*(?:\/|of)\s*(\d+)/i;function Ut(a){let e=Bn.exec(a);if(e)return{type:"subtask-count",data:{active:parseInt(e[1],10)}};Pr.lastIndex=0;let t=[],r;for(;(r=Pr.exec(a))!==null;)t.push(r[0]);if(t.length>0)return{type:"subtask-count",data:{active:t.length,teammates:t}};let s=Wn.exec(a);return s?{type:"subtask-count",data:{current:parseInt(s[1],10),total:parseInt(s[2],10)}}:null}var $n=[Dt,Pt,xt,_t,Ut];function xr(a){let e=[];for(let t of $n){let r=t(a);r&&e.push(r)}return e}var Hn=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function qn(a){return a.replace(Hn,"")}var Xn=[/\[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],jn=1e3,Gn=1e4,Kn=10,Yn=500,Vn=1e3,_r=5e3,Ur=5,Ne=class{terminals=new Map;pushHandler;constructor(e){this.pushHandler=e}initTerminal(e,t=24,r=80){this.cleanupTerminal(e);let s={vtBuffer:new Le(t,r),shellState:new Me(e,n=>{this.pushHandler("terminal.shell-state",n)}),bufferAssembler:new Oe,silenceTimerHandle:setInterval(()=>this.checkSilence(e),jn),lastRealOutputAt:0,pendingQuestionLine:null,pendingQuestionAt:0,questionEmitted:!1,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),Ir(s)?r.shellState.onChromeOutput():(r.lastRealOutputAt=Date.now(),r.shellState.onRealOutput(),r.pendingQuestionLine!==null&&(r.chunksAfterQuestion++,r.chunksAfterQuestion>=Kn&&(r.pendingQuestionLine=null,r.chunksAfterQuestion=0)),r.questionEmitted&&(r.questionEmitted=!1,this.pushHandler("terminal.awaiting-input-cleared",{terminalId:e})));let i=qn(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())}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<_r))for(let s of t.split(`
44
- `)){let n=s.trim();if(n.length!==0&&!Dr(s)){for(let i of Xn)if(i.test(n)){r.questionEmitted=!0,r.pendingQuestionLine=null,this.pushHandler("terminal.awaiting-input",{terminalId:e,type:"question",confident:!0,promptText:n.slice(0,200)});return}}}}detectQuestionCandidates(e,t){let r=e.split(`
45
- `);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<_r||r-t.lastResizeAt<Vn||r-t.lastUserInputAt<Yn||t.questionEmitted||t.pendingQuestionLine===null||r-t.lastRealOutputAt<Gn||t.lastRealOutputAt===0)return;let n=t.pendingQuestionLine;if(!Nr(n)){t.pendingQuestionLine=null;return}if(!t.vtBuffer.containsInBottom(n,Ur)){let o=t.vtBuffer.getBottomRows(Ur).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.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(`
46
- `);for(let s of r){let n=s.trim();if(n.length===0)continue;let i=xr(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,this.pushHandler("terminal.awaiting-input",{terminalId:e,type:"error",confident:!0,promptText:o.data.message||"API Error"}))}}}};var Jn=process.platform==="win32",Ft=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"]),Pe=class a{terminals=new Map;pushHandler;commandBlockParser=new Te;outputEventParser;processDetectionInterval;useTmux;constructor(e){this.pushHandler=e,this.outputEventParser=new Ne(e),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.detectProcesses()},3e3)}detectProcesses(){for(let[,e]of this.terminals){let t=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}))}}getEffectivePid(e){if(e.tmuxSession){let t=R.getShellPid(e.tmuxSession);if(t)return t}return e.pty.pid}detectProcessForTerminal(e){let t=this.getEffectivePid(e),r;try{if(Jn){let n=De(`wmic process where (ParentProcessId=${t}) get Name /format:list`,{stdio:"pipe",timeout:2e3}).toString().trim().split(`
43
+ `).includes(e)}};var Me=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(){}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 Oe=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 Mn=[/(?: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],On=/(?:retry.?after|wait|try again in)\s*[:=]?\s*(\d+)\s*(s(?:ec)?|m(?:in)?|h(?:our)?)?/i;function Dt(a){for(let e of Mn)if(e.test(a)){let t=On.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 Nn=[/(?: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)/],Dn=/(?:HTTP\s+)?([45]\d{2})/;function Pt(a){for(let e of Nn)if(e.test(a)){let t=Dn.exec(a);return{type:"api-error",data:{message:a.trim().slice(0,300),statusCode:t?parseInt(t[1],10):void 0}}}return null}var Pn=/https?:\/\/(?:github\.com|gitlab\.com|bitbucket\.org)\/[^\s]+\/pull\/(\d+)/gi,xn=/https?:\/\/gitlab\.com\/[^\s]+\/merge_requests\/(\d+)/gi;function xt(a){let e=[];for(let t of[Pn,xn]){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 _n=/(\d{1,3}(?:\.\d+)?)\s*%/,Un=/(\d+)\s*\/\s*(\d+)/,Fn=/\[([█▓▒░=\->#\s]{4,})\]/;function _t(a){let e=_n.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=Un.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 Fn.test(a)?{type:"progress",data:{raw:a.trim().slice(0,100)}}:null}var Bn=/(\d+)\s+(?:tool|sub.?(?:task|agent))s?\s+running/i,Pr=/teammate\s+\w+\s+\((?:working|running|busy)\)/gi,Wn=/(?:task|step|agent)\s+(\d+)\s*(?:\/|of)\s*(\d+)/i;function Ut(a){let e=Bn.exec(a);if(e)return{type:"subtask-count",data:{active:parseInt(e[1],10)}};Pr.lastIndex=0;let t=[],r;for(;(r=Pr.exec(a))!==null;)t.push(r[0]);if(t.length>0)return{type:"subtask-count",data:{active:t.length,teammates:t}};let s=Wn.exec(a);return s?{type:"subtask-count",data:{current:parseInt(s[1],10),total:parseInt(s[2],10)}}:null}var $n=[Dt,Pt,xt,_t,Ut];function xr(a){let e=[];for(let t of $n){let r=t(a);r&&e.push(r)}return e}var Hn=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function qn(a){return a.replace(Hn,"")}var Xn=[/\[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],jn=1e3,Gn=1e4,Kn=10,Yn=500,Vn=1e3,_r=5e3,Ur=5,zn=2e3,Ne=class{terminals=new Map;pushHandler;constructor(e){this.pushHandler=e}initTerminal(e,t=24,r=80){this.cleanupTerminal(e);let s={vtBuffer:new Le(t,r),shellState:new Me(e,n=>{this.pushHandler("terminal.shell-state",n)}),bufferAssembler:new Oe,silenceTimerHandle:setInterval(()=>this.checkSilence(e),jn),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),Ir(s)?r.shellState.onChromeOutput():(r.lastRealOutputAt=Date.now(),r.shellState.onRealOutput(),r.pendingQuestionLine!==null&&(r.chunksAfterQuestion++,r.chunksAfterQuestion>=Kn&&(r.pendingQuestionLine=null,r.chunksAfterQuestion=0)),r.questionEmitted&&Date.now()-r.questionEmittedAt>=zn&&(r.questionEmitted=!1,r.questionEmittedAt=0,this.pushHandler("terminal.awaiting-input-cleared",{terminalId:e})));let i=qn(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<_r))for(let s of t.split(`
44
+ `)){let n=s.trim();if(n.length!==0&&!Dr(s)){for(let i of Xn)if(i.test(n)){r.questionEmitted=!0,r.questionEmittedAt=Date.now(),r.pendingQuestionLine=null,this.pushHandler("terminal.awaiting-input",{terminalId:e,type:"question",confident:!0,promptText:n.slice(0,200)});return}}}}detectQuestionCandidates(e,t){let r=e.split(`
45
+ `);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<_r||r-t.lastResizeAt<Vn||r-t.lastUserInputAt<Yn||t.questionEmitted||t.pendingQuestionLine===null||r-t.lastRealOutputAt<Gn||t.lastRealOutputAt===0)return;let n=t.pendingQuestionLine;if(!Nr(n)){t.pendingQuestionLine=null;return}if(!t.vtBuffer.containsInBottom(n,Ur)){let o=t.vtBuffer.getBottomRows(Ur).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(`
46
+ `);for(let s of r){let n=s.trim();if(n.length===0)continue;let i=xr(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 Qn=process.platform==="win32",Ft=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"]),Pe=class a{terminals=new Map;pushHandler;commandBlockParser=new Te;outputEventParser;processDetectionInterval;useTmux;constructor(e){this.pushHandler=e,this.outputEventParser=new Ne(e),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.detectProcesses()},3e3)}detectProcesses(){for(let[,e]of this.terminals){let t=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}))}}getEffectivePid(e){if(e.tmuxSession){let t=R.getShellPid(e.tmuxSession);if(t)return t}return e.pty.pid}detectProcessForTerminal(e){let t=this.getEffectivePid(e),r;try{if(Qn){let n=De(`wmic process where (ParentProcessId=${t}) get Name /format:list`,{stdio:"pipe",timeout:2e3}).toString().trim().split(`
47
47
  `).map(i=>i.replace(/^Name=/,"").trim()).filter(i=>i&&!Ft.has(i)&&!Ft.has(i.replace(/\.exe$/i,"")));n.length>0&&(r=n[0].replace(/\.exe$/i,""))}else{let s=De(`ps -p ${t} -o tty= 2>/dev/null`,{stdio:"pipe",timeout:2e3}).toString().trim();if(s&&s!=="?"){let i=De(`ps -o comm= -t ${s} 2>/dev/null`,{stdio:"pipe",timeout:2e3}).toString().trim().split(`
48
48
  `).map(o=>{let c=o.trim();return c.split("/").pop()||c}).filter(o=>o&&!Ft.has(o));i.length>0&&(r=i[0])}}}catch{}return{id:e.id,pid:t,foregroundProcess:r,isIdle:r===void 0}}dispose(){clearInterval(this.processDetectionInterval),this.outputEventParser.dispose()}getProcessInfo(e){let t=this.terminals.get(e);return t?t.lastProcessInfo??this.detectProcessForTerminal(t):null}getAllProcessInfo(){return Array.from(this.terminals.values()).map(e=>e.lastProcessInfo??this.detectProcessForTerminal(e))}async open(e,t){this.terminals.has(e.id)&&this.close(e.id);let r=e.cwd==="~"?Fr():e.cwd.replace(/^~\//,Fr()+"/"),s,n;try{if(this.useTmux){let u=await Mt();n=R.createSession(e.id,e.cols,e.rows,r,u,e.env),s=Nt(R.getAttachArgs(n),e.cols,e.rows)}else s=await Ot({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 Ot({cols:e.cols,rows:e.rows,cwd:r,env:e.env})}catch(p){let m=p instanceof Error?p.message:"Failed to spawn PTY";this.pushHandler("terminal.error",{id:e.id,message:m});return}}else{let p=u instanceof Error?u.message:"Failed to spawn PTY";this.pushHandler("terminal.error",{id:e.id,message:p});return}}let i=new AbortController,o={pty:s,id:e.id,tmuxSession:n,sequenceAbort:i,outputBuffer:""};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,p)=>{u.runOnce&&l.has(p)||d.push({...u,originalIndex:p})}),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},p=Nt(R.getAttachArgs(c),u.cols,u.rows),m=R.capturePane(c),h={pty:p,id:l,tmuxSession:c,outputBuffer:m};this.terminals.set(l,h),this.setupHandlers(h),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));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?Te.stripOSC133(t):t;this.outputEventParser.processOutput(e.id,s);let n={id:e.id,data:s};this.pushHandler("terminal.output",n)}),e.pty.onExit(({exitCode:t})=>{e.sequenceAbort?.abort();let r={id:e.id,exitCode:t};this.pushHandler("terminal.exited",r),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})})}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.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);return t?t.outputBuffer:null}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)}getCwd(e){let t=this.terminals.get(e);if(!t)return null;let r=this.getEffectivePid(t);try{if(process.platform==="darwin"){let n=De(`lsof -a -p ${r} -d cwd -Fn 2>/dev/null`,{stdio:"pipe",timeout:3e3}).toString().trim().split(`
49
- `);for(let i of n)if(i.startsWith("n"))return i.slice(1)}else if(process.platform==="linux")return zn(`/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 Qn}from"node:crypto";var xe=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=Qn(),r=new Date().toISOString(),s=e.icon||e.name.split(" ").map(p=>p[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)
49
+ `);for(let i of n)if(i.startsWith("n"))return i.slice(1)}else if(process.platform==="linux")return Jn(`/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 Zn}from"node:crypto";var xe=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=Zn(),r=new Date().toISOString(),s=e.icon||e.name.split(" ").map(p=>p[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)
50
50
  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();if(this.db.prepare(`UPDATE workspaces SET
51
51
  name = ?, icon = ?, imageUrl = ?, color = ?, rootDirectory = ?, initGit = ?,
52
52
  defaultCommand = ?, terminalCount = ?, layout = ?, updatedAt = ?
53
53
  WHERE id = ?`).run(e.name??t.name,e.icon??t.icon,e.imageUrl===null?null:e.imageUrl!==void 0?e.imageUrl:t.imageUrl??null,e.color??t.color,e.rootDirectory??t.rootDirectory,e.initGit!==void 0?e.initGit?1:0:t.initGit?1:0,e.defaultCommand??t.defaultCommand,e.terminalCount??t.terminalCount,e.layout??t.layout,r,e.id),e.terminals||e.terminalCount!==void 0||e.defaultCommand!==void 0||e.layout!==void 0){let n=this.areaManager.getDefaultArea(e.id);n&&this.areaManager.update({id:n.id,defaultCommand:e.defaultCommand,terminalCount:e.terminalCount,layout:e.layout,terminals:e.terminals})}return this.get(e.id)}delete(e){let t=this.areaManager.list(e);for(let i of t)this.areaManager.delete(i.id);return this.db.prepare("DELETE FROM workspace_state WHERE workspaceId = ?").run(e),this.db.prepare("DELETE FROM workspaces WHERE id = ?").run(e).changes>0}setRunning(e,t){this.db.prepare(`UPDATE workspace_state SET isRunning = ?, lastLaunchedAt = ?
54
- WHERE workspaceId = ?`).run(t?1:0,t?new Date().toISOString():null,e)}isRunning(e){let t=this.areaManager.list(e);for(let n of t)if(this.areaManager.isRunning(n.id))return!0;return this.db.prepare("SELECT isRunning FROM workspace_state WHERE workspaceId = ?").get(e)?.isRunning===1}hydrateWorkspace(e){let t=this.areaManager.list(e.id),r=t.find(d=>d.isDefault)||t[0],s=r?.terminals??[],n=r?.terminalCount??e.terminalCount,i=r?.layout??e.layout,o=r?.defaultCommand??e.defaultCommand,l=this.db.prepare("SELECT isRunning FROM workspace_state WHERE workspaceId = ?").get(e.id);return{id:e.id,name:e.name,icon:e.icon,imageUrl:e.imageUrl||void 0,color:e.color,rootDirectory:e.rootDirectory,initGit:e.initGit===1,stackId:e.stackId||void 0,areas:t,defaultCommand:o,terminalCount:n,layout:i,terminals:s,createdAt:e.createdAt,updatedAt:e.updatedAt,isRunning:l?.isRunning===1}}};import{randomUUID as Bt}from"node:crypto";import{join as Zn}from"node:path";var _e=class{db;constructor(e){this.db=e}list(e){return this.db.prepare('SELECT * FROM areas WHERE workspaceId = ? ORDER BY "order" ASC, createdAt ASC').all(e).map(s=>this.hydrateArea(s))}get(e){let r=this.db.prepare("SELECT * FROM areas WHERE id = ?").get(e);return r?this.hydrateArea(r):null}create(e){let t=Bt(),r=new Date().toISOString(),i=this.db.prepare('SELECT MAX("order") as m FROM areas WHERE workspaceId = ?').get(e.workspaceId)?.m??0,o=e.terminalCount??1;this.db.prepare(`INSERT INTO areas (id, workspaceId, name, color, directory, useWorktree, worktreeBranch, defaultCommand, terminalCount, layout, "order", isDefault, templateId, ignoreOnLaunchAll, trigger, createdAt, updatedAt)
54
+ WHERE workspaceId = ?`).run(t?1:0,t?new Date().toISOString():null,e)}isRunning(e){let t=this.areaManager.list(e);for(let n of t)if(this.areaManager.isRunning(n.id))return!0;return this.db.prepare("SELECT isRunning FROM workspace_state WHERE workspaceId = ?").get(e)?.isRunning===1}hydrateWorkspace(e){let t=this.areaManager.list(e.id),r=t.find(d=>d.isDefault)||t[0],s=r?.terminals??[],n=r?.terminalCount??e.terminalCount,i=r?.layout??e.layout,o=r?.defaultCommand??e.defaultCommand,l=this.db.prepare("SELECT isRunning FROM workspace_state WHERE workspaceId = ?").get(e.id);return{id:e.id,name:e.name,icon:e.icon,imageUrl:e.imageUrl||void 0,color:e.color,rootDirectory:e.rootDirectory,initGit:e.initGit===1,stackId:e.stackId||void 0,areas:t,defaultCommand:o,terminalCount:n,layout:i,terminals:s,createdAt:e.createdAt,updatedAt:e.updatedAt,isRunning:l?.isRunning===1}}};import{randomUUID as Bt}from"node:crypto";import{join as ea}from"node:path";var _e=class{db;constructor(e){this.db=e}list(e){return this.db.prepare('SELECT * FROM areas WHERE workspaceId = ? ORDER BY "order" ASC, createdAt ASC').all(e).map(s=>this.hydrateArea(s))}get(e){let r=this.db.prepare("SELECT * FROM areas WHERE id = ?").get(e);return r?this.hydrateArea(r):null}create(e){let t=Bt(),r=new Date().toISOString(),i=this.db.prepare('SELECT MAX("order") as m FROM areas WHERE workspaceId = ?').get(e.workspaceId)?.m??0,o=e.terminalCount??1;this.db.prepare(`INSERT INTO areas (id, workspaceId, name, color, directory, useWorktree, worktreeBranch, defaultCommand, terminalCount, layout, "order", isDefault, templateId, ignoreOnLaunchAll, trigger, createdAt, updatedAt)
55
55
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(t,e.workspaceId,e.name,e.color||"#7C3AED",e.directory||"",e.useWorktree?1:0,e.worktreeBranch||null,e.defaultCommand||"",o,e.layout||"auto",i+1,0,e.templateId??null,e.ignoreOnLaunchAll?1:0,e.trigger?JSON.stringify(e.trigger):null,r,r);let l=this.db.prepare(`INSERT INTO terminal_configs (id, workspaceId, areaId, label, directory, command, env, position, commandSequence, runOnce, commandRunOnce, startDelay, startWaitFor, startRunOnce, closeAfterCommand, closeDelay, closeWaitFor, color)
56
56
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);for(let u=0;u<o;u++){let p=e.terminals?.[u],m=Bt();l.run(m,e.workspaceId,t,p?.label||`Terminal ${u+1}`,p?.directory||"",p?.command||"",JSON.stringify(p?.env||{}),u,JSON.stringify(p?.commandSequence||[]),p?.runOnce?1:0,p?.commandRunOnce?1:0,p?.startDelay||0,p?.startWaitFor||"",p?.startRunOnce?1:0,p?.closeAfterCommand?1:0,p?.closeDelay??1e3,p?.closeWaitFor||"",p?.color||"default")}return this.db.prepare("INSERT INTO area_state (areaId) VALUES (?)").run(t),this.get(t)}update(e){let t=this.get(e.id);if(!t)return null;let r=new Date().toISOString(),s;if(e.trigger===void 0?s=t.trigger?JSON.stringify(t.trigger):null:e.trigger===null?s=null:s=JSON.stringify(e.trigger),this.db.prepare(`UPDATE areas SET
57
57
  name = ?, color = ?, directory = ?, useWorktree = ?,
58
58
  worktreeBranch = ?, defaultCommand = ?, terminalCount = ?,
59
59
  layout = ?, ignoreOnLaunchAll = ?, trigger = ?, updatedAt = ?
60
60
  WHERE id = ?`).run(e.name??t.name,e.color??t.color,e.directory??t.directory,e.useWorktree!==void 0?e.useWorktree?1:0:t.useWorktree?1:0,e.worktreeBranch!==void 0?e.worktreeBranch||null:t.worktreeBranch||null,e.defaultCommand??t.defaultCommand,e.terminalCount??t.terminalCount,e.layout??t.layout,e.ignoreOnLaunchAll!==void 0?e.ignoreOnLaunchAll?1:0:t.ignoreOnLaunchAll?1:0,s,r,e.id),e.terminals){this.db.prepare("DELETE FROM terminal_configs WHERE areaId = ?").run(e.id);let o=this.db.prepare(`INSERT INTO terminal_configs (id, workspaceId, areaId, label, directory, command, env, position, commandSequence, runOnce, commandRunOnce, startDelay, startWaitFor, startRunOnce, closeAfterCommand, closeDelay, closeWaitFor, color)
61
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),c=e.terminalCount??t.terminalCount;for(let l=0;l<c;l++){let d=e.terminals[l],u=d?.id||Bt();o.run(u,t.workspaceId,e.id,d?.label||`Terminal ${l+1}`,d?.directory||"",d?.command||"",JSON.stringify(d?.env||{}),l,JSON.stringify(d?.commandSequence||[]),d?.runOnce?1:0,d?.commandRunOnce?1:0,d?.startDelay||0,d?.startWaitFor||"",d?.startRunOnce?1:0,d?.closeAfterCommand?1:0,d?.closeDelay??1e3,d?.closeWaitFor||"",d?.color||"default")}}return this.get(e.id)}delete(e){return this.db.prepare("DELETE FROM terminal_configs WHERE areaId = ?").run(e),this.db.prepare("DELETE FROM area_state WHERE areaId = ?").run(e),this.db.prepare("DELETE FROM areas WHERE id = ?").run(e).changes>0}duplicate(e,t){let r=this.get(e);if(!r)throw new Error(`Area not found: ${e}`);return this.create({workspaceId:r.workspaceId,name:t,color:r.color,directory:r.directory,useWorktree:r.useWorktree,worktreeBranch:r.worktreeBranch,defaultCommand:r.defaultCommand,terminalCount:r.terminalCount,terminals:r.terminals.map(s=>({label:s.label,directory:s.directory,command:s.command,env:s.env,commandSequence:s.commandSequence,runOnce:s.runOnce,commandRunOnce:s.commandRunOnce,startDelay:s.startDelay,startWaitFor:s.startWaitFor,startRunOnce:s.startRunOnce,closeAfterCommand:s.closeAfterCommand,closeDelay:s.closeDelay,closeWaitFor:s.closeWaitFor,color:s.color})),layout:r.layout})}getDefaultArea(e){let r=this.db.prepare("SELECT * FROM areas WHERE workspaceId = ? AND isDefault = 1 LIMIT 1").get(e);return r?this.hydrateArea(r):null}resolveForLaunch(e,t){let r=e.directory||t;return e.terminals.filter(n=>!(n.runOnce&&this.db.prepare("SELECT hasLaunched FROM terminal_configs WHERE id = ?").get(n.id)?.hasLaunched===1)).map((n,i)=>{let o=n.directory||".",c=o.startsWith("/")?o:Zn(r,o),u=this.db.prepare("SELECT hasLaunched FROM terminal_configs WHERE id = ?").get(n.id)?.hasLaunched===1,p=n.commandRunOnce&&u,m=p?e.defaultCommand:n.command||e.defaultCommand,h=p?void 0:n.commandSequence;return{id:n.id,label:n.label||`Terminal ${i+1}`,cwd:c,command:m,commandSequence:h,env:{SWARM_WORKSPACE_ID:e.workspaceId,SWARM_WORKSPACE_NAME:"",SWARM_AREA_ID:e.id,SWARM_AREA_NAME:e.name,SWARM_TERMINAL_ID:n.id,SWARM_TERMINAL_LABEL:n.label,SWARM_TERMINAL_INDEX:String(i+1),SWARM_TERMINAL_COUNT:String(e.terminalCount),SWARM_MODE:"web",...n.env},position:i,startDelay:n.startDelay||0,startWaitFor:n.startWaitFor||"",startRunOnce:n.startRunOnce||!1,hasLaunched:u,closeAfterCommand:n.closeAfterCommand||!1,closeDelay:n.closeDelay??1e3,closeWaitFor:n.closeWaitFor||""}})}setRunning(e,t){this.db.prepare(`UPDATE area_state SET isRunning = ?, lastLaunchedAt = ?
62
- WHERE areaId = ?`).run(t?1:0,t?new Date().toISOString():null,e)}isRunning(e){return this.db.prepare("SELECT isRunning FROM area_state WHERE areaId = ?").get(e)?.isRunning===1}setTerminalColor(e,t,r){this.db.prepare("UPDATE terminal_configs SET color = ? WHERE id = ? AND areaId = ?").run(r||"default",e,t)}markTerminalLaunched(e){this.db.prepare("UPDATE terminal_configs SET hasLaunched = 1 WHERE id = ?").run(e)}resetTerminalLaunched(e){this.db.prepare("UPDATE terminal_configs SET hasLaunched = 0, completedSteps = '[]' WHERE id = ?").run(e)}resetAllTerminals(e){this.db.prepare("UPDATE terminal_configs SET hasLaunched = 0, completedSteps = '[]' WHERE areaId = ?").run(e)}markStepCompleted(e,t){let s=this.db.prepare("SELECT completedSteps FROM terminal_configs WHERE id = ?").get(e),n=JSON.parse(s?.completedSteps||"[]");n.includes(t)||(n.push(t),this.db.prepare("UPDATE terminal_configs SET completedSteps = ? WHERE id = ?").run(JSON.stringify(n),e))}getCompletedSteps(e){let r=this.db.prepare("SELECT completedSteps FROM terminal_configs WHERE id = ?").get(e);return JSON.parse(r?.completedSteps||"[]")}saveRuntimeState(e,t){this.db.prepare("INSERT OR REPLACE INTO area_runtime_state (areaId, data, updatedAt) VALUES (?, ?, ?)").run(e,JSON.stringify(t),new Date().toISOString())}getRuntimeState(e){let r=this.db.prepare("SELECT data FROM area_runtime_state WHERE areaId = ?").get(e);return r?JSON.parse(r.data):null}clearRuntimeState(e){this.db.prepare("DELETE FROM area_runtime_state WHERE areaId = ?").run(e)}hydrateArea(e){let r=this.db.prepare("SELECT * FROM terminal_configs WHERE areaId = ? ORDER BY position ASC").all(e.id),s,n=e.trigger;if(n)try{s=JSON.parse(n)}catch{s=void 0}return{id:e.id,workspaceId:e.workspaceId,name:e.name,color:e.color,directory:e.directory,useWorktree:e.useWorktree===1,worktreeBranch:e.worktreeBranch||void 0,worktreePath:e.worktreePath||void 0,defaultCommand:e.defaultCommand,terminalCount:e.terminalCount,layout:e.layout,order:e.order,isDefault:e.isDefault===1,templateId:e.templateId||void 0,ignoreOnLaunchAll:e.ignoreOnLaunchAll===1,trigger:s,createdAt:e.createdAt,updatedAt:e.updatedAt,terminals:r.map(i=>({id:i.id,label:i.label,directory:i.directory,command:i.command,env:JSON.parse(i.env),commandSequence:JSON.parse(i.commandSequence||"[]"),runOnce:i.runOnce===1,commandRunOnce:i.commandRunOnce===1,startDelay:i.startDelay||0,startWaitFor:i.startWaitFor||"",startRunOnce:i.startRunOnce===1,closeAfterCommand:i.closeAfterCommand===1,closeDelay:i.closeDelay??1e3,closeWaitFor:i.closeWaitFor||"",color:i.color||"default"}))}}};import{randomUUID as qt}from"node:crypto";import{mkdirSync as de,writeFileSync as ua}from"node:fs";import{join as K}from"node:path";import{randomUUID as ea}from"node:crypto";import{mkdirSync as ta,writeFileSync as Br}from"node:fs";import{join as Wt}from"node:path";var Ue=class{registry;constructor(e){this.registry=e}async boot(e,t,r,s,n){let i=`swarm-${t.id}-agent-${e.id}-${ea().slice(0,8)}`,o=this.getCommandForCli(e.cli,t.mission,e.autoApprove||t.autoApprove),c=e.name.toLowerCase().replace(/\s+/g,"-"),l=Wt(t.directory,".swarm","agents",c);ta(l,{recursive:!0});let d=this.generateClaudeMd(t,e);if(Br(Wt(l,"CLAUDE.md"),d),e.mcps&&e.mcps.length>0){let h={mcpServers:Object.fromEntries(e.mcps.map(f=>[f,{command:f}]))};Br(Wt(l,".mcp.json"),JSON.stringify(h,null,2))}let u,p,m=t.directory;if(t.useWorktrees&&n&&n.isGitRepo(t.directory))try{let h=n.createForAgent(t.directory,t.id,e.name);u=h.path,p=h.branch,m=h.path}catch(h){console.warn(`[WorktreeManager] Failed to create worktree for agent ${e.name}:`,h)}return await r.open({id:i,cwd:m,command:o,env:s,cols:120,rows:30}),{terminalId:i,worktreePath:u,worktreeBranch:p}}generateClaudeMd(e,t){let r=[`# Agent: ${t.name}`,`## Role: ${t.role}`,"","## Mission",e.mission,"","## Working Directory",e.directory,""];return t.systemPrompt&&r.push("## System Prompt",t.systemPrompt,""),t.workScope&&t.workScope.length>0&&r.push("## Work Scope",...t.workScope.map(s=>`- ${s}`),""),t.role==="coordinator"&&r.push("## Coordinator Instructions",`You are the coordinator of a swarm of ${e.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",...e.agents.map(s=>`- ${s.name} (${s.role}): ${s.systemPrompt||"No specific prompt"}`),""),r.join(`
63
- `)}getCommandForCli(e,t,r){let s=this.registry.get(e);return s?s.buildCommand({mission:t,cwd:"",autoApprove:r}):e}};import{randomUUID as aa}from"node:crypto";import{query as ia}from"@anthropic-ai/claude-agent-sdk";import{randomUUID as ra}from"node:crypto";import{resolve as $t}from"node:path";import{spawn as sa}from"node:child_process";import{query as na}from"@anthropic-ai/claude-agent-sdk";var Wr=1024*1024,$r=5e4,Hr=50,qr=new Set(["PATH","HOME","USER","SHELL","LD_PRELOAD","LD_LIBRARY_PATH","DYLD_INSERT_LIBRARIES","DYLD_LIBRARY_PATH","NODE_OPTIONS","ELECTRON_RUN_AS_NODE","NODE_PATH"]),Fe=class{sessions=new Map;agentSessionCount=new Map;maxCLIsPerAgent;allowedBasePaths;claudeBinaryPath;onEvent;cleanupTimer=null;constructor(e){this.maxCLIsPerAgent=e.maxCLIsPerAgent??5,this.allowedBasePaths=e.allowedBasePaths??[process.cwd()],this.claudeBinaryPath=e.claudeBinaryPath??"claude",this.onEvent=e.onEvent,this.cleanupTimer=setInterval(()=>this.cleanup(3e5),6e4)}dispose(){this.cleanupTimer&&(clearInterval(this.cleanupTimer),this.cleanupTimer=null),this.killAll()}async spawn(e,t){this.validateConfig(t);let r=this.agentSessionCount.get(e)??0;if(r>=this.maxCLIsPerAgent)throw new Error(`Agent ${e} has reached the maximum of ${this.maxCLIsPerAgent} concurrent CLIs`);if([...this.sessions.values()].filter(o=>o.status==="running").length>=Hr)throw new Error(`Global CLI session limit (${Hr}) reached`);let n=ra(),i={id:n,agentId:e,config:t,status:"running",outputBuffer:"",startedAt:new Date().toISOString()};return this.sessions.set(n,i),this.agentSessionCount.set(e,r+1),t.cli==="claude"?this.spawnClaudeSDK(i):this.spawnCLIProcess(i),n}validateConfig(e){if(!e.prompt||e.prompt.length===0)throw new Error("Prompt is required");if(e.prompt.length>$r)throw new Error(`Prompt too long (max ${$r} chars)`);if(e.prompt.includes("\0"))throw new Error("Prompt contains invalid characters");if(e.workDir){let t=$t(e.workDir);if(!this.allowedBasePaths.some(s=>t===$t(s)||t.startsWith($t(s)+"/")))throw new Error(`Working directory "${e.workDir}" is outside allowed paths`)}if(e.env){for(let t of Object.keys(e.env))if(qr.has(t.toUpperCase()))throw new Error(`Environment variable "${t}" cannot be overridden`)}if(e.timeout!==void 0&&(e.timeout<=0||e.timeout>3600))throw new Error("Timeout must be between 1 and 3600 seconds");if(e.maxBudget!==void 0&&(e.maxBudget<=0||e.maxBudget>100))throw new Error("Max budget must be between $0.01 and $100")}sanitizeEnv(e){let t={...process.env};if(!e)return t;for(let[r,s]of Object.entries(e))qr.has(r.toUpperCase())||(t[r]=s);return t}async spawnClaudeSDK(e){let t=e.config,r=new AbortController;e.sdkAbort=r;let s;t.timeout&&(s=setTimeout(()=>{r.abort(),this.completeSession(e.id,"timeout","CLI timed out")},t.timeout*1e3));try{let n=na({prompt:t.prompt,options:{model:t.model||"claude-sonnet-4-6",pathToClaudeCodeExecutable:this.claudeBinaryPath,cwd:t.workDir||process.cwd(),permissionMode:t.autoApprove?"bypassPermissions":"default",allowDangerouslySkipPermissions:t.autoApprove||void 0,maxBudgetUsd:t.maxBudget,abortController:r,env:this.sanitizeEnv(t.env)}}),i="",o;for await(let c of n){if(r.signal.aborted)break;if(c.type==="assistant"){let l=this.extractAssistantText(c);l&&(this.appendToBuffer(e,l),this.onEvent({type:"output",sessionId:e.id,agentId:e.agentId,data:l}))}if(c.type==="result"){let l=c;i=l.result??"",o=l.total_cost_usd}}s&&clearTimeout(s),r.signal.aborted||this.completeSession(e.id,"completed",void 0,i||e.outputBuffer,void 0,o)}catch(n){s&&clearTimeout(s);let i=n instanceof Error?n.message:String(n);this.completeSession(e.id,"error",i)}}extractAssistantText(e){if(e.type!=="assistant")return"";let r=e.message;return!r?.content||!Array.isArray(r.content)?"":r.content.filter(s=>s.type==="text").map(s=>typeof s.text=="string"?s.text:"").join("")}appendToBuffer(e,t){e.outputBuffer+=t,e.outputBuffer.length>Wr&&(e.outputBuffer=e.outputBuffer.slice(-Wr/2))}spawnCLIProcess(e){let t=e.config,{cmd:r,args:s}=this.buildCLICommand(t),n;try{let i=sa(r,s,{cwd:t.workDir||process.cwd(),env:this.sanitizeEnv(t.env),stdio:["pipe","pipe","pipe"]});e.process=i,t.timeout&&(n=setTimeout(()=>{i.kill("SIGTERM"),this.completeSession(e.id,"timeout","CLI timed out")},t.timeout*1e3)),i.stdout?.on("data",o=>{let c=o.toString();this.appendToBuffer(e,c),this.onEvent({type:"output",sessionId:e.id,agentId:e.agentId,data:c})}),i.stderr?.on("data",o=>{this.appendToBuffer(e,o.toString())}),i.on("close",o=>{n&&clearTimeout(n),o===0?this.completeSession(e.id,"completed",void 0,e.outputBuffer,o):this.completeSession(e.id,"error",`Process exited with code ${o}`,e.outputBuffer,o??void 0)}),i.on("error",o=>{n&&clearTimeout(n),this.completeSession(e.id,"error",o.message)})}catch(i){let o=i instanceof Error?i.message:String(i);this.completeSession(e.id,"error",o)}}buildCLICommand(e){switch(e.cli){case"codex":{let t=["exec",e.prompt];return e.autoApprove&&t.push("--dangerously-bypass-approvals-and-sandbox"),t.push("--json"),e.model&&t.push("-m",e.model),{cmd:"codex",args:t}}case"gemini":{let t=["-p",e.prompt];return e.autoApprove&&t.push("--yolo"),t.push("--output-format",e.outputFormat||"json"),e.model&&t.push("-m",e.model),{cmd:"gemini",args:t}}case"opencode":return{cmd:"opencode",args:[e.prompt]};case"cursor":return{cmd:"cursor",args:["--prompt",e.prompt]};default:return{cmd:e.cli,args:[e.prompt]}}}completeSession(e,t,r,s,n,i){let o=this.sessions.get(e);if(!o)return;o.status=t;let c={id:e,cli:o.config.cli,status:t,output:s||o.outputBuffer,exitCode:n,startedAt:o.startedAt,completedAt:new Date().toISOString(),error:r,cost:i};o.result=c;let l=this.agentSessionCount.get(o.agentId)??1;this.agentSessionCount.set(o.agentId,Math.max(0,l-1)),this.onEvent({type:t==="completed"?"completed":"error",sessionId:e,agentId:o.agentId,data:r||s||"",result:c})}kill(e){let t=this.sessions.get(e);t&&(t.sdkAbort&&t.sdkAbort.abort(),t.process&&t.process.kill("SIGTERM"),this.completeSession(e,"error","Killed by user"))}killAllForAgent(e){for(let[,t]of this.sessions)t.agentId===e&&t.status==="running"&&this.kill(t.id)}killAll(){for(let[,e]of this.sessions)e.status==="running"&&this.kill(e.id)}getSessionsForAgent(e){let t=[];for(let r of this.sessions.values())r.agentId===e&&t.push(r);return t}getSession(e){return this.sessions.get(e)}getActiveCount(e){return this.agentSessionCount.get(e)??0}cleanup(e=36e5){let t=Date.now();for(let[r,s]of this.sessions)s.status!=="running"&&s.result?.completedAt&&t-new Date(s.result.completedAt).getTime()>e&&this.sessions.delete(r)}};var Be=class{instances=new Map;cliProvider;config;escalations=new Map;escalationResolvers=new Map;running=!1;autoCaptureCount=new Map;constructor(e){this.config=e,this.cliProvider=new Fe({maxCLIsPerAgent:5,allowedBasePaths:[e.swarm.directory],claudeBinaryPath:e.claudeBinaryPath,onEvent:t=>{t.type==="output"&&this.config.onAgentOutput?.({swarmId:this.config.swarm.id,agentId:t.agentId,agentName:this.getAgentName(t.agentId),type:"tool_result",content:t.data}),t.type==="completed"&&t.result&&this.config.onCLICompleted?.({swarmId:this.config.swarm.id,agentId:t.agentId,sessionId:t.sessionId,result:t.result})}})}async start(){this.running=!0;let e=this.config.topology,t=this.config.swarm.agents;if(!e||t.length===0){await this.runParallel(t),this.finalize();return}if(e.executionMode==="dag"&&this.hasCycles(e.connections))throw new Error("Topology contains cycles \u2014 DAG mode requires acyclic connections");switch(e.executionMode){case"sequential":await this.runSequential(t,e);break;case"parallel":await this.runParallel(t);break;case"dag":await this.runDAG(t,e);break;case"loop":await this.runLoop(t,e);break}this.finalize()}finalize(){this.running&&(this.running=!1,this.cliProvider.dispose(),this.config.onSwarmCompleted?.({swarmId:this.config.swarm.id,results:new Map(Array.from(this.instances.entries()).map(([e,t])=>[e,t.result]))}))}stop(){this.running=!1;for(let e of this.instances.values())e.status==="running"&&(e.sessionAbort.abort(),e.status="completed",e.completedAt=new Date().toISOString());this.cliProvider.killAll(),this.cliProvider.dispose();for(let[e,t]of this.escalationResolvers)t("ORCHESTRATOR_STOPPED"),this.escalationResolvers.delete(e)}respondToEscalation(e,t){let r=this.escalations.get(e);if(!r)return;r.status="responded",r.response=t,r.resolvedAt=new Date().toISOString();let s=this.escalationResolvers.get(e);s&&(s(t),this.escalationResolvers.delete(e))}getInstances(){return Array.from(this.instances.values())}getEscalations(){return Array.from(this.escalations.values())}getCLIProvider(){return this.cliProvider}async runSequential(e,t){let r=t?this.orderByConnections(e,t.connections):e,s;for(let n of r){if(!this.running)break;let i=s?`
61
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),c=e.terminalCount??t.terminalCount;for(let l=0;l<c;l++){let d=e.terminals[l],u=d?.id||Bt();o.run(u,t.workspaceId,e.id,d?.label||`Terminal ${l+1}`,d?.directory||"",d?.command||"",JSON.stringify(d?.env||{}),l,JSON.stringify(d?.commandSequence||[]),d?.runOnce?1:0,d?.commandRunOnce?1:0,d?.startDelay||0,d?.startWaitFor||"",d?.startRunOnce?1:0,d?.closeAfterCommand?1:0,d?.closeDelay??1e3,d?.closeWaitFor||"",d?.color||"default")}}return this.get(e.id)}delete(e){return this.db.prepare("DELETE FROM terminal_configs WHERE areaId = ?").run(e),this.db.prepare("DELETE FROM area_state WHERE areaId = ?").run(e),this.db.prepare("DELETE FROM areas WHERE id = ?").run(e).changes>0}duplicate(e,t){let r=this.get(e);if(!r)throw new Error(`Area not found: ${e}`);return this.create({workspaceId:r.workspaceId,name:t,color:r.color,directory:r.directory,useWorktree:r.useWorktree,worktreeBranch:r.worktreeBranch,defaultCommand:r.defaultCommand,terminalCount:r.terminalCount,terminals:r.terminals.map(s=>({label:s.label,directory:s.directory,command:s.command,env:s.env,commandSequence:s.commandSequence,runOnce:s.runOnce,commandRunOnce:s.commandRunOnce,startDelay:s.startDelay,startWaitFor:s.startWaitFor,startRunOnce:s.startRunOnce,closeAfterCommand:s.closeAfterCommand,closeDelay:s.closeDelay,closeWaitFor:s.closeWaitFor,color:s.color})),layout:r.layout})}getDefaultArea(e){let r=this.db.prepare("SELECT * FROM areas WHERE workspaceId = ? AND isDefault = 1 LIMIT 1").get(e);return r?this.hydrateArea(r):null}resolveForLaunch(e,t){let r=e.directory||t;return e.terminals.filter(n=>!(n.runOnce&&this.db.prepare("SELECT hasLaunched FROM terminal_configs WHERE id = ?").get(n.id)?.hasLaunched===1)).map((n,i)=>{let o=n.directory||".",c=o.startsWith("/")?o:ea(r,o),u=this.db.prepare("SELECT hasLaunched FROM terminal_configs WHERE id = ?").get(n.id)?.hasLaunched===1,p=n.commandRunOnce&&u,m=p?e.defaultCommand:n.command||e.defaultCommand,h=p?void 0:n.commandSequence;return{id:n.id,label:n.label||`Terminal ${i+1}`,cwd:c,command:m,commandSequence:h,env:{SWARM_WORKSPACE_ID:e.workspaceId,SWARM_WORKSPACE_NAME:"",SWARM_AREA_ID:e.id,SWARM_AREA_NAME:e.name,SWARM_TERMINAL_ID:n.id,SWARM_TERMINAL_LABEL:n.label,SWARM_TERMINAL_INDEX:String(i+1),SWARM_TERMINAL_COUNT:String(e.terminalCount),SWARM_MODE:"web",...n.env},position:i,startDelay:n.startDelay||0,startWaitFor:n.startWaitFor||"",startRunOnce:n.startRunOnce||!1,hasLaunched:u,closeAfterCommand:n.closeAfterCommand||!1,closeDelay:n.closeDelay??1e3,closeWaitFor:n.closeWaitFor||""}})}setRunning(e,t){this.db.prepare(`UPDATE area_state SET isRunning = ?, lastLaunchedAt = ?
62
+ WHERE areaId = ?`).run(t?1:0,t?new Date().toISOString():null,e)}isRunning(e){return this.db.prepare("SELECT isRunning FROM area_state WHERE areaId = ?").get(e)?.isRunning===1}setTerminalColor(e,t,r){this.db.prepare("UPDATE terminal_configs SET color = ? WHERE id = ? AND areaId = ?").run(r||"default",e,t)}markTerminalLaunched(e){this.db.prepare("UPDATE terminal_configs SET hasLaunched = 1 WHERE id = ?").run(e)}resetTerminalLaunched(e){this.db.prepare("UPDATE terminal_configs SET hasLaunched = 0, completedSteps = '[]' WHERE id = ?").run(e)}resetAllTerminals(e){this.db.prepare("UPDATE terminal_configs SET hasLaunched = 0, completedSteps = '[]' WHERE areaId = ?").run(e)}markStepCompleted(e,t){let s=this.db.prepare("SELECT completedSteps FROM terminal_configs WHERE id = ?").get(e),n=JSON.parse(s?.completedSteps||"[]");n.includes(t)||(n.push(t),this.db.prepare("UPDATE terminal_configs SET completedSteps = ? WHERE id = ?").run(JSON.stringify(n),e))}getCompletedSteps(e){let r=this.db.prepare("SELECT completedSteps FROM terminal_configs WHERE id = ?").get(e);return JSON.parse(r?.completedSteps||"[]")}saveRuntimeState(e,t){this.db.prepare("INSERT OR REPLACE INTO area_runtime_state (areaId, data, updatedAt) VALUES (?, ?, ?)").run(e,JSON.stringify(t),new Date().toISOString())}getRuntimeState(e){let r=this.db.prepare("SELECT data FROM area_runtime_state WHERE areaId = ?").get(e);return r?JSON.parse(r.data):null}clearRuntimeState(e){this.db.prepare("DELETE FROM area_runtime_state WHERE areaId = ?").run(e)}hydrateArea(e){let r=this.db.prepare("SELECT * FROM terminal_configs WHERE areaId = ? ORDER BY position ASC").all(e.id),s,n=e.trigger;if(n)try{s=JSON.parse(n)}catch{s=void 0}return{id:e.id,workspaceId:e.workspaceId,name:e.name,color:e.color,directory:e.directory,useWorktree:e.useWorktree===1,worktreeBranch:e.worktreeBranch||void 0,worktreePath:e.worktreePath||void 0,defaultCommand:e.defaultCommand,terminalCount:e.terminalCount,layout:e.layout,order:e.order,isDefault:e.isDefault===1,templateId:e.templateId||void 0,ignoreOnLaunchAll:e.ignoreOnLaunchAll===1,trigger:s,createdAt:e.createdAt,updatedAt:e.updatedAt,terminals:r.map(i=>({id:i.id,label:i.label,directory:i.directory,command:i.command,env:JSON.parse(i.env),commandSequence:JSON.parse(i.commandSequence||"[]"),runOnce:i.runOnce===1,commandRunOnce:i.commandRunOnce===1,startDelay:i.startDelay||0,startWaitFor:i.startWaitFor||"",startRunOnce:i.startRunOnce===1,closeAfterCommand:i.closeAfterCommand===1,closeDelay:i.closeDelay??1e3,closeWaitFor:i.closeWaitFor||"",color:i.color||"default"}))}}};import{randomUUID as qt}from"node:crypto";import{mkdirSync as de,writeFileSync as pa}from"node:fs";import{join as K}from"node:path";import{randomUUID as ta}from"node:crypto";import{mkdirSync as ra,writeFileSync as Br}from"node:fs";import{join as Wt}from"node:path";var Ue=class{registry;constructor(e){this.registry=e}async boot(e,t,r,s,n){let i=`swarm-${t.id}-agent-${e.id}-${ta().slice(0,8)}`,o=this.getCommandForCli(e.cli,t.mission,e.autoApprove||t.autoApprove),c=e.name.toLowerCase().replace(/\s+/g,"-"),l=Wt(t.directory,".swarm","agents",c);ra(l,{recursive:!0});let d=this.generateClaudeMd(t,e);if(Br(Wt(l,"CLAUDE.md"),d),e.mcps&&e.mcps.length>0){let h={mcpServers:Object.fromEntries(e.mcps.map(f=>[f,{command:f}]))};Br(Wt(l,".mcp.json"),JSON.stringify(h,null,2))}let u,p,m=t.directory;if(t.useWorktrees&&n&&n.isGitRepo(t.directory))try{let h=n.createForAgent(t.directory,t.id,e.name);u=h.path,p=h.branch,m=h.path}catch(h){console.warn(`[WorktreeManager] Failed to create worktree for agent ${e.name}:`,h)}return await r.open({id:i,cwd:m,command:o,env:s,cols:120,rows:30}),{terminalId:i,worktreePath:u,worktreeBranch:p}}generateClaudeMd(e,t){let r=[`# Agent: ${t.name}`,`## Role: ${t.role}`,"","## Mission",e.mission,"","## Working Directory",e.directory,""];return t.systemPrompt&&r.push("## System Prompt",t.systemPrompt,""),t.workScope&&t.workScope.length>0&&r.push("## Work Scope",...t.workScope.map(s=>`- ${s}`),""),t.role==="coordinator"&&r.push("## Coordinator Instructions",`You are the coordinator of a swarm of ${e.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",...e.agents.map(s=>`- ${s.name} (${s.role}): ${s.systemPrompt||"No specific prompt"}`),""),r.join(`
63
+ `)}getCommandForCli(e,t,r){let s=this.registry.get(e);return s?s.buildCommand({mission:t,cwd:"",autoApprove:r}):e}};import{randomUUID as ia}from"node:crypto";import{query as oa}from"@anthropic-ai/claude-agent-sdk";import{randomUUID as sa}from"node:crypto";import{resolve as $t}from"node:path";import{spawn as na}from"node:child_process";import{query as aa}from"@anthropic-ai/claude-agent-sdk";var Wr=1024*1024,$r=5e4,Hr=50,qr=new Set(["PATH","HOME","USER","SHELL","LD_PRELOAD","LD_LIBRARY_PATH","DYLD_INSERT_LIBRARIES","DYLD_LIBRARY_PATH","NODE_OPTIONS","ELECTRON_RUN_AS_NODE","NODE_PATH"]),Fe=class{sessions=new Map;agentSessionCount=new Map;maxCLIsPerAgent;allowedBasePaths;claudeBinaryPath;onEvent;cleanupTimer=null;constructor(e){this.maxCLIsPerAgent=e.maxCLIsPerAgent??5,this.allowedBasePaths=e.allowedBasePaths??[process.cwd()],this.claudeBinaryPath=e.claudeBinaryPath??"claude",this.onEvent=e.onEvent,this.cleanupTimer=setInterval(()=>this.cleanup(3e5),6e4)}dispose(){this.cleanupTimer&&(clearInterval(this.cleanupTimer),this.cleanupTimer=null),this.killAll()}async spawn(e,t){this.validateConfig(t);let r=this.agentSessionCount.get(e)??0;if(r>=this.maxCLIsPerAgent)throw new Error(`Agent ${e} has reached the maximum of ${this.maxCLIsPerAgent} concurrent CLIs`);if([...this.sessions.values()].filter(o=>o.status==="running").length>=Hr)throw new Error(`Global CLI session limit (${Hr}) reached`);let n=sa(),i={id:n,agentId:e,config:t,status:"running",outputBuffer:"",startedAt:new Date().toISOString()};return this.sessions.set(n,i),this.agentSessionCount.set(e,r+1),t.cli==="claude"?this.spawnClaudeSDK(i):this.spawnCLIProcess(i),n}validateConfig(e){if(!e.prompt||e.prompt.length===0)throw new Error("Prompt is required");if(e.prompt.length>$r)throw new Error(`Prompt too long (max ${$r} chars)`);if(e.prompt.includes("\0"))throw new Error("Prompt contains invalid characters");if(e.workDir){let t=$t(e.workDir);if(!this.allowedBasePaths.some(s=>t===$t(s)||t.startsWith($t(s)+"/")))throw new Error(`Working directory "${e.workDir}" is outside allowed paths`)}if(e.env){for(let t of Object.keys(e.env))if(qr.has(t.toUpperCase()))throw new Error(`Environment variable "${t}" cannot be overridden`)}if(e.timeout!==void 0&&(e.timeout<=0||e.timeout>3600))throw new Error("Timeout must be between 1 and 3600 seconds");if(e.maxBudget!==void 0&&(e.maxBudget<=0||e.maxBudget>100))throw new Error("Max budget must be between $0.01 and $100")}sanitizeEnv(e){let t={...process.env};if(!e)return t;for(let[r,s]of Object.entries(e))qr.has(r.toUpperCase())||(t[r]=s);return t}async spawnClaudeSDK(e){let t=e.config,r=new AbortController;e.sdkAbort=r;let s;t.timeout&&(s=setTimeout(()=>{r.abort(),this.completeSession(e.id,"timeout","CLI timed out")},t.timeout*1e3));try{let n=aa({prompt:t.prompt,options:{model:t.model||"claude-sonnet-4-6",pathToClaudeCodeExecutable:this.claudeBinaryPath,cwd:t.workDir||process.cwd(),permissionMode:t.autoApprove?"bypassPermissions":"default",allowDangerouslySkipPermissions:t.autoApprove||void 0,maxBudgetUsd:t.maxBudget,abortController:r,env:this.sanitizeEnv(t.env)}}),i="",o;for await(let c of n){if(r.signal.aborted)break;if(c.type==="assistant"){let l=this.extractAssistantText(c);l&&(this.appendToBuffer(e,l),this.onEvent({type:"output",sessionId:e.id,agentId:e.agentId,data:l}))}if(c.type==="result"){let l=c;i=l.result??"",o=l.total_cost_usd}}s&&clearTimeout(s),r.signal.aborted||this.completeSession(e.id,"completed",void 0,i||e.outputBuffer,void 0,o)}catch(n){s&&clearTimeout(s);let i=n instanceof Error?n.message:String(n);this.completeSession(e.id,"error",i)}}extractAssistantText(e){if(e.type!=="assistant")return"";let r=e.message;return!r?.content||!Array.isArray(r.content)?"":r.content.filter(s=>s.type==="text").map(s=>typeof s.text=="string"?s.text:"").join("")}appendToBuffer(e,t){e.outputBuffer+=t,e.outputBuffer.length>Wr&&(e.outputBuffer=e.outputBuffer.slice(-Wr/2))}spawnCLIProcess(e){let t=e.config,{cmd:r,args:s}=this.buildCLICommand(t),n;try{let i=na(r,s,{cwd:t.workDir||process.cwd(),env:this.sanitizeEnv(t.env),stdio:["pipe","pipe","pipe"]});e.process=i,t.timeout&&(n=setTimeout(()=>{i.kill("SIGTERM"),this.completeSession(e.id,"timeout","CLI timed out")},t.timeout*1e3)),i.stdout?.on("data",o=>{let c=o.toString();this.appendToBuffer(e,c),this.onEvent({type:"output",sessionId:e.id,agentId:e.agentId,data:c})}),i.stderr?.on("data",o=>{this.appendToBuffer(e,o.toString())}),i.on("close",o=>{n&&clearTimeout(n),o===0?this.completeSession(e.id,"completed",void 0,e.outputBuffer,o):this.completeSession(e.id,"error",`Process exited with code ${o}`,e.outputBuffer,o??void 0)}),i.on("error",o=>{n&&clearTimeout(n),this.completeSession(e.id,"error",o.message)})}catch(i){let o=i instanceof Error?i.message:String(i);this.completeSession(e.id,"error",o)}}buildCLICommand(e){switch(e.cli){case"codex":{let t=["exec",e.prompt];return e.autoApprove&&t.push("--dangerously-bypass-approvals-and-sandbox"),t.push("--json"),e.model&&t.push("-m",e.model),{cmd:"codex",args:t}}case"gemini":{let t=["-p",e.prompt];return e.autoApprove&&t.push("--yolo"),t.push("--output-format",e.outputFormat||"json"),e.model&&t.push("-m",e.model),{cmd:"gemini",args:t}}case"opencode":return{cmd:"opencode",args:[e.prompt]};case"cursor":return{cmd:"cursor",args:["--prompt",e.prompt]};default:return{cmd:e.cli,args:[e.prompt]}}}completeSession(e,t,r,s,n,i){let o=this.sessions.get(e);if(!o)return;o.status=t;let c={id:e,cli:o.config.cli,status:t,output:s||o.outputBuffer,exitCode:n,startedAt:o.startedAt,completedAt:new Date().toISOString(),error:r,cost:i};o.result=c;let l=this.agentSessionCount.get(o.agentId)??1;this.agentSessionCount.set(o.agentId,Math.max(0,l-1)),this.onEvent({type:t==="completed"?"completed":"error",sessionId:e,agentId:o.agentId,data:r||s||"",result:c})}kill(e){let t=this.sessions.get(e);t&&(t.sdkAbort&&t.sdkAbort.abort(),t.process&&t.process.kill("SIGTERM"),this.completeSession(e,"error","Killed by user"))}killAllForAgent(e){for(let[,t]of this.sessions)t.agentId===e&&t.status==="running"&&this.kill(t.id)}killAll(){for(let[,e]of this.sessions)e.status==="running"&&this.kill(e.id)}getSessionsForAgent(e){let t=[];for(let r of this.sessions.values())r.agentId===e&&t.push(r);return t}getSession(e){return this.sessions.get(e)}getActiveCount(e){return this.agentSessionCount.get(e)??0}cleanup(e=36e5){let t=Date.now();for(let[r,s]of this.sessions)s.status!=="running"&&s.result?.completedAt&&t-new Date(s.result.completedAt).getTime()>e&&this.sessions.delete(r)}};var Be=class{instances=new Map;cliProvider;config;escalations=new Map;escalationResolvers=new Map;running=!1;autoCaptureCount=new Map;constructor(e){this.config=e,this.cliProvider=new Fe({maxCLIsPerAgent:5,allowedBasePaths:[e.swarm.directory],claudeBinaryPath:e.claudeBinaryPath,onEvent:t=>{t.type==="output"&&this.config.onAgentOutput?.({swarmId:this.config.swarm.id,agentId:t.agentId,agentName:this.getAgentName(t.agentId),type:"tool_result",content:t.data}),t.type==="completed"&&t.result&&this.config.onCLICompleted?.({swarmId:this.config.swarm.id,agentId:t.agentId,sessionId:t.sessionId,result:t.result})}})}async start(){this.running=!0;let e=this.config.topology,t=this.config.swarm.agents;if(!e||t.length===0){await this.runParallel(t),this.finalize();return}if(e.executionMode==="dag"&&this.hasCycles(e.connections))throw new Error("Topology contains cycles \u2014 DAG mode requires acyclic connections");switch(e.executionMode){case"sequential":await this.runSequential(t,e);break;case"parallel":await this.runParallel(t);break;case"dag":await this.runDAG(t,e);break;case"loop":await this.runLoop(t,e);break}this.finalize()}finalize(){this.running&&(this.running=!1,this.cliProvider.dispose(),this.config.onSwarmCompleted?.({swarmId:this.config.swarm.id,results:new Map(Array.from(this.instances.entries()).map(([e,t])=>[e,t.result]))}))}stop(){this.running=!1;for(let e of this.instances.values())e.status==="running"&&(e.sessionAbort.abort(),e.status="completed",e.completedAt=new Date().toISOString());this.cliProvider.killAll(),this.cliProvider.dispose();for(let[e,t]of this.escalationResolvers)t("ORCHESTRATOR_STOPPED"),this.escalationResolvers.delete(e)}respondToEscalation(e,t){let r=this.escalations.get(e);if(!r)return;r.status="responded",r.response=t,r.resolvedAt=new Date().toISOString();let s=this.escalationResolvers.get(e);s&&(s(t),this.escalationResolvers.delete(e))}getInstances(){return Array.from(this.instances.values())}getEscalations(){return Array.from(this.escalations.values())}getCLIProvider(){return this.cliProvider}async runSequential(e,t){let r=t?this.orderByConnections(e,t.connections):e,s;for(let n of r){if(!this.running)break;let i=s?`
64
64
 
65
65
  Context from previous agent:
66
66
  ${s}`:"";s=await this.runAgent(n,i)}}async runParallel(e){let t=e.map(r=>this.runAgent(r));await Promise.allSettled(t)}async runDAG(e,t){let r=new Map(e.map(c=>[c.id,c])),s=new Set,n=new Map,i=new Map;for(let c of e)i.set(c.id,new Set);for(let c of t.connections)if(c.type==="trigger"||c.type==="pipe"){let l=i.get(c.to);l&&l.add(c.from)}let o=()=>{for(let[c,l]of i){if(s.has(c)||n.has(c)||![...l].every(f=>s.has(f)))continue;let u=r.get(c);if(!u)continue;let p=[];for(let f of t.connections)if(f.to===c&&f.type==="pipe"&&s.has(f.from)){let g=this.instances.get(f.from);if(g?.result){let w=r.get(f.from);p.push(`Result from ${w?.name??f.from}:
@@ -71,24 +71,24 @@ ${p.join(`
71
71
 
72
72
  `)}`:"",h=this.runAgent(u,m).then(f=>(s.add(c),n.delete(c),this.running&&o(),f)).catch(()=>{s.add(c),n.delete(c),this.running&&o()});n.set(c,h)}};for(o();n.size>0&&this.running;){let c=[...n.values()];if(c.length===0)break;await Promise.race(c)}}async runLoop(e,t){let r=t.loopMaxIterations??10,s=0,n=!0;for(;n&&s<r&&this.running;){s++;for(let i of e){if(!this.running)break;let o=`
73
73
 
74
- Loop iteration: ${s}/${r}`,c=await this.runAgent(i,o);if(c&&this.detectLoopCompletion(c)){n=!1;break}}for(let i of t.connections)if(i.type==="feedback"&&i.condition&&this.instances.get(i.from)?.result?.toLowerCase().includes(i.condition.toLowerCase())){n=!1;break}}}async runAgent(e,t=""){let r=new AbortController,s={id:e.id,swarmId:this.config.swarm.id,agent:e,status:"running",sessionAbort:r,output:[],cliSessionIds:[],startedAt:new Date().toISOString()};this.instances.set(e.id,s);let n=this.buildAgentPrompt(e,t);try{let i=e.autoApprove||this.config.swarm.autoApprove,o=ia({prompt:n,options:{model:"claude-sonnet-4-6",pathToClaudeCodeExecutable:this.config.claudeBinaryPath||"claude",cwd:e.worktreePath||this.config.swarm.directory,permissionMode:i?"bypassPermissions":"default",allowDangerouslySkipPermissions:i||void 0,abortController:r,env:this.config.env}}),c="";for await(let l of o){if(r.signal.aborted)break;if(this.handleSDKMessage(s,l),l.type==="result"){let d=l;d.subtype==="success"&&d.result&&(c=d.result)}}s.status="completed",s.result=c||s.output.join(`
74
+ Loop iteration: ${s}/${r}`,c=await this.runAgent(i,o);if(c&&this.detectLoopCompletion(c)){n=!1;break}}for(let i of t.connections)if(i.type==="feedback"&&i.condition&&this.instances.get(i.from)?.result?.toLowerCase().includes(i.condition.toLowerCase())){n=!1;break}}}async runAgent(e,t=""){let r=new AbortController,s={id:e.id,swarmId:this.config.swarm.id,agent:e,status:"running",sessionAbort:r,output:[],cliSessionIds:[],startedAt:new Date().toISOString()};this.instances.set(e.id,s);let n=this.buildAgentPrompt(e,t);try{let i=e.autoApprove||this.config.swarm.autoApprove,o=oa({prompt:n,options:{model:"claude-sonnet-4-6",pathToClaudeCodeExecutable:this.config.claudeBinaryPath||"claude",cwd:e.worktreePath||this.config.swarm.directory,permissionMode:i?"bypassPermissions":"default",allowDangerouslySkipPermissions:i||void 0,abortController:r,env:this.config.env}}),c="";for await(let l of o){if(r.signal.aborted)break;if(this.handleSDKMessage(s,l),l.type==="result"){let d=l;d.subtype==="success"&&d.result&&(c=d.result)}}s.status="completed",s.result=c||s.output.join(`
75
75
  `),s.completedAt=new Date().toISOString();try{this.autoCapture(s.result,e.id,e.name,this.config.swarm.id)}catch{}return this.config.onAgentCompleted?.({swarmId:this.config.swarm.id,agentId:e.id,agentName:e.name,result:s.result}),s.result}catch(i){let o=i instanceof Error?i.message:String(i);s.status="error",s.error=o,s.completedAt=new Date().toISOString(),await this.escalate(e,"critical",`Agent error: ${o}`,"Agent execution failed"),this.config.onAgentCompleted?.({swarmId:this.config.swarm.id,agentId:e.id,agentName:e.name,error:o});return}}handleSDKMessage(e,t){let r=e.agent;switch(t.type){case"assistant":{let s=this.extractAssistantText(t);if(s&&(e.output.push(s),this.config.onAgentOutput?.({swarmId:this.config.swarm.id,agentId:r.id,agentName:r.name,type:"text",content:s}),s.length>50))try{this.autoCapture(s,r.id,r.name,this.config.swarm.id)}catch{}break}case"result":{let s=t;s.is_error&&s.errors&&this.config.onAgentOutput?.({swarmId:this.config.swarm.id,agentId:r.id,agentName:r.name,type:"error",content:s.errors.join(`
76
76
  `)});break}}}extractAssistantText(e){if(e.type!=="assistant")return"";let t=e.message;return!t?.content||!Array.isArray(t.content)?"":t.content.filter(r=>r.type==="text"&&typeof r.text=="string").map(r=>r.text).join("")}buildAgentPrompt(e,t){let r=this.config.swarm,s=[];if(s.push(`# Agent: ${e.name}`),s.push(`## Role: ${e.role}`),s.push(""),s.push("## Mission"),s.push(r.mission),s.push(""),e.systemPrompt&&(s.push("## Instructions"),s.push(e.systemPrompt),s.push("")),e.workScope&&e.workScope.length>0&&(s.push("## Work Scope"),s.push(...e.workScope.map(n=>`- ${n}`)),s.push("")),s.push("## Autonomy Rules"),s.push("- Execute tasks autonomously without asking questions"),s.push("- If uncertain, choose the safest option and document your decision"),s.push('- If you encounter an impossible blocker, include "===NEEDS_HUMAN===" in your output'),s.push("- When done, ensure all changes are saved and tests pass"),s.push(""),t&&(s.push("## Additional Context"),s.push(t),s.push("")),r.agents.length>1){s.push("## Other Agents in Swarm");for(let n of r.agents)n.id!==e.id&&s.push(`- ${n.name} (${n.role}): ${n.systemPrompt||"No specific prompt"}`);s.push("")}if(this.config.knowledgeManager&&r.id)try{let n=this.config.knowledgeManager.getAllForSwarm(r.id,10);if(n&&n.length>0){s.push("## Shared Knowledge Base"),s.push(`The following insights have been discovered by your teammates:
77
77
  `);for(let i of n){let o=i.isVerified?" \u2713":"",c=`[${i.confidence}%${o}]`,l=i.agentName?` (by ${i.agentName})`:"",d=i.content.length>200?i.content.slice(0,200)+"...":i.content;s.push(`- **[${i.category}] ${i.title}** ${c}${l}: ${d}`)}s.push(`
78
78
  You can document your own discoveries for teammates to benefit from.`),s.push("")}}catch{}return s.join(`
79
- `)}async escalate(e,t,r,s,n){let i={id:aa(),swarmId:this.config.swarm.id,agentId:e.id,agentName:e.name,level:t,reason:r,context:s,suggestedAction:n?.suggestedAction,status:"pending",timeout:n?.timeout,autoResolve:n?.autoResolve,createdAt:new Date().toISOString()};if(this.escalations.set(i.id,i),this.config.onEscalation?.({swarmId:this.config.swarm.id,escalation:i}),n?.autoResolve&&setTimeout(()=>{if(i.status==="pending"){i.status="auto-resolved",i.response=n.autoResolve.action,i.resolvedAt=new Date().toISOString();let o=this.escalationResolvers.get(i.id);o&&(o(n.autoResolve.action),this.escalationResolvers.delete(i.id))}},n.autoResolve.afterMs),n?.timeout&&!n?.autoResolve&&setTimeout(()=>{if(i.status==="pending"){i.status="expired",i.resolvedAt=new Date().toISOString();let o=this.escalationResolvers.get(i.id);o&&(o("ESCALATION_EXPIRED"),this.escalationResolvers.delete(i.id))}},n.timeout),!n?.timeout&&!n?.autoResolve&&setTimeout(()=>{if(this.escalationResolvers.has(i.id)){let o=this.escalationResolvers.get(i.id);o&&o("ESCALATION_FAILSAFE_TIMEOUT"),this.escalationResolvers.delete(i.id),i.status==="pending"&&(i.status="expired",i.resolvedAt=new Date().toISOString())}},36e5),n?.waitForResponse)return new Promise(o=>{this.escalationResolvers.set(i.id,o)})}autoCapture(e,t,r,s){if(!this.config.knowledgeManager||!e)return;let n=this.autoCaptureCount.get(t)??0;if(n>=10)return;let i=[{regex:/(?:found|discovered|located|identified)\s+(?:file|module|class|function|component)\s+[`"']?([^\s`"'\n,]+)/gi,category:"file_path",titlePrefix:"Found"},{regex:/(?:error|bug|issue|exception|failure)[:\s]+(.{10,100})/gi,category:"error",titlePrefix:"Error"},{regex:/(?:fixed|resolved|solved|patched|corrected)[:\s]+(.{10,100})/gi,category:"solution",titlePrefix:"Fixed"},{regex:/(?:pattern|convention|standard|approach)[:\s]+(.{10,100})/gi,category:"pattern",titlePrefix:"Pattern"},{regex:/(?:installed|added|configured|setup)\s+(?:package|dependency|module)\s+[`"']?([^\s`"'\n,]+)/gi,category:"config",titlePrefix:"Configured"},{regex:/(?:root cause|caused by|because of)[:\s]+(.{10,100})/gi,category:"note",titlePrefix:"Root cause"}],o=new Set,c=n;for(let{regex:l,category:d,titlePrefix:u}of i){l.lastIndex=0;let p;for(;(p=l.exec(e))!==null&&!(c>=10);){let m=p[1]?.trim()||p[0].trim();if(!(m.length<5||o.has(m))){o.add(m);try{this.config.knowledgeManager.addEntry({swarmId:s,agentId:t,category:d,title:`${u}: ${m.slice(0,80)}`,content:p[0].trim(),confidence:35,metadata:{source:"auto-capture",agentName:r},tags:["auto-captured"]}),c++}catch{}}}if(c>=10)break}this.autoCaptureCount.set(t,c)}getAgentName(e){return this.instances.get(e)?.agent.name??e}orderByConnections(e,t){let r=new Map(e.map(c=>[c.id,c])),s=new Map,n=new Map;for(let c of e)s.set(c.id,0),n.set(c.id,[]);for(let c of t){let l=s.get(c.to)??0;s.set(c.to,l+1);let d=n.get(c.from)??[];d.push(c.to),n.set(c.from,d)}let i=[];for(let[c,l]of s)l===0&&i.push(c);let o=[];for(;i.length>0;){let c=i.shift(),l=r.get(c);l&&o.push(l);for(let d of n.get(c)??[]){let u=(s.get(d)??1)-1;s.set(d,u),u===0&&i.push(d)}}for(let c of e)o.find(l=>l.id===c.id)||o.push(c);return o}detectLoopCompletion(e){let t=e.toLowerCase();return t.includes("loop complete")||t.includes("iteration done")||t.includes("no more iterations needed")||t.includes("===loop_complete===")}hasCycles(e){let t=new Map;for(let i of e)if(i.type==="pipe"||i.type==="trigger"){let o=t.get(i.from)??[];o.push(i.to),t.set(i.from,o)}let r=new Set,s=new Set,n=i=>{if(s.has(i))return!0;if(r.has(i))return!1;r.add(i),s.add(i);for(let o of t.get(i)??[])if(n(o))return!0;return s.delete(i),!1};for(let i of t.keys())if(n(i))return!0;return!1}};var We=class{running=!1;coordinatorId=null;swarmId=null;swarmManager=null;terminalManager=null;taskManager=null;broadcast=null;agents=new Map;terminalToAgent=new Map;coordinatorTerminalIds=[];outputBuffers=new Map;flushTimer=null;start(e,t,r,s,n,i){this.coordinatorId=e,this.swarmId=t,this.swarmManager=r,this.terminalManager=s,this.broadcast=n,this.taskManager=i??null,this.running=!0,this.refreshAgentRegistry(),this.flushTimer=setInterval(()=>this.flushAllBuffers(),3e3)}stop(){this.running=!1,this.coordinatorId=null,this.swarmId=null,this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),this.agents.clear(),this.terminalToAgent.clear(),this.coordinatorTerminalIds=[],this.outputBuffers.clear()}get isRunning(){return this.running}get activeCoordinatorId(){return this.coordinatorId}onTerminalOutput(e,t){if(!this.running)return;if(this.coordinatorTerminalIds.includes(e)){this.parseCoordinatorOutput(t);return}let r=this.terminalToAgent.get(e);!r||!this.agents.get(r)||(this.bufferAgentOutput(r,t),this.detectAgentStatus(r,t))}refreshAgentRegistry(){if(!this.swarmManager||!this.swarmId)return;let e=this.swarmManager.get(this.swarmId);if(e){this.agents.clear(),this.terminalToAgent.clear(),this.coordinatorTerminalIds=[];for(let t of e.agents){this.agents.set(t.id,{id:t.id,name:t.name,role:t.role,terminalIds:[...t.terminalIds]});for(let r of t.terminalIds)t.id===this.coordinatorId?this.coordinatorTerminalIds.push(r):this.terminalToAgent.set(r,t.id)}}}registerAgentTerminal(e,t,r){let s=this.agents.get(e)??{id:e,name:r.name,role:r.role,terminalIds:[]};s.terminalIds.push(t),this.agents.set(e,s),e===this.coordinatorId?this.coordinatorTerminalIds.push(t):this.terminalToAgent.set(t,e)}MAX_BUFFER_SIZE=5e3;bufferAgentOutput(e,t){let s=(this.outputBuffers.get(e)??"")+t,n=s.length>this.MAX_BUFFER_SIZE?s.slice(s.length-this.MAX_BUFFER_SIZE):s;this.outputBuffers.set(e,n),(t.includes(`
80
- `)||t.includes("\r"))&&this.flushBuffer(e)}flushBuffer(e){let t=this.outputBuffers.get(e);if(!t||t.trim().length===0){this.outputBuffers.delete(e);return}let r=this.agents.get(e);if(!r){this.outputBuffers.delete(e);return}let s=this.truncateOutput(t.trim()),n=`[${r.name} (${r.role})]: ${s}`;this.writeToCoordinator(n),this.outputBuffers.delete(e)}flushAllBuffers(){for(let e of this.outputBuffers.keys())this.flushBuffer(e)}truncateOutput(e,t=500){return e.length<=t?e:e.slice(0,t)+"..."}writeToCoordinator(e){if(!(!this.terminalManager||this.coordinatorTerminalIds.length===0))for(let t of this.coordinatorTerminalIds)this.terminalManager.write(t,e+"\r")}coordinatorOutputBuffer="";parseCoordinatorOutput(e){this.coordinatorOutputBuffer+=e;let t=this.coordinatorOutputBuffer.split(/\r?\n/);this.coordinatorOutputBuffer=t.pop()??"";for(let r of t){let s=r.trim();if(!s)continue;this.detectSwarmCompletion(s);let n=s.match(/^\/send\s+@(\S+)\s+(.+)$/);if(n){this.handleSendCommand(n[1],n[2]);continue}let i=s.match(/^\/task\s+create\s+"([^"]+)"\s+@(\S+)$/);if(i){this.handleTaskCreate(i[1],i[2]);continue}let o=s.match(/^\/task\s+done\s+(\S+)$/);if(o){this.handleTaskMove(o[1],"done");continue}let c=s.match(/^\/task\s+block\s+(\S+)$/);if(c){this.handleTaskMove(c[1],"blocked");continue}let l=s.match(/^\/escalate\s+(.+)$/);if(l){this.handleEscalate(l[1]);continue}}}handleSendCommand(e,t){let r=this.findAgentByName(e);if(r&&this.terminalManager)for(let s of r.terminalIds)this.terminalManager.write(s,t+"\r")}handleTaskCreate(e,t){if(!this.taskManager||!this.swarmId||!this.swarmManager)return;let r=this.findAgentByName(t),s=this.swarmManager.get(this.swarmId);s&&this.taskManager.create({swarmId:this.swarmId,workspaceId:s.workspaceId,title:e,description:"",assignedAgentId:r?.id})}handleTaskMove(e,t){if(this.taskManager)try{this.taskManager.move(e,t)}catch{}}handleEscalate(e){if(!this.broadcast||!this.swarmId||!this.coordinatorId)return;let t=this.agents.get(this.coordinatorId);this.broadcast(`swarm.escalation.${this.swarmId}`,{swarmId:this.swarmId,agentId:this.coordinatorId,agentName:t?.name??"Coordinator",message:e,requiresResponse:!0})}detectAgentStatus(e,t){if(!this.broadcast||!this.swarmId)return;let r=t.toLowerCase(),s=null;r.includes("task completed")||r.includes("task done")||r.includes("finished")||r.includes("all tests passing")||r.includes("done")?s="done":r.includes("error:")||r.includes("fatal:")||r.includes("exception")?s="error":(r.includes("waiting for")||r.includes("blocked by"))&&(s="waiting"),s&&this.broadcast(`swarm.agent.status.${this.swarmId}`,{swarmId:this.swarmId,agentId:e,status:s}),s==="done"&&this.handleAgentTaskCompletion(e)}handleAgentTaskCompletion(e){if(!this.taskManager||!this.swarmId)return;let r=this.taskManager.list({swarmId:this.swarmId}).find(n=>n.assignedAgentId===e&&n.status==="running");if(!r)return;try{this.taskManager.move(r.id,"done")}catch{return}let s=this.findReviewerAgent();if(s){let i=this.agents.get(e)?.name??e;this.writeToCoordinator(`[SYSTEM]: Task "${r.title}" (${r.id}) assigned to ${i} has been marked as done. Reviewer agent "${s.name}" is available \u2014 consider using /send @${s.name} to assign a review.`)}}findReviewerAgent(){for(let e of this.agents.values())if(e.id!==this.coordinatorId&&e.role==="reviewer")return e}detectSwarmCompletion(e){if(!this.swarmId||!this.swarmManager)return;let t=e.toLowerCase();(t.includes("mission complete")||t.includes("all tasks done")||t.includes("swarm complete")||t.includes("mission accomplished")||t.includes("all agents done"))&&this.swarmManager.stop(this.swarmId)}findAgentByName(e){let t=e.toLowerCase();for(let r of this.agents.values())if(r.name.toLowerCase()===t)return r}};import{randomUUID as oa}from"node:crypto";var $e=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}addMessage(e){let t=oa(),r=new Date().toISOString(),s={...e,id:t,timestamp:r};return this.db.prepare(`INSERT INTO swarm_console (id, swarmId, agentId, agentName, agentRole, message, source, timestamp)
79
+ `)}async escalate(e,t,r,s,n){let i={id:ia(),swarmId:this.config.swarm.id,agentId:e.id,agentName:e.name,level:t,reason:r,context:s,suggestedAction:n?.suggestedAction,status:"pending",timeout:n?.timeout,autoResolve:n?.autoResolve,createdAt:new Date().toISOString()};if(this.escalations.set(i.id,i),this.config.onEscalation?.({swarmId:this.config.swarm.id,escalation:i}),n?.autoResolve&&setTimeout(()=>{if(i.status==="pending"){i.status="auto-resolved",i.response=n.autoResolve.action,i.resolvedAt=new Date().toISOString();let o=this.escalationResolvers.get(i.id);o&&(o(n.autoResolve.action),this.escalationResolvers.delete(i.id))}},n.autoResolve.afterMs),n?.timeout&&!n?.autoResolve&&setTimeout(()=>{if(i.status==="pending"){i.status="expired",i.resolvedAt=new Date().toISOString();let o=this.escalationResolvers.get(i.id);o&&(o("ESCALATION_EXPIRED"),this.escalationResolvers.delete(i.id))}},n.timeout),!n?.timeout&&!n?.autoResolve&&setTimeout(()=>{if(this.escalationResolvers.has(i.id)){let o=this.escalationResolvers.get(i.id);o&&o("ESCALATION_FAILSAFE_TIMEOUT"),this.escalationResolvers.delete(i.id),i.status==="pending"&&(i.status="expired",i.resolvedAt=new Date().toISOString())}},36e5),n?.waitForResponse)return new Promise(o=>{this.escalationResolvers.set(i.id,o)})}autoCapture(e,t,r,s){if(!this.config.knowledgeManager||!e)return;let n=this.autoCaptureCount.get(t)??0;if(n>=10)return;let i=[{regex:/(?:found|discovered|located|identified)\s+(?:file|module|class|function|component)\s+[`"']?([^\s`"'\n,]+)/gi,category:"file_path",titlePrefix:"Found"},{regex:/(?:error|bug|issue|exception|failure)[:\s]+(.{10,100})/gi,category:"error",titlePrefix:"Error"},{regex:/(?:fixed|resolved|solved|patched|corrected)[:\s]+(.{10,100})/gi,category:"solution",titlePrefix:"Fixed"},{regex:/(?:pattern|convention|standard|approach)[:\s]+(.{10,100})/gi,category:"pattern",titlePrefix:"Pattern"},{regex:/(?:installed|added|configured|setup)\s+(?:package|dependency|module)\s+[`"']?([^\s`"'\n,]+)/gi,category:"config",titlePrefix:"Configured"},{regex:/(?:root cause|caused by|because of)[:\s]+(.{10,100})/gi,category:"note",titlePrefix:"Root cause"}],o=new Set,c=n;for(let{regex:l,category:d,titlePrefix:u}of i){l.lastIndex=0;let p;for(;(p=l.exec(e))!==null&&!(c>=10);){let m=p[1]?.trim()||p[0].trim();if(!(m.length<5||o.has(m))){o.add(m);try{this.config.knowledgeManager.addEntry({swarmId:s,agentId:t,category:d,title:`${u}: ${m.slice(0,80)}`,content:p[0].trim(),confidence:35,metadata:{source:"auto-capture",agentName:r},tags:["auto-captured"]}),c++}catch{}}}if(c>=10)break}this.autoCaptureCount.set(t,c)}getAgentName(e){return this.instances.get(e)?.agent.name??e}orderByConnections(e,t){let r=new Map(e.map(c=>[c.id,c])),s=new Map,n=new Map;for(let c of e)s.set(c.id,0),n.set(c.id,[]);for(let c of t){let l=s.get(c.to)??0;s.set(c.to,l+1);let d=n.get(c.from)??[];d.push(c.to),n.set(c.from,d)}let i=[];for(let[c,l]of s)l===0&&i.push(c);let o=[];for(;i.length>0;){let c=i.shift(),l=r.get(c);l&&o.push(l);for(let d of n.get(c)??[]){let u=(s.get(d)??1)-1;s.set(d,u),u===0&&i.push(d)}}for(let c of e)o.find(l=>l.id===c.id)||o.push(c);return o}detectLoopCompletion(e){let t=e.toLowerCase();return t.includes("loop complete")||t.includes("iteration done")||t.includes("no more iterations needed")||t.includes("===loop_complete===")}hasCycles(e){let t=new Map;for(let i of e)if(i.type==="pipe"||i.type==="trigger"){let o=t.get(i.from)??[];o.push(i.to),t.set(i.from,o)}let r=new Set,s=new Set,n=i=>{if(s.has(i))return!0;if(r.has(i))return!1;r.add(i),s.add(i);for(let o of t.get(i)??[])if(n(o))return!0;return s.delete(i),!1};for(let i of t.keys())if(n(i))return!0;return!1}};var We=class{running=!1;coordinatorId=null;swarmId=null;swarmManager=null;terminalManager=null;taskManager=null;broadcast=null;agents=new Map;terminalToAgent=new Map;coordinatorTerminalIds=[];outputBuffers=new Map;flushTimer=null;start(e,t,r,s,n,i){this.coordinatorId=e,this.swarmId=t,this.swarmManager=r,this.terminalManager=s,this.broadcast=n,this.taskManager=i??null,this.running=!0,this.refreshAgentRegistry(),this.flushTimer=setInterval(()=>this.flushAllBuffers(),3e3)}stop(){this.running=!1,this.coordinatorId=null,this.swarmId=null,this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),this.agents.clear(),this.terminalToAgent.clear(),this.coordinatorTerminalIds=[],this.outputBuffers.clear()}get isRunning(){return this.running}get activeCoordinatorId(){return this.coordinatorId}onTerminalOutput(e,t){if(!this.running)return;if(this.coordinatorTerminalIds.includes(e)){this.parseCoordinatorOutput(t);return}let r=this.terminalToAgent.get(e);!r||!this.agents.get(r)||(this.bufferAgentOutput(r,t),this.detectAgentStatus(r,t))}refreshAgentRegistry(){if(!this.swarmManager||!this.swarmId)return;let e=this.swarmManager.get(this.swarmId);if(e){this.agents.clear(),this.terminalToAgent.clear(),this.coordinatorTerminalIds=[];for(let t of e.agents){this.agents.set(t.id,{id:t.id,name:t.name,role:t.role,terminalIds:[...t.terminalIds]});for(let r of t.terminalIds)t.id===this.coordinatorId?this.coordinatorTerminalIds.push(r):this.terminalToAgent.set(r,t.id)}}}registerAgentTerminal(e,t,r){let s=this.agents.get(e)??{id:e,name:r.name,role:r.role,terminalIds:[]};s.terminalIds.push(t),this.agents.set(e,s),e===this.coordinatorId?this.coordinatorTerminalIds.push(t):this.terminalToAgent.set(t,e)}MAX_BUFFER_SIZE=5e3;bufferAgentOutput(e,t){let s=(this.outputBuffers.get(e)??"")+t,n=s.length>this.MAX_BUFFER_SIZE?s.slice(s.length-this.MAX_BUFFER_SIZE):s;this.outputBuffers.set(e,n),(t.includes(`
80
+ `)||t.includes("\r"))&&this.flushBuffer(e)}flushBuffer(e){let t=this.outputBuffers.get(e);if(!t||t.trim().length===0){this.outputBuffers.delete(e);return}let r=this.agents.get(e);if(!r){this.outputBuffers.delete(e);return}let s=this.truncateOutput(t.trim()),n=`[${r.name} (${r.role})]: ${s}`;this.writeToCoordinator(n),this.outputBuffers.delete(e)}flushAllBuffers(){for(let e of this.outputBuffers.keys())this.flushBuffer(e)}truncateOutput(e,t=500){return e.length<=t?e:e.slice(0,t)+"..."}writeToCoordinator(e){if(!(!this.terminalManager||this.coordinatorTerminalIds.length===0))for(let t of this.coordinatorTerminalIds)this.terminalManager.write(t,e+"\r")}coordinatorOutputBuffer="";parseCoordinatorOutput(e){this.coordinatorOutputBuffer+=e;let t=this.coordinatorOutputBuffer.split(/\r?\n/);this.coordinatorOutputBuffer=t.pop()??"";for(let r of t){let s=r.trim();if(!s)continue;this.detectSwarmCompletion(s);let n=s.match(/^\/send\s+@(\S+)\s+(.+)$/);if(n){this.handleSendCommand(n[1],n[2]);continue}let i=s.match(/^\/task\s+create\s+"([^"]+)"\s+@(\S+)$/);if(i){this.handleTaskCreate(i[1],i[2]);continue}let o=s.match(/^\/task\s+done\s+(\S+)$/);if(o){this.handleTaskMove(o[1],"done");continue}let c=s.match(/^\/task\s+block\s+(\S+)$/);if(c){this.handleTaskMove(c[1],"blocked");continue}let l=s.match(/^\/escalate\s+(.+)$/);if(l){this.handleEscalate(l[1]);continue}}}handleSendCommand(e,t){let r=this.findAgentByName(e);if(r&&this.terminalManager)for(let s of r.terminalIds)this.terminalManager.write(s,t+"\r")}handleTaskCreate(e,t){if(!this.taskManager||!this.swarmId||!this.swarmManager)return;let r=this.findAgentByName(t),s=this.swarmManager.get(this.swarmId);s&&this.taskManager.create({swarmId:this.swarmId,workspaceId:s.workspaceId,title:e,description:"",assignedAgentId:r?.id})}handleTaskMove(e,t){if(this.taskManager)try{this.taskManager.move(e,t)}catch{}}handleEscalate(e){if(!this.broadcast||!this.swarmId||!this.coordinatorId)return;let t=this.agents.get(this.coordinatorId);this.broadcast(`swarm.escalation.${this.swarmId}`,{swarmId:this.swarmId,agentId:this.coordinatorId,agentName:t?.name??"Coordinator",message:e,requiresResponse:!0})}detectAgentStatus(e,t){if(!this.broadcast||!this.swarmId)return;let r=t.toLowerCase(),s=null;r.includes("task completed")||r.includes("task done")||r.includes("finished")||r.includes("all tests passing")||r.includes("done")?s="done":r.includes("error:")||r.includes("fatal:")||r.includes("exception")?s="error":(r.includes("waiting for")||r.includes("blocked by"))&&(s="waiting"),s&&this.broadcast(`swarm.agent.status.${this.swarmId}`,{swarmId:this.swarmId,agentId:e,status:s}),s==="done"&&this.handleAgentTaskCompletion(e)}handleAgentTaskCompletion(e){if(!this.taskManager||!this.swarmId)return;let r=this.taskManager.list({swarmId:this.swarmId}).find(n=>n.assignedAgentId===e&&n.status==="running");if(!r)return;try{this.taskManager.move(r.id,"done")}catch{return}let s=this.findReviewerAgent();if(s){let i=this.agents.get(e)?.name??e;this.writeToCoordinator(`[SYSTEM]: Task "${r.title}" (${r.id}) assigned to ${i} has been marked as done. Reviewer agent "${s.name}" is available \u2014 consider using /send @${s.name} to assign a review.`)}}findReviewerAgent(){for(let e of this.agents.values())if(e.id!==this.coordinatorId&&e.role==="reviewer")return e}detectSwarmCompletion(e){if(!this.swarmId||!this.swarmManager)return;let t=e.toLowerCase();(t.includes("mission complete")||t.includes("all tasks done")||t.includes("swarm complete")||t.includes("mission accomplished")||t.includes("all agents done"))&&this.swarmManager.stop(this.swarmId)}findAgentByName(e){let t=e.toLowerCase();for(let r of this.agents.values())if(r.name.toLowerCase()===t)return r}};import{randomUUID as ca}from"node:crypto";var $e=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}addMessage(e){let t=ca(),r=new Date().toISOString(),s={...e,id:t,timestamp:r};return this.db.prepare(`INSERT INTO swarm_console (id, swarmId, agentId, agentName, agentRole, message, source, timestamp)
81
81
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(s.id,s.swarmId,s.agentId??null,s.agentName??null,s.agentRole??null,s.message,s.source,s.timestamp),this.broadcast(`swarm.console.${e.swarmId}`,{swarmId:e.swarmId,message:s}),s}getMessages(e,t=200){return this.db.prepare(`SELECT id, swarmId, agentId, agentName, agentRole, message, source, timestamp
82
- FROM swarm_console WHERE swarmId = ? ORDER BY timestamp DESC LIMIT ?`).all(e,t).reverse().map(s=>({id:s.id,swarmId:s.swarmId,agentId:s.agentId??void 0,agentName:s.agentName??void 0,agentRole:s.agentRole??void 0,message:s.message,source:s.source,timestamp:s.timestamp}))}};import{execSync as X}from"node:child_process";import{existsSync as ca}from"node:fs";import{join as Ht}from"node:path";var He=class{isGitRepo(e){try{return X("git rev-parse --is-inside-work-tree",{cwd:e,stdio:"pipe"}),!0}catch{return!1}}createForAgent(e,t,r){let s=r.toLowerCase().replace(/\s+/g,"-"),i=`swarm/${t.slice(0,8)}/${s}`,o=Ht(e,".swarm","worktrees",s);try{X(`git branch "${i}" HEAD`,{cwd:e,stdio:"pipe"})}catch{}return X(`git worktree add -B "${i}" "${o}" HEAD`,{cwd:e,stdio:"pipe"}),{path:o,branch:i}}remove(e,t){try{X(`git worktree remove --force "${t}"`,{cwd:e,stdio:"pipe"})}catch{}}removeAllForSwarm(e,t){let r=t.slice(0,8),s=Ht(e,".swarm","worktrees");if(ca(s))try{let n=X("git worktree list --porcelain",{cwd:e,stdio:"pipe"}).toString(),i=[],o={};for(let c of n.split(`
82
+ FROM swarm_console WHERE swarmId = ? ORDER BY timestamp DESC LIMIT ?`).all(e,t).reverse().map(s=>({id:s.id,swarmId:s.swarmId,agentId:s.agentId??void 0,agentName:s.agentName??void 0,agentRole:s.agentRole??void 0,message:s.message,source:s.source,timestamp:s.timestamp}))}};import{execSync as X}from"node:child_process";import{existsSync as la}from"node:fs";import{join as Ht}from"node:path";var He=class{isGitRepo(e){try{return X("git rev-parse --is-inside-work-tree",{cwd:e,stdio:"pipe"}),!0}catch{return!1}}createForAgent(e,t,r){let s=r.toLowerCase().replace(/\s+/g,"-"),i=`swarm/${t.slice(0,8)}/${s}`,o=Ht(e,".swarm","worktrees",s);try{X(`git branch "${i}" HEAD`,{cwd:e,stdio:"pipe"})}catch{}return X(`git worktree add -B "${i}" "${o}" HEAD`,{cwd:e,stdio:"pipe"}),{path:o,branch:i}}remove(e,t){try{X(`git worktree remove --force "${t}"`,{cwd:e,stdio:"pipe"})}catch{}}removeAllForSwarm(e,t){let r=t.slice(0,8),s=Ht(e,".swarm","worktrees");if(la(s))try{let n=X("git worktree list --porcelain",{cwd:e,stdio:"pipe"}).toString(),i=[],o={};for(let c of n.split(`
83
83
  `))c.startsWith("worktree ")?o={worktree:c.slice(9).trim()}:c.startsWith("branch ")&&(o.branch=c.slice(7).trim(),o.worktree&&o.branch&&i.push({worktree:o.worktree,branch:o.branch}));for(let c of i)c.branch.includes(`swarm/${r}/`)&&this.remove(e,c.worktree)}catch{}}createForArea(e,t,r,s){let n=r.toLowerCase().replace(/\s+/g,"-"),i=t.slice(0,8),o=s||`area/${i}/${n}`,c=Ht(e,".areas","worktrees",n);try{X(`git branch "${o}" HEAD`,{cwd:e,stdio:"pipe"})}catch{}return X(`git worktree add -B "${o}" "${c}" HEAD`,{cwd:e,stdio:"pipe"}),{path:c,branch:o}}removeForArea(e,t){try{X(`git worktree remove --force "${t}"`,{cwd:e,stdio:"pipe"})}catch{}}initGitRepo(e){if(this.isGitRepo(e))return!1;try{return X("git init",{cwd:e,stdio:"pipe"}),!0}catch{return!1}}list(e){try{let t=X("git worktree list --porcelain",{cwd:e,stdio:"pipe"}).toString(),r=[],s={};for(let n of t.split(`
84
- `))n.startsWith("worktree ")?s={path:n.slice(9).trim()}:n.startsWith("HEAD ")?s.head=n.slice(5).trim():n.startsWith("branch ")?s.branch=n.slice(7).trim():n===""&&s.path&&(r.push({path:s.path,branch:s.branch??"",head:s.head??""}),s={});return r}catch{return[]}}};import{randomUUID as la}from"node:crypto";var qe=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}addEntry(e){let t=la(),r=new Date().toISOString(),s=null;if(e.agentId&&(s=this.db.prepare("SELECT name FROM swarm_agents WHERE id = ?").get(e.agentId)?.name??null),this.db.prepare(`INSERT INTO swarm_knowledge_entries (id, swarmId, agentId, agentName, category, title, content, metadata, createdAt, updatedAt, confidence, relatedEntryIds, isVerified)
85
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '[]', 0)`).run(t,e.swarmId,e.agentId??null,s,e.category,e.title,e.content,JSON.stringify(e.metadata??{}),r,r,e.confidence??50),e.tags&&e.tags.length>0){let i=this.db.prepare("INSERT INTO swarm_knowledge_tags (entryId, tag) VALUES (?, ?)");for(let o of e.tags)i.run(t,o)}let n=this.getEntry(t);return this.broadcast("knowledge.entry.added",{swarmId:e.swarmId,entry:n}),n}updateEntry(e){let t=this.getEntry(e.entryId);if(!t)return null;let r=new Date().toISOString(),s=["updatedAt = ?"],n=[r];if(e.title!==void 0&&(s.push("title = ?"),n.push(e.title)),e.content!==void 0&&(s.push("content = ?"),n.push(e.content)),e.metadata!==void 0&&(s.push("metadata = ?"),n.push(JSON.stringify(e.metadata))),e.confidence!==void 0&&(s.push("confidence = ?"),n.push(String(e.confidence))),e.isVerified!==void 0&&(s.push("isVerified = ?"),n.push(e.isVerified?"1":"0")),n.push(e.entryId),this.db.prepare(`UPDATE swarm_knowledge_entries SET ${s.join(", ")} WHERE id = ?`).run(...n),e.tags!==void 0&&(this.db.prepare("DELETE FROM swarm_knowledge_tags WHERE entryId = ?").run(e.entryId),e.tags.length>0)){let o=this.db.prepare("INSERT INTO swarm_knowledge_tags (entryId, tag) VALUES (?, ?)");for(let c of e.tags)o.run(e.entryId,c)}let i=this.getEntry(e.entryId);return this.broadcast("knowledge.entry.updated",{swarmId:t.swarmId,entry:i}),i}deleteEntry(e){let t=this.getEntry(e);return t&&this.db.prepare("DELETE FROM swarm_knowledge_entries WHERE id = ?").run(e).changes>0?(this.broadcast("knowledge.entry.deleted",{swarmId:t.swarmId,entryId:e}),!0):!1}verifyEntry(e,t){let r=this.getEntry(e);if(!r)return null;let s=new Date().toISOString();this.db.prepare("UPDATE swarm_knowledge_entries SET isVerified = ?, updatedAt = ? WHERE id = ?").run(t?1:0,s,e);let n=this.getEntry(e);return this.broadcast("knowledge.entry.updated",{swarmId:r.swarmId,entry:n}),n}search(e){let t=[],r=[];if(e.acrossSwarms?e.workspaceId&&(t.push("e.swarmId IN (SELECT id FROM swarms WHERE workspaceId = ?)"),r.push(e.workspaceId)):e.swarmId&&(t.push("e.swarmId = ?"),r.push(e.swarmId)),e.query){t.push("(e.title LIKE ? OR e.content LIKE ?)");let d=`%${e.query}%`;r.push(d,d)}e.category&&(t.push("e.category = ?"),r.push(e.category)),e.agentId&&(t.push("e.agentId = ?"),r.push(e.agentId)),e.minConfidence!==void 0&&(t.push("e.confidence >= ?"),r.push(String(e.minConfidence))),e.onlyVerified&&t.push("e.isVerified = 1");let s="";e.tags&&e.tags.length>0&&(s=`INNER JOIN swarm_knowledge_tags t ON t.entryId = e.id AND t.tag IN (${e.tags.map(()=>"?").join(", ")})`,r.push(...e.tags));let n=t.length>0?`WHERE ${t.join(" AND ")}`:"",i=e.limit??20,o=this.db.prepare(`SELECT COUNT(DISTINCT e.id) as total FROM swarm_knowledge_entries e ${s} ${n}`).get(...r);return{entries:this.db.prepare(`SELECT DISTINCT e.* FROM swarm_knowledge_entries e ${s} ${n} ORDER BY e.isVerified DESC, e.confidence DESC, e.createdAt DESC LIMIT ?`).all(...r,i).map(d=>this.rowToEntry(d)),total:o.total}}getAllForSwarm(e,t=20){return this.db.prepare("SELECT * FROM swarm_knowledge_entries WHERE swarmId = ? ORDER BY isVerified DESC, confidence DESC, createdAt DESC LIMIT ?").all(e,t).map(s=>this.rowToEntry(s))}getEntry(e){let t=this.db.prepare("SELECT * FROM swarm_knowledge_entries WHERE id = ?").get(e);return t?this.rowToEntry(t):null}rowToEntry(e){let t=this.getTagsForEntry(e.id);return{id:e.id,swarmId:e.swarmId,agentId:e.agentId??void 0,agentName:e.agentName??void 0,category:e.category,title:e.title,content:e.content,metadata:JSON.parse(e.metadata),createdAt:e.createdAt,updatedAt:e.updatedAt,confidence:e.confidence,relatedEntryIds:JSON.parse(e.relatedEntryIds),isVerified:e.isVerified===1,tags:t.length>0?t:void 0}}getTagsForEntry(e){return this.db.prepare("SELECT tag FROM swarm_knowledge_tags WHERE entryId = ?").all(e).map(r=>r.tag)}};import{randomUUID as da}from"node:crypto";var Xe=class{constructor(e,t){this.db=e;this.broadcast=t}post(e){let t=da(),r=new Date().toISOString(),s=this.db.prepare("SELECT name, role FROM swarm_agents WHERE id = ?").get(e.agentId),n=s?.name??"Unknown",i=s?.role??"worker",o=JSON.stringify(e.tags??[]),c=JSON.stringify(e.attachments??[]),l=e.priority??"normal";this.db.prepare(`INSERT INTO swarm_mailbox (id, swarmId, agentId, agentName, agentRole, type, title, content, priority, tags, parentMessageId, attachments, timestamp, readBy, createdAt)
84
+ `))n.startsWith("worktree ")?s={path:n.slice(9).trim()}:n.startsWith("HEAD ")?s.head=n.slice(5).trim():n.startsWith("branch ")?s.branch=n.slice(7).trim():n===""&&s.path&&(r.push({path:s.path,branch:s.branch??"",head:s.head??""}),s={});return r}catch{return[]}}};import{randomUUID as da}from"node:crypto";var qe=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}addEntry(e){let t=da(),r=new Date().toISOString(),s=null;if(e.agentId&&(s=this.db.prepare("SELECT name FROM swarm_agents WHERE id = ?").get(e.agentId)?.name??null),this.db.prepare(`INSERT INTO swarm_knowledge_entries (id, swarmId, agentId, agentName, category, title, content, metadata, createdAt, updatedAt, confidence, relatedEntryIds, isVerified)
85
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '[]', 0)`).run(t,e.swarmId,e.agentId??null,s,e.category,e.title,e.content,JSON.stringify(e.metadata??{}),r,r,e.confidence??50),e.tags&&e.tags.length>0){let i=this.db.prepare("INSERT INTO swarm_knowledge_tags (entryId, tag) VALUES (?, ?)");for(let o of e.tags)i.run(t,o)}let n=this.getEntry(t);return this.broadcast("knowledge.entry.added",{swarmId:e.swarmId,entry:n}),n}updateEntry(e){let t=this.getEntry(e.entryId);if(!t)return null;let r=new Date().toISOString(),s=["updatedAt = ?"],n=[r];if(e.title!==void 0&&(s.push("title = ?"),n.push(e.title)),e.content!==void 0&&(s.push("content = ?"),n.push(e.content)),e.metadata!==void 0&&(s.push("metadata = ?"),n.push(JSON.stringify(e.metadata))),e.confidence!==void 0&&(s.push("confidence = ?"),n.push(String(e.confidence))),e.isVerified!==void 0&&(s.push("isVerified = ?"),n.push(e.isVerified?"1":"0")),n.push(e.entryId),this.db.prepare(`UPDATE swarm_knowledge_entries SET ${s.join(", ")} WHERE id = ?`).run(...n),e.tags!==void 0&&(this.db.prepare("DELETE FROM swarm_knowledge_tags WHERE entryId = ?").run(e.entryId),e.tags.length>0)){let o=this.db.prepare("INSERT INTO swarm_knowledge_tags (entryId, tag) VALUES (?, ?)");for(let c of e.tags)o.run(e.entryId,c)}let i=this.getEntry(e.entryId);return this.broadcast("knowledge.entry.updated",{swarmId:t.swarmId,entry:i}),i}deleteEntry(e){let t=this.getEntry(e);return t&&this.db.prepare("DELETE FROM swarm_knowledge_entries WHERE id = ?").run(e).changes>0?(this.broadcast("knowledge.entry.deleted",{swarmId:t.swarmId,entryId:e}),!0):!1}verifyEntry(e,t){let r=this.getEntry(e);if(!r)return null;let s=new Date().toISOString();this.db.prepare("UPDATE swarm_knowledge_entries SET isVerified = ?, updatedAt = ? WHERE id = ?").run(t?1:0,s,e);let n=this.getEntry(e);return this.broadcast("knowledge.entry.updated",{swarmId:r.swarmId,entry:n}),n}search(e){let t=[],r=[];if(e.acrossSwarms?e.workspaceId&&(t.push("e.swarmId IN (SELECT id FROM swarms WHERE workspaceId = ?)"),r.push(e.workspaceId)):e.swarmId&&(t.push("e.swarmId = ?"),r.push(e.swarmId)),e.query){t.push("(e.title LIKE ? OR e.content LIKE ?)");let d=`%${e.query}%`;r.push(d,d)}e.category&&(t.push("e.category = ?"),r.push(e.category)),e.agentId&&(t.push("e.agentId = ?"),r.push(e.agentId)),e.minConfidence!==void 0&&(t.push("e.confidence >= ?"),r.push(String(e.minConfidence))),e.onlyVerified&&t.push("e.isVerified = 1");let s="";e.tags&&e.tags.length>0&&(s=`INNER JOIN swarm_knowledge_tags t ON t.entryId = e.id AND t.tag IN (${e.tags.map(()=>"?").join(", ")})`,r.push(...e.tags));let n=t.length>0?`WHERE ${t.join(" AND ")}`:"",i=e.limit??20,o=this.db.prepare(`SELECT COUNT(DISTINCT e.id) as total FROM swarm_knowledge_entries e ${s} ${n}`).get(...r);return{entries:this.db.prepare(`SELECT DISTINCT e.* FROM swarm_knowledge_entries e ${s} ${n} ORDER BY e.isVerified DESC, e.confidence DESC, e.createdAt DESC LIMIT ?`).all(...r,i).map(d=>this.rowToEntry(d)),total:o.total}}getAllForSwarm(e,t=20){return this.db.prepare("SELECT * FROM swarm_knowledge_entries WHERE swarmId = ? ORDER BY isVerified DESC, confidence DESC, createdAt DESC LIMIT ?").all(e,t).map(s=>this.rowToEntry(s))}getEntry(e){let t=this.db.prepare("SELECT * FROM swarm_knowledge_entries WHERE id = ?").get(e);return t?this.rowToEntry(t):null}rowToEntry(e){let t=this.getTagsForEntry(e.id);return{id:e.id,swarmId:e.swarmId,agentId:e.agentId??void 0,agentName:e.agentName??void 0,category:e.category,title:e.title,content:e.content,metadata:JSON.parse(e.metadata),createdAt:e.createdAt,updatedAt:e.updatedAt,confidence:e.confidence,relatedEntryIds:JSON.parse(e.relatedEntryIds),isVerified:e.isVerified===1,tags:t.length>0?t:void 0}}getTagsForEntry(e){return this.db.prepare("SELECT tag FROM swarm_knowledge_tags WHERE entryId = ?").all(e).map(r=>r.tag)}};import{randomUUID as ua}from"node:crypto";var Xe=class{constructor(e,t){this.db=e;this.broadcast=t}post(e){let t=ua(),r=new Date().toISOString(),s=this.db.prepare("SELECT name, role FROM swarm_agents WHERE id = ?").get(e.agentId),n=s?.name??"Unknown",i=s?.role??"worker",o=JSON.stringify(e.tags??[]),c=JSON.stringify(e.attachments??[]),l=e.priority??"normal";this.db.prepare(`INSERT INTO swarm_mailbox (id, swarmId, agentId, agentName, agentRole, type, title, content, priority, tags, parentMessageId, attachments, timestamp, readBy, createdAt)
86
86
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '[]', ?)`).run(t,e.swarmId,e.agentId,n,i,e.type,e.title,e.content,l,o,e.parentMessageId??null,c,r,r);let d={id:t,swarmId:e.swarmId,agentId:e.agentId,agentName:n,agentRole:i,type:e.type,title:e.title,content:e.content,priority:l,tags:e.tags??[],parentMessageId:e.parentMessageId,attachments:e.attachments??[],timestamp:r,readBy:[]};return this.broadcast("mailbox.new-message",{swarmId:e.swarmId,message:d}),d}list(e){let t=["swarmId = ?"],r=[e.swarmId];if(e.type&&(t.push("type = ?"),r.push(e.type)),e.priority&&(t.push("priority = ?"),r.push(e.priority)),e.tags&&e.tags.length>0)for(let u of e.tags){let p=u.replace(/%/g,"\\%").replace(/_/g,"\\_");t.push("tags LIKE ? ESCAPE '\\'"),r.push(`%"${p}"%`)}e.fromAgentId&&(t.push("agentId = ?"),r.push(e.fromAgentId)),e.since&&(t.push("timestamp >= ?"),r.push(e.since));let s=t.join(" AND "),i=this.db.prepare(`SELECT COUNT(*) as total FROM swarm_mailbox WHERE ${s}`).get(...r).total,o=e.limit??50,c=e.offset??0,d=this.db.prepare(`SELECT * FROM swarm_mailbox WHERE ${s} ORDER BY timestamp DESC LIMIT ? OFFSET ?`).all(...r,o,c).map(u=>this.rowToMessage(u));return{messages:d,total:i,hasMore:c+d.length<i}}markRead(e,t){let r=this.db.prepare("SELECT readBy FROM swarm_mailbox WHERE id = ?").get(e);if(!r)return;let s=JSON.parse(r.readBy);s.includes(t)||(s.push(t),this.db.prepare("UPDATE swarm_mailbox SET readBy = ? WHERE id = ?").run(JSON.stringify(s),e))}getThread(e){return this.db.prepare("SELECT * FROM swarm_mailbox WHERE parentMessageId = ? ORDER BY timestamp ASC").all(e).map(r=>this.rowToMessage(r))}rowToMessage(e){return{id:e.id,swarmId:e.swarmId,agentId:e.agentId,agentName:e.agentName,agentRole:e.agentRole,type:e.type,title:e.title,content:e.content,priority:e.priority,tags:JSON.parse(e.tags),parentMessageId:e.parentMessageId??void 0,attachments:JSON.parse(e.attachments),timestamp:e.timestamp,readBy:JSON.parse(e.readBy)}}};var je=class{db;terminalManager;broadcast;agentSession;worktreeManager;coordinatorLoops=new Map;agentTerminals=new Map;orchestrators=new Map;topologies=new Map;consoleManager;knowledgeManager;mailboxManager;taskManager=null;settingsManager=null;providerRegistry;constructor(e,t,r,s){this.db=e,this.terminalManager=t,this.broadcast=r,this.providerRegistry=s,this.consoleManager=new $e(e,r),this.knowledgeManager=new qe(e,r),this.mailboxManager=new Xe(e,r),this.agentSession=new Ue(s),this.worktreeManager=new He}setTaskManager(e){this.taskManager=e}setSettingsManager(e){this.settingsManager=e}getKnowledgeManager(){return this.knowledgeManager}getMailboxManager(){return this.mailboxManager}getTaskManager(){return this.taskManager}onTerminalOutput(e,t){for(let[r,s]of this.coordinatorLoops)s.isRunning&&s.onTerminalOutput(e,t)}create(e){let t=qt(),r=new Date().toISOString(),s=e.knowledge.map(i=>({...i,id:qt()}));this.db.prepare(`INSERT INTO swarms (id, workspaceId, name, mission, directory, knowledge, status, presetSize, cliForAll, autoApprove, useWorktrees, createdAt)
87
87
  VALUES (?, ?, ?, ?, ?, ?, 'draft', ?, ?, ?, ?, ?)`).run(t,e.workspaceId,e.name,e.mission,e.directory,JSON.stringify(s),e.presetSize??null,e.cliForAll??null,e.autoApprove?1:0,e.useWorktrees?1:0,r);for(let i of s)this.db.prepare("INSERT INTO swarm_knowledge (id, swarmId, name, path, type) VALUES (?, ?, ?, ?, ?)").run(i.id,t,i.name,i.path,i.type);let n=e.agents.map((i,o)=>this.insertAgent(t,i,o,r));return this.consoleManager.addMessage({swarmId:t,message:`Swarm "${e.name}" created with ${n.length} agents`,source:"system"}),this.buildSwarm(t)}insertAgent(e,t,r,s){let n=qt();return this.db.prepare(`INSERT INTO swarm_agents (id, swarmId, "index", name, role, cli, status, autoApprove, systemPrompt, skills, mcps, workScope, createdAt)
88
- VALUES (?, ?, ?, ?, ?, ?, 'idle', ?, ?, ?, ?, ?, ?)`).run(n,e,r,t.name,t.role,t.cli,t.autoApprove?1:0,t.systemPrompt??null,JSON.stringify(t.skills??[]),JSON.stringify(t.mcps??[]),t.workScope?JSON.stringify(t.workScope):null,s),this.rowToAgent({id:n,swarmId:e,index:r,name:t.name,role:t.role,cli:t.cli,status:"idle",autoApprove:t.autoApprove?1:0,systemPrompt:t.systemPrompt??null,skills:JSON.stringify(t.skills??[]),mcps:JSON.stringify(t.mcps??[]),workScope:t.workScope?JSON.stringify(t.workScope):null,worktreeBranch:null,worktreePath:null,createdAt:s})}async launch(e){let t=this.buildSwarm(e);if(!t)throw new Error(`Swarm ${e} not found`);let r=new Date().toISOString();this.db.prepare("UPDATE swarms SET status = 'active', launchedAt = ? WHERE id = ?").run(r,e);let s=K(t.directory,".swarm");de(K(s,"agents"),{recursive:!0}),de(K(s,"registry"),{recursive:!0}),de(K(s,"progress"),{recursive:!0});let n=this.settingsManager?.getEnvVarsForWorkspace(t.workspaceId)??{};for(let c of t.agents){this.db.prepare("UPDATE swarm_agents SET status = 'booting' WHERE id = ?").run(c.id);let l=this.buildSwarm(e),d=await this.agentSession.boot(c,l,this.terminalManager,Object.keys(n).length>0?n:void 0,this.worktreeManager),{terminalId:u,worktreePath:p,worktreeBranch:m}=d,h=this.agentTerminals.get(c.id)??[];h.push(u),this.agentTerminals.set(c.id,h),this.db.prepare("UPDATE swarm_agents SET status = 'running', worktreePath = ?, worktreeBranch = ? WHERE id = ?").run(p??null,m??null,c.id),this.consoleManager.addMessage({swarmId:e,agentId:c.id,agentName:c.name,agentRole:c.role,message:`Agent "${c.name}" (${c.role}) started on terminal ${u}`,source:"system"});let f=this.coordinatorLoops.get(e);if(f?.isRunning&&f.registerAgentTerminal(c.id,u,c),c.role==="coordinator"){let g=new We;g.start(c.id,e,this,this.terminalManager,this.broadcast,this.taskManager??void 0),this.coordinatorLoops.set(e,g);for(let w of t.agents){let E=this.agentTerminals.get(w.id)??[];for(let T of E)g.registerAgentTerminal(w.id,T,w)}}}let i=this.buildSwarm(e),o={swarmId:e,status:i.status,launchedAt:i.launchedAt,agents:i.agents.map(c=>({id:c.id,name:c.name,role:c.role,status:c.status}))};if(ua(K(s,"progress","status.json"),JSON.stringify(o,null,2)),this.taskManager){let c=this.taskManager.list({swarmId:e}),l=i.agents.filter(u=>u.role!=="coordinator"),d=0;for(let u of c)if(u.status==="todo"&&!u.assignedAgentId&&l.length>0){let p=l[d%l.length];this.taskManager.assign(u.id,p.id),d++}}this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"active"})}stop(e){let t=this.buildSwarm(e);if(!t)throw new Error(`Swarm ${e} not found`);let r=this.orchestrators.get(e);r&&(r.stop(),this.orchestrators.delete(e));let s=this.coordinatorLoops.get(e);s&&(s.stop(),this.coordinatorLoops.delete(e));for(let i of t.agents){let o=this.agentTerminals.get(i.id)??[];for(let c of o)this.terminalManager.close(c);this.agentTerminals.delete(i.id),this.db.prepare("UPDATE swarm_agents SET status = 'idle' WHERE id = ?").run(i.id)}if(t.useWorktrees&&t.directory)try{this.worktreeManager.removeAllForSwarm(t.directory,e)}catch(i){console.warn(`[WorktreeManager] Cleanup failed for swarm ${e}:`,i)}let n=new Date().toISOString();this.db.prepare("UPDATE swarms SET status = 'completed', stoppedAt = ? WHERE id = ?").run(n,e),this.consoleManager.addMessage({swarmId:e,message:"Swarm stopped",source:"system"}),this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"completed"})}pause(e){this.db.prepare("UPDATE swarms SET status = 'paused' WHERE id = ?").run(e),this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"paused"})}resume(e){this.db.prepare("UPDATE swarms SET status = 'active' WHERE id = ?").run(e),this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"active"})}list(e){return this.db.prepare("SELECT id FROM swarms WHERE workspaceId = ? ORDER BY createdAt DESC").all(e).map(r=>this.buildSwarm(r.id))}get(e){return this.db.prepare("SELECT id FROM swarms WHERE id = ?").get(e)?this.buildSwarm(e):null}delete(e){let t=this.get(e);return t&&t.status==="active"&&this.stop(e),this.db.prepare("DELETE FROM swarms WHERE id = ?").run(e).changes>0}message(e,t,r){if(t){let s=this.agentTerminals.get(t)??[];for(let n of s)this.terminalManager.write(n,r+"\r")}else{let s=this.buildSwarm(e);for(let n of s.agents){let i=this.agentTerminals.get(n.id)??[];for(let o of i)this.terminalManager.write(o,r+"\r")}}this.consoleManager.addMessage({swarmId:e,agentId:t,message:r,source:"user"})}addAgent(e){let t=new Date().toISOString(),s=(this.db.prepare('SELECT MAX("index") as maxIdx FROM swarm_agents WHERE swarmId = ?').get(e.swarmId)?.maxIdx??-1)+1;return this.insertAgent(e.swarmId,e.agent,s,t)}removeAgent(e){let t=this.agentTerminals.get(e.agentId)??[];for(let s of t)this.terminalManager.close(s);return this.agentTerminals.delete(e.agentId),this.db.prepare("DELETE FROM swarm_agents WHERE id = ? AND swarmId = ?").run(e.agentId,e.swarmId).changes>0}updateAgent(e){let{updates:t}=e,r=[],s=[];if(t.name!==void 0&&(r.push("name = ?"),s.push(t.name)),t.role!==void 0&&(r.push("role = ?"),s.push(t.role)),t.cli!==void 0&&(r.push("cli = ?"),s.push(t.cli)),t.autoApprove!==void 0&&(r.push("autoApprove = ?"),s.push(t.autoApprove?1:0)),t.systemPrompt!==void 0&&(r.push("systemPrompt = ?"),s.push(t.systemPrompt)),t.skills!==void 0&&(r.push("skills = ?"),s.push(JSON.stringify(t.skills))),t.mcps!==void 0&&(r.push("mcps = ?"),s.push(JSON.stringify(t.mcps))),t.workScope!==void 0&&(r.push("workScope = ?"),s.push(JSON.stringify(t.workScope))),r.length===0)return null;s.push(e.agentId,e.swarmId),this.db.prepare(`UPDATE swarm_agents SET ${r.join(", ")} WHERE id = ? AND swarmId = ?`).run(...s);let n=this.db.prepare("SELECT * FROM swarm_agents WHERE id = ?").get(e.agentId);return n?this.rowToAgent(n):null}getStats(e){let t=this.getAgents(e),r=t.filter(c=>c.status==="running"||c.status==="booting").length,s=t.filter(c=>c.status==="done").length,n=t.filter(c=>c.status==="error").length,i=this.db.prepare("SELECT launchedAt FROM swarms WHERE id = ?").get(e),o=0;return i?.launchedAt&&(o=Date.now()-new Date(i.launchedAt).getTime()),{activeAgents:r,completedTasks:s,errors:n,escalations:0,reviewsPending:0,elapsedTime:o}}setTopology(e,t){this.topologies.set(e,t),this.db.prepare("UPDATE swarms SET knowledge = json_set(knowledge, '$.topology', ?) WHERE id = ?").run(JSON.stringify(t),e)}launchOrchestrated(e){let t=this.buildSwarm(e);if(!t)throw new Error(`Swarm ${e} not found`);let r=new Date().toISOString();this.db.prepare("UPDATE swarms SET status = 'active', launchedAt = ? WHERE id = ?").run(r,e);let s=K(t.directory,".swarm");de(K(s,"agents"),{recursive:!0}),de(K(s,"registry"),{recursive:!0}),de(K(s,"progress"),{recursive:!0});let n=this.settingsManager?.getEnvVarsForWorkspace(t.workspaceId)??{},i=this.topologies.get(e)??t.topology,o=this.settingsManager?.get("providers.claude_binary_path")?.value??this.providerRegistry?.getClaudeBinaryPath()??"claude",c=new Be({swarm:t,topology:i,claudeBinaryPath:o,env:Object.keys(n).length>0?n:void 0,onAgentOutput:l=>{this.broadcast(`orchestrator.agent.output.${e}`,l),this.consoleManager.addMessage({swarmId:e,agentId:l.agentId,agentName:l.agentName,message:`[${l.type}] ${l.content.slice(0,500)}`,source:"agent"})},onCLISpawned:l=>{this.broadcast(`orchestrator.cli.spawned.${e}`,l),this.consoleManager.addMessage({swarmId:e,agentId:l.agentId,message:`Spawned ${l.cli} CLI: ${l.prompt.slice(0,200)}`,source:"system"})},onCLICompleted:l=>{this.broadcast(`orchestrator.cli.completed.${e}`,l)},onEscalation:l=>{this.broadcast(`orchestrator.escalation.${e}`,l),this.broadcast(`swarm.escalation.${e}`,{swarmId:e,agentId:l.escalation.agentId,agentName:l.escalation.agentName,message:l.escalation.reason,requiresResponse:!0,escalation:l.escalation})},onAgentCompleted:l=>{this.broadcast(`swarm.agent.status.${e}`,{swarmId:e,agentId:l.agentId,status:l.error?"error":"done"}),this.db.prepare("UPDATE swarm_agents SET status = ? WHERE id = ?").run(l.error?"error":"done",l.agentId)},onSwarmCompleted:l=>{this.db.prepare("UPDATE swarms SET status = 'completed', stoppedAt = ? WHERE id = ?").run(new Date().toISOString(),e),this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"completed"}),this.consoleManager.addMessage({swarmId:e,message:"Swarm orchestration completed",source:"system"}),this.orchestrators.delete(e)}});this.orchestrators.set(e,c);for(let l of t.agents)this.db.prepare("UPDATE swarm_agents SET status = 'running' WHERE id = ?").run(l.id);this.consoleManager.addMessage({swarmId:e,message:`Swarm "${t.name}" launched in orchestrated mode with ${t.agents.length} agents`,source:"system"}),this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"active"}),c.start().catch(l=>{console.error(`[AgentOrchestrator] Swarm ${e} failed:`,l),this.db.prepare("UPDATE swarms SET status = 'error', stoppedAt = ? WHERE id = ?").run(new Date().toISOString(),e),this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"error"})})}async spawnCLI(e,t,r){let s=this.orchestrators.get(e);if(!s)throw new Error(`No active orchestrator for swarm ${e}`);return{sessionId:await s.getCLIProvider().spawn(t,r)}}respondToEscalation(e,t){for(let r of this.orchestrators.values())r.respondToEscalation(e,t)}getOrchestrator(e){return this.orchestrators.get(e)}getAgents(e){return this.db.prepare('SELECT * FROM swarm_agents WHERE swarmId = ? ORDER BY "index" ASC').all(e).map(r=>this.rowToAgent(r))}buildSwarm(e){let t=this.db.prepare("SELECT * FROM swarms WHERE id = ?").get(e);if(!t)throw new Error(`Swarm ${e} not found`);let r=this.getAgents(e),s=this.getStats(e);return{id:t.id,workspaceId:t.workspaceId,name:t.name,mission:t.mission,directory:t.directory,knowledge:JSON.parse(t.knowledge),agents:r,status:t.status,presetSize:t.presetSize??void 0,cliForAll:t.cliForAll??void 0,autoApprove:t.autoApprove===1,useWorktrees:t.useWorktrees===1,stats:s,createdAt:t.createdAt,launchedAt:t.launchedAt??void 0,stoppedAt:t.stoppedAt??void 0}}rowToAgent(e){let t=this.agentTerminals.get(e.id)??[];return{id:e.id,swarmId:e.swarmId,index:e.index,name:e.name,role:e.role,cli:e.cli,status:e.status,autoApprove:e.autoApprove===1,terminalIds:t,systemPrompt:e.systemPrompt??void 0,skills:JSON.parse(e.skills),mcps:JSON.parse(e.mcps),workScope:e.workScope?JSON.parse(e.workScope):void 0,worktreeBranch:e.worktreeBranch??void 0,worktreePath:e.worktreePath??void 0,elapsedTime:0}}};import{randomUUID as Xr}from"node:crypto";import Y from"node:fs";import Q from"node:path";import jr from"node:os";var Gr={"frontend-design":{description:"Frontend design patterns and best practices"},shadcn:{description:"shadcn/ui component library integration"},"next-best-practices":{description:"Next.js best practices and patterns"},"systematic-debugging":{description:"Systematic debugging methodology"},"web-design-guidelines":{description:"Web design guidelines and principles"},"vercel-react-best-practices":{description:"Vercel + React best practices"},"supabase-postgres-best-practices":{description:"Supabase + Postgres best practices"},"expo-tailwind-setup":{description:"Expo + Tailwind CSS setup guide"},"nodejs-backend-patterns":{description:"Node.js backend architecture patterns"},"api-design-principles":{description:"API design principles and REST patterns"},"database-schema-design":{description:"Database schema design best practices"},"better-auth":{description:"Authentication best practices with Better Auth"},"skill-creator":{description:"Create custom skills for agents"},"building-native-ui":{description:"Building native UI components"},"expo-deployment":{description:"Expo deployment and distribution"}},Kr=[{id:"nextjs-convex-clerk",name:"Next.js + Convex + Clerk",description:"Full-stack Next.js with Convex backend and Clerk auth",skills:["next-best-practices","frontend-design","shadcn","better-auth"],mcps:[],stack:"nextjs"},{id:"react-native-expo",name:"React Native + Expo",description:"Mobile development with React Native and Expo",skills:["expo-tailwind-setup","expo-deployment","building-native-ui"],mcps:[],stack:"mobile"},{id:"fullstack-supabase",name:"Full Stack Supabase",description:"Full-stack app with Supabase backend and Postgres",skills:["supabase-postgres-best-practices","database-schema-design","api-design-principles","better-auth"],mcps:[],stack:"supabase"},{id:"vibe-coding",name:"Vibe Coding",description:"Generic vibe coding setup for rapid prototyping",skills:["frontend-design","web-design-guidelines","systematic-debugging","shadcn"],mcps:[],stack:"generic"},{id:"api-nodejs",name:"API + Node.js",description:"Backend API development with Node.js",skills:["nodejs-backend-patterns","api-design-principles","database-schema-design","systematic-debugging"],mcps:[],stack:"backend"}],Ge=class{projectSkillsDir(e){return Q.join(e,".swarm","registry","skills")}projectMcpsDir(e){return Q.join(e,".swarm","registry","mcps")}globalSkillsDir(){return Q.join(jr.homedir(),".swarm","registry","skills")}globalMcpsDir(){return Q.join(jr.homedir(),".swarm","registry","mcps")}readJsonFiles(e){return Y.existsSync(e)?Y.readdirSync(e).filter(r=>r.endsWith(".json")).map(r=>JSON.parse(Y.readFileSync(Q.join(e,r),"utf-8"))):[]}listSkills(e){let t=this.readJsonFiles(this.globalSkillsDir());return e?[...this.readJsonFiles(this.projectSkillsDir(e)),...t]:t}searchSkills(e){let t=e.toLowerCase();return Object.entries(Gr).filter(([r,s])=>r.includes(t)||s.description.toLowerCase().includes(t)).map(([r,s])=>({name:r,description:s.description,source:"skills.sh"}))}installSkill(e,t){let r=this.projectSkillsDir(t);Y.mkdirSync(r,{recursive:!0});let s=Gr[e],n={id:Xr(),name:e,description:s?.description??`Custom skill: ${e}`,source:s?"skills.sh":"custom",installedAt:new Date().toISOString()};return Y.writeFileSync(Q.join(r,`${e}.json`),JSON.stringify(n,null,2)),n}removeSkill(e,t){let r=Q.join(this.projectSkillsDir(t),`${e}.json`);return Y.existsSync(r)?(Y.unlinkSync(r),!0):!1}listBundles(){return Kr}installBundle(e,t){let r=Kr.find(s=>s.id===e);if(!r)throw new Error(`Bundle "${e}" not found`);for(let s of r.skills)this.installSkill(s,t)}listMcps(e){let t=this.readJsonFiles(this.globalMcpsDir());return e?[...this.readJsonFiles(this.projectMcpsDir(e)),...t]:t}configureMcp(e){let t=this.projectMcpsDir(e.projectDir);Y.mkdirSync(t,{recursive:!0});let r={id:Xr(),name:e.name,command:e.command,args:e.args,env:e.env,enabled:!0};return Y.writeFileSync(Q.join(t,`${e.name}.json`),JSON.stringify(r,null,2)),r}};import{randomUUID as Yr}from"node:crypto";import{execSync as Vr}from"node:child_process";var Ke=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}create(e){let t=Yr(),r=new Date().toISOString();if(this.db.prepare(`INSERT INTO tasks (id, swarmId, workspaceId, title, description, assignedAgentId, useWorktree, status, approvalMode, createdAt, updatedAt)
88
+ VALUES (?, ?, ?, ?, ?, ?, 'idle', ?, ?, ?, ?, ?, ?)`).run(n,e,r,t.name,t.role,t.cli,t.autoApprove?1:0,t.systemPrompt??null,JSON.stringify(t.skills??[]),JSON.stringify(t.mcps??[]),t.workScope?JSON.stringify(t.workScope):null,s),this.rowToAgent({id:n,swarmId:e,index:r,name:t.name,role:t.role,cli:t.cli,status:"idle",autoApprove:t.autoApprove?1:0,systemPrompt:t.systemPrompt??null,skills:JSON.stringify(t.skills??[]),mcps:JSON.stringify(t.mcps??[]),workScope:t.workScope?JSON.stringify(t.workScope):null,worktreeBranch:null,worktreePath:null,createdAt:s})}async launch(e){let t=this.buildSwarm(e);if(!t)throw new Error(`Swarm ${e} not found`);let r=new Date().toISOString();this.db.prepare("UPDATE swarms SET status = 'active', launchedAt = ? WHERE id = ?").run(r,e);let s=K(t.directory,".swarm");de(K(s,"agents"),{recursive:!0}),de(K(s,"registry"),{recursive:!0}),de(K(s,"progress"),{recursive:!0});let n=this.settingsManager?.getEnvVarsForWorkspace(t.workspaceId)??{};for(let c of t.agents){this.db.prepare("UPDATE swarm_agents SET status = 'booting' WHERE id = ?").run(c.id);let l=this.buildSwarm(e),d=await this.agentSession.boot(c,l,this.terminalManager,Object.keys(n).length>0?n:void 0,this.worktreeManager),{terminalId:u,worktreePath:p,worktreeBranch:m}=d,h=this.agentTerminals.get(c.id)??[];h.push(u),this.agentTerminals.set(c.id,h),this.db.prepare("UPDATE swarm_agents SET status = 'running', worktreePath = ?, worktreeBranch = ? WHERE id = ?").run(p??null,m??null,c.id),this.consoleManager.addMessage({swarmId:e,agentId:c.id,agentName:c.name,agentRole:c.role,message:`Agent "${c.name}" (${c.role}) started on terminal ${u}`,source:"system"});let f=this.coordinatorLoops.get(e);if(f?.isRunning&&f.registerAgentTerminal(c.id,u,c),c.role==="coordinator"){let g=new We;g.start(c.id,e,this,this.terminalManager,this.broadcast,this.taskManager??void 0),this.coordinatorLoops.set(e,g);for(let w of t.agents){let E=this.agentTerminals.get(w.id)??[];for(let T of E)g.registerAgentTerminal(w.id,T,w)}}}let i=this.buildSwarm(e),o={swarmId:e,status:i.status,launchedAt:i.launchedAt,agents:i.agents.map(c=>({id:c.id,name:c.name,role:c.role,status:c.status}))};if(pa(K(s,"progress","status.json"),JSON.stringify(o,null,2)),this.taskManager){let c=this.taskManager.list({swarmId:e}),l=i.agents.filter(u=>u.role!=="coordinator"),d=0;for(let u of c)if(u.status==="todo"&&!u.assignedAgentId&&l.length>0){let p=l[d%l.length];this.taskManager.assign(u.id,p.id),d++}}this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"active"})}stop(e){let t=this.buildSwarm(e);if(!t)throw new Error(`Swarm ${e} not found`);let r=this.orchestrators.get(e);r&&(r.stop(),this.orchestrators.delete(e));let s=this.coordinatorLoops.get(e);s&&(s.stop(),this.coordinatorLoops.delete(e));for(let i of t.agents){let o=this.agentTerminals.get(i.id)??[];for(let c of o)this.terminalManager.close(c);this.agentTerminals.delete(i.id),this.db.prepare("UPDATE swarm_agents SET status = 'idle' WHERE id = ?").run(i.id)}if(t.useWorktrees&&t.directory)try{this.worktreeManager.removeAllForSwarm(t.directory,e)}catch(i){console.warn(`[WorktreeManager] Cleanup failed for swarm ${e}:`,i)}let n=new Date().toISOString();this.db.prepare("UPDATE swarms SET status = 'completed', stoppedAt = ? WHERE id = ?").run(n,e),this.consoleManager.addMessage({swarmId:e,message:"Swarm stopped",source:"system"}),this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"completed"})}pause(e){this.db.prepare("UPDATE swarms SET status = 'paused' WHERE id = ?").run(e),this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"paused"})}resume(e){this.db.prepare("UPDATE swarms SET status = 'active' WHERE id = ?").run(e),this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"active"})}list(e){return this.db.prepare("SELECT id FROM swarms WHERE workspaceId = ? ORDER BY createdAt DESC").all(e).map(r=>this.buildSwarm(r.id))}get(e){return this.db.prepare("SELECT id FROM swarms WHERE id = ?").get(e)?this.buildSwarm(e):null}delete(e){let t=this.get(e);return t&&t.status==="active"&&this.stop(e),this.db.prepare("DELETE FROM swarms WHERE id = ?").run(e).changes>0}message(e,t,r){if(t){let s=this.agentTerminals.get(t)??[];for(let n of s)this.terminalManager.write(n,r+"\r")}else{let s=this.buildSwarm(e);for(let n of s.agents){let i=this.agentTerminals.get(n.id)??[];for(let o of i)this.terminalManager.write(o,r+"\r")}}this.consoleManager.addMessage({swarmId:e,agentId:t,message:r,source:"user"})}addAgent(e){let t=new Date().toISOString(),s=(this.db.prepare('SELECT MAX("index") as maxIdx FROM swarm_agents WHERE swarmId = ?').get(e.swarmId)?.maxIdx??-1)+1;return this.insertAgent(e.swarmId,e.agent,s,t)}removeAgent(e){let t=this.agentTerminals.get(e.agentId)??[];for(let s of t)this.terminalManager.close(s);return this.agentTerminals.delete(e.agentId),this.db.prepare("DELETE FROM swarm_agents WHERE id = ? AND swarmId = ?").run(e.agentId,e.swarmId).changes>0}updateAgent(e){let{updates:t}=e,r=[],s=[];if(t.name!==void 0&&(r.push("name = ?"),s.push(t.name)),t.role!==void 0&&(r.push("role = ?"),s.push(t.role)),t.cli!==void 0&&(r.push("cli = ?"),s.push(t.cli)),t.autoApprove!==void 0&&(r.push("autoApprove = ?"),s.push(t.autoApprove?1:0)),t.systemPrompt!==void 0&&(r.push("systemPrompt = ?"),s.push(t.systemPrompt)),t.skills!==void 0&&(r.push("skills = ?"),s.push(JSON.stringify(t.skills))),t.mcps!==void 0&&(r.push("mcps = ?"),s.push(JSON.stringify(t.mcps))),t.workScope!==void 0&&(r.push("workScope = ?"),s.push(JSON.stringify(t.workScope))),r.length===0)return null;s.push(e.agentId,e.swarmId),this.db.prepare(`UPDATE swarm_agents SET ${r.join(", ")} WHERE id = ? AND swarmId = ?`).run(...s);let n=this.db.prepare("SELECT * FROM swarm_agents WHERE id = ?").get(e.agentId);return n?this.rowToAgent(n):null}getStats(e){let t=this.getAgents(e),r=t.filter(c=>c.status==="running"||c.status==="booting").length,s=t.filter(c=>c.status==="done").length,n=t.filter(c=>c.status==="error").length,i=this.db.prepare("SELECT launchedAt FROM swarms WHERE id = ?").get(e),o=0;return i?.launchedAt&&(o=Date.now()-new Date(i.launchedAt).getTime()),{activeAgents:r,completedTasks:s,errors:n,escalations:0,reviewsPending:0,elapsedTime:o}}setTopology(e,t){this.topologies.set(e,t),this.db.prepare("UPDATE swarms SET knowledge = json_set(knowledge, '$.topology', ?) WHERE id = ?").run(JSON.stringify(t),e)}launchOrchestrated(e){let t=this.buildSwarm(e);if(!t)throw new Error(`Swarm ${e} not found`);let r=new Date().toISOString();this.db.prepare("UPDATE swarms SET status = 'active', launchedAt = ? WHERE id = ?").run(r,e);let s=K(t.directory,".swarm");de(K(s,"agents"),{recursive:!0}),de(K(s,"registry"),{recursive:!0}),de(K(s,"progress"),{recursive:!0});let n=this.settingsManager?.getEnvVarsForWorkspace(t.workspaceId)??{},i=this.topologies.get(e)??t.topology,o=this.settingsManager?.get("providers.claude_binary_path")?.value??this.providerRegistry?.getClaudeBinaryPath()??"claude",c=new Be({swarm:t,topology:i,claudeBinaryPath:o,env:Object.keys(n).length>0?n:void 0,onAgentOutput:l=>{this.broadcast(`orchestrator.agent.output.${e}`,l),this.consoleManager.addMessage({swarmId:e,agentId:l.agentId,agentName:l.agentName,message:`[${l.type}] ${l.content.slice(0,500)}`,source:"agent"})},onCLISpawned:l=>{this.broadcast(`orchestrator.cli.spawned.${e}`,l),this.consoleManager.addMessage({swarmId:e,agentId:l.agentId,message:`Spawned ${l.cli} CLI: ${l.prompt.slice(0,200)}`,source:"system"})},onCLICompleted:l=>{this.broadcast(`orchestrator.cli.completed.${e}`,l)},onEscalation:l=>{this.broadcast(`orchestrator.escalation.${e}`,l),this.broadcast(`swarm.escalation.${e}`,{swarmId:e,agentId:l.escalation.agentId,agentName:l.escalation.agentName,message:l.escalation.reason,requiresResponse:!0,escalation:l.escalation})},onAgentCompleted:l=>{this.broadcast(`swarm.agent.status.${e}`,{swarmId:e,agentId:l.agentId,status:l.error?"error":"done"}),this.db.prepare("UPDATE swarm_agents SET status = ? WHERE id = ?").run(l.error?"error":"done",l.agentId)},onSwarmCompleted:l=>{this.db.prepare("UPDATE swarms SET status = 'completed', stoppedAt = ? WHERE id = ?").run(new Date().toISOString(),e),this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"completed"}),this.consoleManager.addMessage({swarmId:e,message:"Swarm orchestration completed",source:"system"}),this.orchestrators.delete(e)}});this.orchestrators.set(e,c);for(let l of t.agents)this.db.prepare("UPDATE swarm_agents SET status = 'running' WHERE id = ?").run(l.id);this.consoleManager.addMessage({swarmId:e,message:`Swarm "${t.name}" launched in orchestrated mode with ${t.agents.length} agents`,source:"system"}),this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"active"}),c.start().catch(l=>{console.error(`[AgentOrchestrator] Swarm ${e} failed:`,l),this.db.prepare("UPDATE swarms SET status = 'error', stoppedAt = ? WHERE id = ?").run(new Date().toISOString(),e),this.broadcast(`swarm.status.${e}`,{swarmId:e,status:"error"})})}async spawnCLI(e,t,r){let s=this.orchestrators.get(e);if(!s)throw new Error(`No active orchestrator for swarm ${e}`);return{sessionId:await s.getCLIProvider().spawn(t,r)}}respondToEscalation(e,t){for(let r of this.orchestrators.values())r.respondToEscalation(e,t)}getOrchestrator(e){return this.orchestrators.get(e)}getAgents(e){return this.db.prepare('SELECT * FROM swarm_agents WHERE swarmId = ? ORDER BY "index" ASC').all(e).map(r=>this.rowToAgent(r))}buildSwarm(e){let t=this.db.prepare("SELECT * FROM swarms WHERE id = ?").get(e);if(!t)throw new Error(`Swarm ${e} not found`);let r=this.getAgents(e),s=this.getStats(e);return{id:t.id,workspaceId:t.workspaceId,name:t.name,mission:t.mission,directory:t.directory,knowledge:JSON.parse(t.knowledge),agents:r,status:t.status,presetSize:t.presetSize??void 0,cliForAll:t.cliForAll??void 0,autoApprove:t.autoApprove===1,useWorktrees:t.useWorktrees===1,stats:s,createdAt:t.createdAt,launchedAt:t.launchedAt??void 0,stoppedAt:t.stoppedAt??void 0}}rowToAgent(e){let t=this.agentTerminals.get(e.id)??[];return{id:e.id,swarmId:e.swarmId,index:e.index,name:e.name,role:e.role,cli:e.cli,status:e.status,autoApprove:e.autoApprove===1,terminalIds:t,systemPrompt:e.systemPrompt??void 0,skills:JSON.parse(e.skills),mcps:JSON.parse(e.mcps),workScope:e.workScope?JSON.parse(e.workScope):void 0,worktreeBranch:e.worktreeBranch??void 0,worktreePath:e.worktreePath??void 0,elapsedTime:0}}};import{randomUUID as Xr}from"node:crypto";import Y from"node:fs";import Q from"node:path";import jr from"node:os";var Gr={"frontend-design":{description:"Frontend design patterns and best practices"},shadcn:{description:"shadcn/ui component library integration"},"next-best-practices":{description:"Next.js best practices and patterns"},"systematic-debugging":{description:"Systematic debugging methodology"},"web-design-guidelines":{description:"Web design guidelines and principles"},"vercel-react-best-practices":{description:"Vercel + React best practices"},"supabase-postgres-best-practices":{description:"Supabase + Postgres best practices"},"expo-tailwind-setup":{description:"Expo + Tailwind CSS setup guide"},"nodejs-backend-patterns":{description:"Node.js backend architecture patterns"},"api-design-principles":{description:"API design principles and REST patterns"},"database-schema-design":{description:"Database schema design best practices"},"better-auth":{description:"Authentication best practices with Better Auth"},"skill-creator":{description:"Create custom skills for agents"},"building-native-ui":{description:"Building native UI components"},"expo-deployment":{description:"Expo deployment and distribution"}},Kr=[{id:"nextjs-convex-clerk",name:"Next.js + Convex + Clerk",description:"Full-stack Next.js with Convex backend and Clerk auth",skills:["next-best-practices","frontend-design","shadcn","better-auth"],mcps:[],stack:"nextjs"},{id:"react-native-expo",name:"React Native + Expo",description:"Mobile development with React Native and Expo",skills:["expo-tailwind-setup","expo-deployment","building-native-ui"],mcps:[],stack:"mobile"},{id:"fullstack-supabase",name:"Full Stack Supabase",description:"Full-stack app with Supabase backend and Postgres",skills:["supabase-postgres-best-practices","database-schema-design","api-design-principles","better-auth"],mcps:[],stack:"supabase"},{id:"vibe-coding",name:"Vibe Coding",description:"Generic vibe coding setup for rapid prototyping",skills:["frontend-design","web-design-guidelines","systematic-debugging","shadcn"],mcps:[],stack:"generic"},{id:"api-nodejs",name:"API + Node.js",description:"Backend API development with Node.js",skills:["nodejs-backend-patterns","api-design-principles","database-schema-design","systematic-debugging"],mcps:[],stack:"backend"}],Ge=class{projectSkillsDir(e){return Q.join(e,".swarm","registry","skills")}projectMcpsDir(e){return Q.join(e,".swarm","registry","mcps")}globalSkillsDir(){return Q.join(jr.homedir(),".swarm","registry","skills")}globalMcpsDir(){return Q.join(jr.homedir(),".swarm","registry","mcps")}readJsonFiles(e){return Y.existsSync(e)?Y.readdirSync(e).filter(r=>r.endsWith(".json")).map(r=>JSON.parse(Y.readFileSync(Q.join(e,r),"utf-8"))):[]}listSkills(e){let t=this.readJsonFiles(this.globalSkillsDir());return e?[...this.readJsonFiles(this.projectSkillsDir(e)),...t]:t}searchSkills(e){let t=e.toLowerCase();return Object.entries(Gr).filter(([r,s])=>r.includes(t)||s.description.toLowerCase().includes(t)).map(([r,s])=>({name:r,description:s.description,source:"skills.sh"}))}installSkill(e,t){let r=this.projectSkillsDir(t);Y.mkdirSync(r,{recursive:!0});let s=Gr[e],n={id:Xr(),name:e,description:s?.description??`Custom skill: ${e}`,source:s?"skills.sh":"custom",installedAt:new Date().toISOString()};return Y.writeFileSync(Q.join(r,`${e}.json`),JSON.stringify(n,null,2)),n}removeSkill(e,t){let r=Q.join(this.projectSkillsDir(t),`${e}.json`);return Y.existsSync(r)?(Y.unlinkSync(r),!0):!1}listBundles(){return Kr}installBundle(e,t){let r=Kr.find(s=>s.id===e);if(!r)throw new Error(`Bundle "${e}" not found`);for(let s of r.skills)this.installSkill(s,t)}listMcps(e){let t=this.readJsonFiles(this.globalMcpsDir());return e?[...this.readJsonFiles(this.projectMcpsDir(e)),...t]:t}configureMcp(e){let t=this.projectMcpsDir(e.projectDir);Y.mkdirSync(t,{recursive:!0});let r={id:Xr(),name:e.name,command:e.command,args:e.args,env:e.env,enabled:!0};return Y.writeFileSync(Q.join(t,`${e.name}.json`),JSON.stringify(r,null,2)),r}};import{randomUUID as Yr}from"node:crypto";import{execSync as Vr}from"node:child_process";var Ke=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}create(e){let t=Yr(),r=new Date().toISOString();if(this.db.prepare(`INSERT INTO tasks (id, swarmId, workspaceId, title, description, assignedAgentId, useWorktree, status, approvalMode, createdAt, updatedAt)
89
89
  VALUES (?, ?, ?, ?, ?, ?, ?, 'todo', ?, ?, ?)`).run(t,e.swarmId??null,e.workspaceId,e.title,e.description??"",e.assignedAgentId??null,e.useWorktree?1:0,e.approvalMode??"auto",r,r),e.attachments&&e.attachments.length>0){let n=this.db.prepare(`INSERT INTO task_attachments (id, taskId, type, data, width, height, label, createdAt)
90
90
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let i of e.attachments)n.run(Yr(),t,i.type,i.data,i.width,i.height,i.label??null,r)}if(e.dependencies&&e.dependencies.length>0){let n=this.db.prepare("INSERT INTO task_dependencies (taskId, dependsOnTaskId) VALUES (?, ?)");for(let i of e.dependencies)n.run(t,i)}let s=this.getById(t);return this.broadcast("task.created",{task:s}),s}update(e,t){let r=[],s=[];if(t.title!==void 0&&(r.push("title = ?"),s.push(t.title)),t.description!==void 0&&(r.push("description = ?"),s.push(t.description)),t.assignedAgentId!==void 0&&(r.push("assignedAgentId = ?"),s.push(t.assignedAgentId)),t.useWorktree!==void 0&&(r.push("useWorktree = ?"),s.push(t.useWorktree?1:0)),t.approvalMode!==void 0&&(r.push("approvalMode = ?"),s.push(t.approvalMode)),t.output!==void 0&&(r.push("output = ?"),s.push(t.output)),t.filesChanged!==void 0&&(r.push("filesChanged = ?"),s.push(JSON.stringify(t.filesChanged))),r.length===0)return this.getById(e);let n=new Date().toISOString();r.push("updatedAt = ?"),s.push(n),s.push(e),this.db.prepare(`UPDATE tasks SET ${r.join(", ")} WHERE id = ?`).run(...s);let i=this.getById(e);return this.broadcast("task.updated",{task:i}),i}get(e){return this.getById(e)}delete(e){return this.db.prepare("DELETE FROM tasks WHERE id = ?").run(e).changes>0}list(e){let t="SELECT * FROM tasks WHERE 1=1",r=[];return e.workspaceId&&(t+=" AND workspaceId = ?",r.push(e.workspaceId)),e.swarmId&&(t+=" AND swarmId = ?",r.push(e.swarmId)),t+=" ORDER BY createdAt ASC",this.db.prepare(t).all(...r).map(n=>this.rowToTask(n))}move(e,t){if(t==="running"&&!this.checkDependencies(e))throw new Error(`Task ${e} is blocked by unfinished dependencies`);let r=this.getById(e);if(!r)throw new Error(`Task ${e} not found`);let s=r.status,n=new Date().toISOString();if(t==="running"&&r.useWorktree&&r.swarmId){let o=this.getSwarmDirectory(r.swarmId);if(o){let c=`.swarm/worktrees/${r.id}`;try{Vr(`git worktree add ${c} -b swarm/${r.id}`,{cwd:o,stdio:"pipe"}),this.db.prepare("UPDATE tasks SET worktreePath = ?, status = ?, updatedAt = ? WHERE id = ?").run(c,t,n,e);let l=this.getById(e);return this.broadcast("task.moved",{taskId:e,from:s,to:t}),l}catch{}}}if(t==="done"&&r.worktreePath&&r.swarmId){let o=this.getSwarmDirectory(r.swarmId);if(o)try{Vr(`git worktree remove ${r.worktreePath}`,{cwd:o,stdio:"pipe"})}catch{}}this.db.prepare("UPDATE tasks SET status = ?, updatedAt = ? WHERE id = ?").run(t,n,e);let i=this.getById(e);return this.broadcast("task.moved",{taskId:e,from:s,to:t}),i}getSwarmDirectory(e){return this.db.prepare("SELECT directory FROM swarms WHERE id = ?").get(e)?.directory??null}updateTerminalId(e,t){let r=new Date().toISOString();this.db.prepare("UPDATE tasks SET terminalId = ?, updatedAt = ? WHERE id = ?").run(t,r,e)}assign(e,t){let r=new Date().toISOString();this.db.prepare("UPDATE tasks SET assignedAgentId = ?, updatedAt = ? WHERE id = ?").run(t,r,e);let s=this.getById(e);return this.broadcast("task.assigned",{taskId:e,agentId:t}),s}complete(e,t,r){let s=new Date().toISOString();this.db.prepare("UPDATE tasks SET status = 'done', output = ?, filesChanged = ?, updatedAt = ?, completedAt = ? WHERE id = ?").run(t??null,JSON.stringify(r??[]),s,s,e);let n=this.getById(e);return this.broadcast("task.completed",{task:n}),n}checkDependencies(e){let t=this.getBlockedBy(e);if(t.length===0)return!0;for(let r of t){let s=this.getById(r);if(!s||s.status!=="done")return!1}return!0}getBlockedBy(e){return this.db.prepare("SELECT dependsOnTaskId FROM task_dependencies WHERE taskId = ?").all(e).map(r=>r.dependsOnTaskId)}getById(e){let t=this.db.prepare("SELECT * FROM tasks WHERE id = ?").get(e);return t?this.rowToTask(t):null}getAttachments(e){return this.db.prepare("SELECT * FROM task_attachments WHERE taskId = ?").all(e).map(r=>({id:r.id,type:r.type,data:r.data,width:r.width,height:r.height,label:r.label??void 0,createdAt:r.createdAt}))}rowToTask(e){let t=this.getDependencies(e.id),r=this.getAllTerminalIds(e.id),s=this.getAttachments(e.id);return{id:e.id,swarmId:e.swarmId??void 0,workspaceId:e.workspaceId,title:e.title,description:e.description,dependencies:t,assignedAgentId:e.assignedAgentId??void 0,useWorktree:e.useWorktree===1,worktreePath:e.worktreePath??void 0,status:e.status,approvalMode:e.approvalMode,terminalId:e.terminalId??void 0,terminalIds:r,createdAt:e.createdAt,updatedAt:e.updatedAt,completedAt:e.completedAt??void 0,output:e.output??void 0,filesChanged:JSON.parse(e.filesChanged),attachments:s.length>0?s:void 0}}getDependencies(e){return this.db.prepare("SELECT dependsOnTaskId FROM task_dependencies WHERE taskId = ?").all(e).map(r=>r.dependsOnTaskId)}getTerminalIds(e){return this.db.prepare("SELECT terminalId FROM task_terminals WHERE taskId = ? AND status = 'running'").all(e).map(r=>r.terminalId)}getAllTerminalIds(e){return this.db.prepare("SELECT terminalId FROM task_terminals WHERE taskId = ?").all(e).map(r=>r.terminalId)}addTerminal(e,t,r,s,n){let i=new Date().toISOString();this.db.prepare(`INSERT INTO task_terminals (taskId, terminalId, cli, prompt, autoApprove, status, startedAt)
91
- VALUES (?, ?, ?, ?, ?, 'running', ?)`).run(e,t,r,s,n?1:0,i)}getTaskTerminals(e){return this.db.prepare("SELECT * FROM task_terminals WHERE taskId = ?").all(e).map(r=>({taskId:r.taskId,terminalId:r.terminalId,cli:r.cli,prompt:r.prompt,autoApprove:r.autoApprove===1,status:r.status,exitCode:r.exitCode??void 0,startedAt:r.startedAt,exitedAt:r.exitedAt??void 0}))}getTaskByTerminalId(e){let t=this.db.prepare("SELECT taskId FROM task_terminals WHERE terminalId = ?").get(e);return t?this.getById(t.taskId):null}markTerminalExited(e,t,r){let s=new Date().toISOString(),n=r===0?"exited":"error";this.db.prepare("UPDATE task_terminals SET status = ?, exitCode = ?, exitedAt = ? WHERE taskId = ? AND terminalId = ?").run(n,r,s,e,t);let o=this.db.prepare("SELECT COUNT(*) as cnt FROM task_terminals WHERE taskId = ? AND status = 'running'").get(e).cnt===0,c=!1;return o&&(c=this.db.prepare("SELECT COUNT(*) as cnt FROM task_terminals WHERE taskId = ? AND status = 'error'").get(e).cnt>0),{allDone:o,hasError:c}}removeTaskTerminals(e){this.db.prepare("DELETE FROM task_terminals WHERE taskId = ?").run(e)}};import{execSync as Xt}from"node:child_process";var zr={id:"claude",name:"Claude Code",command:"claude",buildCommand({mission:a,autoApprove:e,claudeMdPath:t}){let r=a.replace(/'/g,"'\\''"),s=["claude"];return e&&s.push("--dangerously-skip-permissions"),t&&s.push(`--project ${t}`),s.push(`'${r}'`),s.join(" ")}};var Jr={id:"codex",name:"Codex",command:"codex",buildCommand({mission:a,autoApprove:e}){let t=a.replace(/'/g,"'\\''"),r=["codex"];return e&&r.push("--full-auto"),r.push(`'${t}'`),r.join(" ")}};var Qr={id:"gemini",name:"Gemini",command:"gemini",buildCommand({mission:a}){return`gemini '${a.replace(/'/g,"'\\''")}'`}};var Zr={id:"opencode",name:"OpenCode",command:"opencode",buildCommand(){return"opencode"}};var es={id:"cursor",name:"Cursor",command:"cursor",buildCommand(){return"cursor"}};var Ye=class{providers=new Map;constructor(){this.register(zr),this.register(Jr),this.register(Qr),this.register(Zr),this.register(es)}register(e){this.providers.set(e.id,e)}get(e){return this.providers.get(e)}listRegistered(){return Array.from(this.providers.keys())}async detectInstalled(){let e=[];for(let[t,r]of this.providers)try{let s=Xt(`which ${r.command}`,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim(),n={cli:t,installed:!0,path:s};t==="claude"&&(n.authenticated=this.checkClaudeAuth(s)),e.push(n)}catch{e.push({cli:t,installed:!1})}return e}checkClaudeAuth(e="claude"){try{let r=Xt(`${e} auth status`,{encoding:"utf8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).toLowerCase();return!r.includes("not logged in")&&!r.includes("login required")}catch{return!1}}getClaudeBinaryPath(e){if(e&&e!=="claude")return e;try{return Xt("which claude",{encoding:"utf8"}).trim()}catch{return"claude"}}};import{randomUUID as as}from"node:crypto";import{mkdirSync as ma,writeFileSync as Je}from"node:fs";import{join as ye}from"node:path";var Ve=[{id:"nextjs",name:"Next.js",category:"frontend"},{id:"react",name:"React",category:"frontend"},{id:"react-native",name:"React Native",category:"frontend"},{id:"expo",name:"Expo",category:"frontend"},{id:"vite",name:"Vite",category:"frontend"},{id:"nodejs",name:"Node.js",category:"backend"},{id:"express",name:"Express",category:"backend"},{id:"fastify",name:"Fastify",category:"backend"},{id:"clerk",name:"Clerk",category:"auth",requiredEnvVars:["CLERK_PUBLISHABLE_KEY","CLERK_SECRET_KEY"]},{id:"better-auth",name:"Better Auth",category:"auth"},{id:"convex",name:"Convex",category:"database",requiredEnvVars:["CONVEX_DEPLOYMENT_URL"]},{id:"supabase",name:"Supabase",category:"database",requiredEnvVars:["SUPABASE_URL","SUPABASE_ANON_KEY"]},{id:"prisma",name:"Prisma",category:"database"},{id:"drizzle",name:"Drizzle",category:"database"},{id:"stripe",name:"Stripe",category:"other",requiredEnvVars:["STRIPE_SECRET_KEY","STRIPE_WEBHOOK_SECRET"]},{id:"vercel",name:"Vercel",category:"deployment",requiredEnvVars:["VERCEL_TOKEN"]},{id:"tailwind",name:"Tailwind CSS",category:"frontend"},{id:"shadcn",name:"shadcn/ui",category:"frontend"}];var Se=[{provider:"anthropic",envVar:"ANTHROPIC_API_KEY",label:"Anthropic API Key",required:!1,docsUrl:"https://console.anthropic.com/settings/keys",settingKey:"api_key.anthropic",description:"Optional \u2014 if not set, the system uses the Claude CLI's existing authentication (claude auth login)"},{provider:"openai",envVar:"OPENAI_API_KEY",label:"OpenAI API Key",required:!1,docsUrl:"https://platform.openai.com/api-keys",settingKey:"api_key.openai"},{provider:"google",envVar:"GOOGLE_API_KEY",label:"Google API Key",required:!1,docsUrl:"https://aistudio.google.com/apikey",settingKey:"api_key.google"},{provider:"clerk",envVar:"CLERK_SECRET_KEY",label:"Clerk Secret Key",required:!1,docsUrl:"https://dashboard.clerk.com",settingKey:"api_key.clerk"},{provider:"convex",envVar:"CONVEX_DEPLOYMENT_URL",label:"Convex Deployment URL",required:!1,docsUrl:"https://dashboard.convex.dev",settingKey:"api_key.convex"},{provider:"supabase",envVar:"SUPABASE_ANON_KEY",label:"Supabase Anon Key",required:!1,docsUrl:"https://supabase.com/dashboard",settingKey:"api_key.supabase"},{provider:"stripe",envVar:"STRIPE_SECRET_KEY",label:"Stripe Secret Key",required:!1,docsUrl:"https://dashboard.stripe.com/apikeys",settingKey:"api_key.stripe"},{provider:"vercel",envVar:"VERCEL_TOKEN",label:"Vercel Token",required:!1,docsUrl:"https://vercel.com/account/tokens",settingKey:"api_key.vercel"},{provider:"cloudflare",envVar:"CF_TUNNEL_TOKEN",label:"Cloudflare Tunnel Token",required:!1,docsUrl:"https://dash.cloudflare.com",settingKey:"api_key.cloudflare"}],ts=[{key:"general.theme",value:"system",category:"general",label:"Tema",description:"Aparencia do app (system/dark/light)"},{key:"general.default_cli",value:"claude",category:"general",label:"CLI Padrao",description:"CLI agent padrao para novos swarms"},{key:"general.auto_approve",value:"false",category:"general",label:"Auto-Approve",description:"Pular confirmacoes de permissao por padrao"},{key:"general.language",value:"pt",category:"general",label:"Idioma",description:"Idioma da interface (pt/en)"},{key:"providers.claude_binary_path",value:"claude",category:"providers",label:"Claude CLI Path",description:"Caminho para o binario do Claude CLI (usado para autenticacao via Agent SDK)"},{key:"general.notification_sound",value:"true",category:"general",label:"Som de Notificacao",description:"Tocar som quando um terminal precisa de atencao (pergunta ou tarefa concluida)"},{key:"advanced.server_port",value:"7773",category:"advanced",label:"Porta do Servidor",description:"Porta HTTP/WebSocket do servidor"}];var rs=[{name:"Claude Code",category:"ai_coding",command:"claude",healthCommand:"claude --version",healthSuccessKeywords:["claude"],versionCommand:"claude --version",authCommand:"claude auth status",authSuccessKeywords:["logged in","authenticated","isloggedin"],docsUrl:"https://docs.anthropic.com/en/docs/claude-code",enabled:!0,isBuiltIn:!0},{name:"Codex",category:"ai_coding",command:"codex",healthCommand:"codex --version",healthSuccessKeywords:["codex"],versionCommand:"codex --version",authCommand:"codex login status",authSuccessKeywords:["logged in"],docsUrl:"https://github.com/openai/codex",enabled:!0,isBuiltIn:!0},{name:"Gemini CLI",category:"ai_coding",command:"gemini",healthCommand:"gemini --version 2>&1",healthSuccessKeywords:["0.","1.","2."],versionCommand:"gemini --version",authCommand:"gemini --prompt exit 2>&1",authSuccessKeywords:["cached credentials","signed in with google"],docsUrl:"https://github.com/google-gemini/gemini-cli",enabled:!0,isBuiltIn:!0},{name:"OpenCode",category:"ai_coding",command:"opencode",healthCommand:"opencode --version",healthSuccessKeywords:["opencode"],versionCommand:"opencode --version",enabled:!0,isBuiltIn:!0},{name:"Cursor",category:"ai_coding",command:"cursor",healthCommand:"cursor --version",healthSuccessKeywords:["0.","1.","2.","3."],versionCommand:"cursor --version",docsUrl:"https://docs.cursor.com",enabled:!0,isBuiltIn:!0}];function jt(a){let e=a.split(".").pop()?.toLowerCase()||"";return{ts:"typescript",tsx:"typescript",js:"javascript",jsx:"javascript",mjs:"javascript",py:"python",html:"html",htm:"html",css:"css",scss:"css",json:"json",md:"markdown",yaml:"yaml",yml:"yaml",rs:"rust",go:"go",sh:"shell",bash:"shell",zsh:"shell",sql:"sql",toml:"toml",xml:"xml",svg:"svg",c:"c",cpp:"cpp",h:"c",hpp:"cpp",java:"java",rb:"ruby",php:"php",swift:"swift",kt:"kotlin",lua:"lua",r:"r",dockerfile:"dockerfile",vue:"vue",svelte:"svelte",png:"image",jpg:"image",jpeg:"image",gif:"image",webp:"image",ico:"image",bmp:"image",tiff:"image",tif:"image",csv:"csv",tsv:"tsv",pdf:"pdf",mp3:"audio",wav:"audio",ogg:"audio",flac:"audio",aac:"audio",m4a:"audio",mp4:"video",webm:"video",mov:"video",avi:"video",mkv:"video",zip:"archive",tar:"archive",gz:"archive",bz2:"archive","7z":"archive",rar:"archive",woff:"font",woff2:"font",ttf:"font",eot:"font",otf:"font",env:"shell"}[e]||"text"}function Gt(a){let e=a.split(".").pop()?.toLowerCase()||"";return{png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",ico:"image/x-icon",bmp:"image/bmp",tiff:"image/tiff",tif:"image/tiff",svg:"image/svg+xml",pdf:"application/pdf",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",flac:"audio/flac",aac:"audio/aac",m4a:"audio/mp4",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",csv:"text/csv",tsv:"text/tab-separated-values"}[e]}function Kt(a){let e=jt(a);return["image","pdf","audio","video","archive","font"].includes(e)}var Yt=[{id:"cursor",label:"Cursor",command:"cursor"},{id:"vscode",label:"VS Code",command:"code"},{id:"vscode-insiders",label:"VS Code Insiders",command:"code-insiders"},{id:"vscodium",label:"VSCodium",command:"codium"},{id:"zed",label:"Zed",command:"zed"},{id:"windsurf",label:"Windsurf",command:"windsurf"},{id:"fleet",label:"Fleet",command:"fleet"},{id:"sublime",label:"Sublime Text",command:"subl"},{id:"terminal",label:"Terminal",command:null},{id:"finder",label:"Finder",command:null}];var ss={engine:"Qual motor de PRD voce gostaria de usar? (impactus-native / bmad / aiox / custom)",overview:"Descreva seu projeto em 2-3 frases. O que ele faz? Qual problema resolve?",features:"Liste as funcionalidades principais do seu projeto (uma por linha):",stack:"Selecione as tecnologias que serao usadas no projeto. (Use o seletor de stack no frontend)",screens:"Descreva as telas principais do seu aplicativo (nome e breve descricao de cada uma):",review:"",done:"PRD gerado com sucesso! Os arquivos foram salvos no diretorio .swarm/prd/"};function pe(a,e){return a==="review"&&e?pa(e):ss[a]}function ze(a){let e=["engine","overview","features","stack","screens","review","done"],t=e.indexOf(a);return t===-1||t===e.length-1?"done":e[t+1]}function pa(a){let e=ue(a,"overview"),t=ue(a,"features"),r=ue(a,"screens"),s=a.stack.map(n=>Ve.find(i=>i.id===n)?.name??n).join(", ");return["--- Resumo do PRD ---","",`**Visao Geral:** ${e||"(nao informado)"}`,"","**Funcionalidades:**",t||"(nao informado)","",`**Stack:** ${s||"(nao selecionado)"}`,"","**Telas:**",r||"(nao informado)","","Tudo certo? Digite 'sim' para gerar o PRD ou descreva o que deseja alterar."].join(`
91
+ VALUES (?, ?, ?, ?, ?, 'running', ?)`).run(e,t,r,s,n?1:0,i)}getTaskTerminals(e){return this.db.prepare("SELECT * FROM task_terminals WHERE taskId = ?").all(e).map(r=>({taskId:r.taskId,terminalId:r.terminalId,cli:r.cli,prompt:r.prompt,autoApprove:r.autoApprove===1,status:r.status,exitCode:r.exitCode??void 0,startedAt:r.startedAt,exitedAt:r.exitedAt??void 0}))}getTaskByTerminalId(e){let t=this.db.prepare("SELECT taskId FROM task_terminals WHERE terminalId = ?").get(e);return t?this.getById(t.taskId):null}markTerminalExited(e,t,r){let s=new Date().toISOString(),n=r===0?"exited":"error";this.db.prepare("UPDATE task_terminals SET status = ?, exitCode = ?, exitedAt = ? WHERE taskId = ? AND terminalId = ?").run(n,r,s,e,t);let o=this.db.prepare("SELECT COUNT(*) as cnt FROM task_terminals WHERE taskId = ? AND status = 'running'").get(e).cnt===0,c=!1;return o&&(c=this.db.prepare("SELECT COUNT(*) as cnt FROM task_terminals WHERE taskId = ? AND status = 'error'").get(e).cnt>0),{allDone:o,hasError:c}}removeTaskTerminals(e){this.db.prepare("DELETE FROM task_terminals WHERE taskId = ?").run(e)}};import{execSync as Xt}from"node:child_process";var zr={id:"claude",name:"Claude Code",command:"claude",buildCommand({mission:a,autoApprove:e,claudeMdPath:t}){let r=a.replace(/'/g,"'\\''"),s=["claude"];return e&&s.push("--dangerously-skip-permissions"),t&&s.push(`--project ${t}`),s.push(`'${r}'`),s.join(" ")}};var Jr={id:"codex",name:"Codex",command:"codex",buildCommand({mission:a,autoApprove:e}){let t=a.replace(/'/g,"'\\''"),r=["codex"];return e&&r.push("--full-auto"),r.push(`'${t}'`),r.join(" ")}};var Qr={id:"gemini",name:"Gemini",command:"gemini",buildCommand({mission:a}){return`gemini '${a.replace(/'/g,"'\\''")}'`}};var Zr={id:"opencode",name:"OpenCode",command:"opencode",buildCommand(){return"opencode"}};var es={id:"cursor",name:"Cursor",command:"cursor",buildCommand(){return"cursor"}};var Ye=class{providers=new Map;constructor(){this.register(zr),this.register(Jr),this.register(Qr),this.register(Zr),this.register(es)}register(e){this.providers.set(e.id,e)}get(e){return this.providers.get(e)}listRegistered(){return Array.from(this.providers.keys())}async detectInstalled(){let e=[];for(let[t,r]of this.providers)try{let s=Xt(`which ${r.command}`,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim(),n={cli:t,installed:!0,path:s};t==="claude"&&(n.authenticated=this.checkClaudeAuth(s)),e.push(n)}catch{e.push({cli:t,installed:!1})}return e}checkClaudeAuth(e="claude"){try{let r=Xt(`${e} auth status`,{encoding:"utf8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).toLowerCase();return!r.includes("not logged in")&&!r.includes("login required")}catch{return!1}}getClaudeBinaryPath(e){if(e&&e!=="claude")return e;try{return Xt("which claude",{encoding:"utf8"}).trim()}catch{return"claude"}}};import{randomUUID as as}from"node:crypto";import{mkdirSync as ga,writeFileSync as Je}from"node:fs";import{join as ye}from"node:path";var Ve=[{id:"nextjs",name:"Next.js",category:"frontend"},{id:"react",name:"React",category:"frontend"},{id:"react-native",name:"React Native",category:"frontend"},{id:"expo",name:"Expo",category:"frontend"},{id:"vite",name:"Vite",category:"frontend"},{id:"nodejs",name:"Node.js",category:"backend"},{id:"express",name:"Express",category:"backend"},{id:"fastify",name:"Fastify",category:"backend"},{id:"clerk",name:"Clerk",category:"auth",requiredEnvVars:["CLERK_PUBLISHABLE_KEY","CLERK_SECRET_KEY"]},{id:"better-auth",name:"Better Auth",category:"auth"},{id:"convex",name:"Convex",category:"database",requiredEnvVars:["CONVEX_DEPLOYMENT_URL"]},{id:"supabase",name:"Supabase",category:"database",requiredEnvVars:["SUPABASE_URL","SUPABASE_ANON_KEY"]},{id:"prisma",name:"Prisma",category:"database"},{id:"drizzle",name:"Drizzle",category:"database"},{id:"stripe",name:"Stripe",category:"other",requiredEnvVars:["STRIPE_SECRET_KEY","STRIPE_WEBHOOK_SECRET"]},{id:"vercel",name:"Vercel",category:"deployment",requiredEnvVars:["VERCEL_TOKEN"]},{id:"tailwind",name:"Tailwind CSS",category:"frontend"},{id:"shadcn",name:"shadcn/ui",category:"frontend"}];var Se=[{provider:"anthropic",envVar:"ANTHROPIC_API_KEY",label:"Anthropic API Key",required:!1,docsUrl:"https://console.anthropic.com/settings/keys",settingKey:"api_key.anthropic",description:"Optional \u2014 if not set, the system uses the Claude CLI's existing authentication (claude auth login)"},{provider:"openai",envVar:"OPENAI_API_KEY",label:"OpenAI API Key",required:!1,docsUrl:"https://platform.openai.com/api-keys",settingKey:"api_key.openai"},{provider:"google",envVar:"GOOGLE_API_KEY",label:"Google API Key",required:!1,docsUrl:"https://aistudio.google.com/apikey",settingKey:"api_key.google"},{provider:"clerk",envVar:"CLERK_SECRET_KEY",label:"Clerk Secret Key",required:!1,docsUrl:"https://dashboard.clerk.com",settingKey:"api_key.clerk"},{provider:"convex",envVar:"CONVEX_DEPLOYMENT_URL",label:"Convex Deployment URL",required:!1,docsUrl:"https://dashboard.convex.dev",settingKey:"api_key.convex"},{provider:"supabase",envVar:"SUPABASE_ANON_KEY",label:"Supabase Anon Key",required:!1,docsUrl:"https://supabase.com/dashboard",settingKey:"api_key.supabase"},{provider:"stripe",envVar:"STRIPE_SECRET_KEY",label:"Stripe Secret Key",required:!1,docsUrl:"https://dashboard.stripe.com/apikeys",settingKey:"api_key.stripe"},{provider:"vercel",envVar:"VERCEL_TOKEN",label:"Vercel Token",required:!1,docsUrl:"https://vercel.com/account/tokens",settingKey:"api_key.vercel"},{provider:"cloudflare",envVar:"CF_TUNNEL_TOKEN",label:"Cloudflare Tunnel Token",required:!1,docsUrl:"https://dash.cloudflare.com",settingKey:"api_key.cloudflare"}],ts=[{key:"general.theme",value:"system",category:"general",label:"Tema",description:"Aparencia do app (system/dark/light)"},{key:"general.default_cli",value:"claude",category:"general",label:"CLI Padrao",description:"CLI agent padrao para novos swarms"},{key:"general.auto_approve",value:"false",category:"general",label:"Auto-Approve",description:"Pular confirmacoes de permissao por padrao"},{key:"general.language",value:"pt",category:"general",label:"Idioma",description:"Idioma da interface (pt/en)"},{key:"providers.claude_binary_path",value:"claude",category:"providers",label:"Claude CLI Path",description:"Caminho para o binario do Claude CLI (usado para autenticacao via Agent SDK)"},{key:"general.notification_sound",value:"true",category:"general",label:"Som de Notificacao",description:"Tocar som quando um terminal precisa de atencao (pergunta ou tarefa concluida)"},{key:"advanced.server_port",value:"7773",category:"advanced",label:"Porta do Servidor",description:"Porta HTTP/WebSocket do servidor"}];var rs=[{name:"Claude Code",category:"ai_coding",command:"claude",healthCommand:"claude --version",healthSuccessKeywords:["claude"],versionCommand:"claude --version",authCommand:"claude auth status",authSuccessKeywords:["logged in","authenticated","isloggedin"],docsUrl:"https://docs.anthropic.com/en/docs/claude-code",enabled:!0,isBuiltIn:!0},{name:"Codex",category:"ai_coding",command:"codex",healthCommand:"codex --version",healthSuccessKeywords:["codex"],versionCommand:"codex --version",authCommand:"codex login status",authSuccessKeywords:["logged in"],docsUrl:"https://github.com/openai/codex",enabled:!0,isBuiltIn:!0},{name:"Gemini CLI",category:"ai_coding",command:"gemini",healthCommand:"gemini --version 2>&1",healthSuccessKeywords:["0.","1.","2."],versionCommand:"gemini --version",authCommand:"gemini --prompt exit 2>&1",authSuccessKeywords:["cached credentials","signed in with google"],docsUrl:"https://github.com/google-gemini/gemini-cli",enabled:!0,isBuiltIn:!0},{name:"OpenCode",category:"ai_coding",command:"opencode",healthCommand:"opencode --version",healthSuccessKeywords:["opencode"],versionCommand:"opencode --version",enabled:!0,isBuiltIn:!0},{name:"Cursor",category:"ai_coding",command:"cursor",healthCommand:"cursor --version",healthSuccessKeywords:["0.","1.","2.","3."],versionCommand:"cursor --version",docsUrl:"https://docs.cursor.com",enabled:!0,isBuiltIn:!0}];function jt(a){let e=a.split(".").pop()?.toLowerCase()||"";return{ts:"typescript",tsx:"typescript",js:"javascript",jsx:"javascript",mjs:"javascript",py:"python",html:"html",htm:"html",css:"css",scss:"css",json:"json",md:"markdown",yaml:"yaml",yml:"yaml",rs:"rust",go:"go",sh:"shell",bash:"shell",zsh:"shell",sql:"sql",toml:"toml",xml:"xml",svg:"svg",c:"c",cpp:"cpp",h:"c",hpp:"cpp",java:"java",rb:"ruby",php:"php",swift:"swift",kt:"kotlin",lua:"lua",r:"r",dockerfile:"dockerfile",vue:"vue",svelte:"svelte",png:"image",jpg:"image",jpeg:"image",gif:"image",webp:"image",ico:"image",bmp:"image",tiff:"image",tif:"image",csv:"csv",tsv:"tsv",pdf:"pdf",mp3:"audio",wav:"audio",ogg:"audio",flac:"audio",aac:"audio",m4a:"audio",mp4:"video",webm:"video",mov:"video",avi:"video",mkv:"video",zip:"archive",tar:"archive",gz:"archive",bz2:"archive","7z":"archive",rar:"archive",woff:"font",woff2:"font",ttf:"font",eot:"font",otf:"font",env:"shell"}[e]||"text"}function Gt(a){let e=a.split(".").pop()?.toLowerCase()||"";return{png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",ico:"image/x-icon",bmp:"image/bmp",tiff:"image/tiff",tif:"image/tiff",svg:"image/svg+xml",pdf:"application/pdf",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",flac:"audio/flac",aac:"audio/aac",m4a:"audio/mp4",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",csv:"text/csv",tsv:"text/tab-separated-values"}[e]}function Kt(a){let e=jt(a);return["image","pdf","audio","video","archive","font"].includes(e)}var Yt=[{id:"cursor",label:"Cursor",command:"cursor"},{id:"vscode",label:"VS Code",command:"code"},{id:"vscode-insiders",label:"VS Code Insiders",command:"code-insiders"},{id:"vscodium",label:"VSCodium",command:"codium"},{id:"zed",label:"Zed",command:"zed"},{id:"windsurf",label:"Windsurf",command:"windsurf"},{id:"fleet",label:"Fleet",command:"fleet"},{id:"sublime",label:"Sublime Text",command:"subl"},{id:"terminal",label:"Terminal",command:null},{id:"finder",label:"Finder",command:null}];var ss={engine:"Qual motor de PRD voce gostaria de usar? (impactus-native / bmad / aiox / custom)",overview:"Descreva seu projeto em 2-3 frases. O que ele faz? Qual problema resolve?",features:"Liste as funcionalidades principais do seu projeto (uma por linha):",stack:"Selecione as tecnologias que serao usadas no projeto. (Use o seletor de stack no frontend)",screens:"Descreva as telas principais do seu aplicativo (nome e breve descricao de cada uma):",review:"",done:"PRD gerado com sucesso! Os arquivos foram salvos no diretorio .swarm/prd/"};function pe(a,e){return a==="review"&&e?ma(e):ss[a]}function ze(a){let e=["engine","overview","features","stack","screens","review","done"],t=e.indexOf(a);return t===-1||t===e.length-1?"done":e[t+1]}function ma(a){let e=ue(a,"overview"),t=ue(a,"features"),r=ue(a,"screens"),s=a.stack.map(n=>Ve.find(i=>i.id===n)?.name??n).join(", ");return["--- Resumo do PRD ---","",`**Visao Geral:** ${e||"(nao informado)"}`,"","**Funcionalidades:**",t||"(nao informado)","",`**Stack:** ${s||"(nao selecionado)"}`,"","**Telas:**",r||"(nao informado)","","Tudo certo? Digite 'sim' para gerar o PRD ou descreva o que deseja alterar."].join(`
92
92
  `)}function ue(a,e){let r=["engine","overview","features","stack","screens","review","done"].indexOf(e),s=ss[e],n=!1;for(let i of a.conversation){if(i.role==="system"&&i.content===s){n=!0;continue}if(n&&i.role==="user")return i.content}}function ns(a){let e=ue(a,"overview")??"",t=ue(a,"features")??"",r=ue(a,"screens")??"",s=a.stack.map(g=>Ve.find(w=>w.id===g)?.name??g),n=a.stack.map(g=>Ve.find(w=>w.id===g)).filter(Boolean),i=["# PRD - Product Requirements Document","","## Visao Geral","",e,"","## Funcionalidades","",...t.split(`
93
93
  `).map(g=>{let w=g.trim();return w?w.startsWith("-")?w:`- ${w}`:""}),"","## Stack Tecnologica","",...s.map(g=>`- ${g}`),"","## Telas","",r,"","---",`Gerado em ${new Date().toISOString()}`].join(`
94
94
  `),o=n.filter(g=>g.category==="frontend").map(g=>g.name),c=n.filter(g=>g.category==="backend").map(g=>g.name),l=n.filter(g=>g.category==="database").map(g=>g.name),d=n.filter(g=>g.category==="auth").map(g=>g.name),u=n.filter(g=>g.category==="deployment").map(g=>g.name),p=["# Arquitetura","","## Frontend",o.length>0?o.map(g=>`- ${g}`).join(`
@@ -99,10 +99,10 @@ You can document your own discoveries for teammates to benefit from.`),s.push(""
99
99
  `):"- A definir","","## Variaveis de Ambiente Necessarias","",...n.filter(g=>g.requiredEnvVars&&g.requiredEnvVars.length>0).flatMap(g=>[`### ${g.name}`,...g.requiredEnvVars.map(w=>`- \`${w}\``),""])].join(`
100
100
  `),m=["# Telas","",r].join(`
101
101
  `),h=t.split(`
102
- `).map(g=>g.trim().replace(/^[-*]\s*/,"")).filter(Boolean),f=h.map((g,w)=>({title:`Implementar: ${g}`,description:`Implementar a funcionalidade "${g}" conforme descrito no PRD.`,dependencies:w>0?[h[w-1]]:[]}));return{prdMd:i,architectureMd:p,screensMd:m,tasksJson:f}}var Qe=class{sessions=new Map;broadcast;constructor(e){this.broadcast=e}startSession(e){let t=as(),r=new Date().toISOString(),s="engine",n=this.createMessage("system",pe(s)),i={id:t,projectDir:e.projectDir,engine:e.engine??"impactus-native",step:s,conversation:[n],stack:[],status:"active",createdAt:r};return this.sessions.set(t,i),this.broadcast("prd.message",{sessionId:t,message:n}),i}sendMessage(e,t){let r=this.getSessionOrThrow(e),s=this.createMessage("user",t);if(r.conversation.push(s),this.broadcast("prd.message",{sessionId:e,message:s}),r.step==="review"){let o=t.toLowerCase().trim();if(o==="sim"||o==="yes"||o==="ok"){r.step="done";let l=this.createMessage("system",pe("done"));return r.conversation.push(l),this.broadcast("prd.message",{sessionId:e,message:l}),this.broadcast("prd.step-changed",{sessionId:e,step:r.step}),r}let c=this.createMessage("system","Entendido. Descreva as alteracoes desejadas e depois confirme com 'sim'.");return r.conversation.push(c),this.broadcast("prd.message",{sessionId:e,message:c}),r}let n=ze(r.step);r.step=n;let i=this.createMessage("system",pe(n,r));return r.conversation.push(i),this.broadcast("prd.message",{sessionId:e,message:i}),this.broadcast("prd.step-changed",{sessionId:e,step:n}),r}selectEngine(e,t){let r=this.getSessionOrThrow(e);r.engine=t;let s=this.createMessage("user",`Motor selecionado: ${t}`);r.conversation.push(s),this.broadcast("prd.message",{sessionId:e,message:s});let n=ze(r.step);r.step=n;let i=this.createMessage("system",pe(n,r));return r.conversation.push(i),this.broadcast("prd.message",{sessionId:e,message:i}),this.broadcast("prd.step-changed",{sessionId:e,step:n}),r}selectStack(e,t){let r=this.getSessionOrThrow(e);r.stack=t;let s=this.createMessage("user",`Stack selecionada: ${t.join(", ")}`);r.conversation.push(s),this.broadcast("prd.message",{sessionId:e,message:s});let n=ze(r.step);r.step=n;let i=this.createMessage("system",pe(n,r));return r.conversation.push(i),this.broadcast("prd.message",{sessionId:e,message:i}),this.broadcast("prd.step-changed",{sessionId:e,step:n}),r}generate(e){let t=this.getSessionOrThrow(e),r=ns(t),s=ye(t.projectDir,".swarm","prd");return ma(s,{recursive:!0}),Je(ye(s,"prd.md"),r.prdMd,"utf-8"),Je(ye(s,"architecture.md"),r.architectureMd,"utf-8"),Je(ye(s,"screens.md"),r.screensMd,"utf-8"),Je(ye(s,"tasks.json"),JSON.stringify(r.tasksJson,null,2),"utf-8"),t.status="completed",this.broadcast("prd.completed",{sessionId:e,output:r}),r}getSession(e){return this.sessions.get(e)??null}getSessionOrThrow(e){let t=this.sessions.get(e);if(!t)throw new Error(`PRD session ${e} not found`);return t}createMessage(e,t){return{id:as(),role:e,content:t,timestamp:new Date().toISOString()}}};import{createCipheriv as ga,createDecipheriv as ha,randomBytes as is}from"node:crypto";var me=class{masterKey;constructor(e){this.masterKey=e}encrypt(e){let t=is(12),r=ga("aes-256-gcm",this.masterKey,t),s=Buffer.concat([r.update(e,"utf8"),r.final()]),n=r.getAuthTag();return`${t.toString("base64")}:${s.toString("base64")}:${n.toString("base64")}`}decrypt(e){let[t,r,s]=e.split(":"),n=Buffer.from(t,"base64"),i=Buffer.from(r,"base64"),o=Buffer.from(s,"base64"),c=ha("aes-256-gcm",this.masterKey,n);return c.setAuthTag(o),c.update(i).toString("utf8")+c.final("utf8")}static generateMasterKey(){return is(32)}};import{execSync as Vt}from"node:child_process";import{pbkdf2Sync as fa}from"node:crypto";import{hostname as wa,userInfo as Ea}from"node:os";var Ze=class{static SERVICE="impactus-swarm";static ACCOUNT="master-key";static isAvailable(){try{return Vt("which security",{stdio:"pipe"}),!0}catch{return!1}}static getMasterKey(){if(!this.isAvailable())return this.deriveFallbackKey();try{let e=Vt(`security find-generic-password -s "${this.SERVICE}" -a "${this.ACCOUNT}" -w`,{stdio:"pipe",encoding:"utf8"}).trim();return Buffer.from(e,"base64")}catch{return null}}static setMasterKey(e){if(!this.isAvailable())return;let t=e.toString("base64");try{Vt(`security add-generic-password -s "${this.SERVICE}" -a "${this.ACCOUNT}" -w "${t}" -U`,{stdio:"pipe"})}catch{}}static getOrCreateMasterKey(){let e=this.getMasterKey();return e||(e=me.generateMasterKey(),this.setMasterKey(e)),e}static deriveFallbackKey(){let e=`${wa()}-${Ea().username}-impactus-swarm-vault`;return fa(e,"impactus-swarm-salt",1e5,32,"sha256")}};var et=class{db;vault;constructor(e){this.db=e;let t=Ze.getOrCreateMasterKey();this.vault=new me(t),this.initializeDefaults()}list(e){return(e?this.db.prepare("SELECT * FROM settings WHERE category = ? ORDER BY key").all(e):this.db.prepare("SELECT * FROM settings ORDER BY key").all()).map(r=>this.rowToSetting(r,!0))}get(e){let t=this.db.prepare("SELECT * FROM settings WHERE key = ?").get(e);return t?this.rowToSetting(t,!0):null}set(e){let t=new Date().toISOString(),r=e.isSecret??!1,s=r?this.vault.encrypt(e.value):e.value,n=this.db.prepare("SELECT * FROM settings WHERE key = ?").get(e.key),i=e.category??n?.category??"general",o=e.label??n?.label??e.key,c=e.description??n?.description??void 0;return this.db.prepare(`INSERT OR REPLACE INTO settings (key, value, isSecret, category, label, description, updatedAt)
102
+ `).map(g=>g.trim().replace(/^[-*]\s*/,"")).filter(Boolean),f=h.map((g,w)=>({title:`Implementar: ${g}`,description:`Implementar a funcionalidade "${g}" conforme descrito no PRD.`,dependencies:w>0?[h[w-1]]:[]}));return{prdMd:i,architectureMd:p,screensMd:m,tasksJson:f}}var Qe=class{sessions=new Map;broadcast;constructor(e){this.broadcast=e}startSession(e){let t=as(),r=new Date().toISOString(),s="engine",n=this.createMessage("system",pe(s)),i={id:t,projectDir:e.projectDir,engine:e.engine??"impactus-native",step:s,conversation:[n],stack:[],status:"active",createdAt:r};return this.sessions.set(t,i),this.broadcast("prd.message",{sessionId:t,message:n}),i}sendMessage(e,t){let r=this.getSessionOrThrow(e),s=this.createMessage("user",t);if(r.conversation.push(s),this.broadcast("prd.message",{sessionId:e,message:s}),r.step==="review"){let o=t.toLowerCase().trim();if(o==="sim"||o==="yes"||o==="ok"){r.step="done";let l=this.createMessage("system",pe("done"));return r.conversation.push(l),this.broadcast("prd.message",{sessionId:e,message:l}),this.broadcast("prd.step-changed",{sessionId:e,step:r.step}),r}let c=this.createMessage("system","Entendido. Descreva as alteracoes desejadas e depois confirme com 'sim'.");return r.conversation.push(c),this.broadcast("prd.message",{sessionId:e,message:c}),r}let n=ze(r.step);r.step=n;let i=this.createMessage("system",pe(n,r));return r.conversation.push(i),this.broadcast("prd.message",{sessionId:e,message:i}),this.broadcast("prd.step-changed",{sessionId:e,step:n}),r}selectEngine(e,t){let r=this.getSessionOrThrow(e);r.engine=t;let s=this.createMessage("user",`Motor selecionado: ${t}`);r.conversation.push(s),this.broadcast("prd.message",{sessionId:e,message:s});let n=ze(r.step);r.step=n;let i=this.createMessage("system",pe(n,r));return r.conversation.push(i),this.broadcast("prd.message",{sessionId:e,message:i}),this.broadcast("prd.step-changed",{sessionId:e,step:n}),r}selectStack(e,t){let r=this.getSessionOrThrow(e);r.stack=t;let s=this.createMessage("user",`Stack selecionada: ${t.join(", ")}`);r.conversation.push(s),this.broadcast("prd.message",{sessionId:e,message:s});let n=ze(r.step);r.step=n;let i=this.createMessage("system",pe(n,r));return r.conversation.push(i),this.broadcast("prd.message",{sessionId:e,message:i}),this.broadcast("prd.step-changed",{sessionId:e,step:n}),r}generate(e){let t=this.getSessionOrThrow(e),r=ns(t),s=ye(t.projectDir,".swarm","prd");return ga(s,{recursive:!0}),Je(ye(s,"prd.md"),r.prdMd,"utf-8"),Je(ye(s,"architecture.md"),r.architectureMd,"utf-8"),Je(ye(s,"screens.md"),r.screensMd,"utf-8"),Je(ye(s,"tasks.json"),JSON.stringify(r.tasksJson,null,2),"utf-8"),t.status="completed",this.broadcast("prd.completed",{sessionId:e,output:r}),r}getSession(e){return this.sessions.get(e)??null}getSessionOrThrow(e){let t=this.sessions.get(e);if(!t)throw new Error(`PRD session ${e} not found`);return t}createMessage(e,t){return{id:as(),role:e,content:t,timestamp:new Date().toISOString()}}};import{createCipheriv as ha,createDecipheriv as fa,randomBytes as is}from"node:crypto";var me=class{masterKey;constructor(e){this.masterKey=e}encrypt(e){let t=is(12),r=ha("aes-256-gcm",this.masterKey,t),s=Buffer.concat([r.update(e,"utf8"),r.final()]),n=r.getAuthTag();return`${t.toString("base64")}:${s.toString("base64")}:${n.toString("base64")}`}decrypt(e){let[t,r,s]=e.split(":"),n=Buffer.from(t,"base64"),i=Buffer.from(r,"base64"),o=Buffer.from(s,"base64"),c=fa("aes-256-gcm",this.masterKey,n);return c.setAuthTag(o),c.update(i).toString("utf8")+c.final("utf8")}static generateMasterKey(){return is(32)}};import{execSync as Vt}from"node:child_process";import{pbkdf2Sync as wa}from"node:crypto";import{hostname as Ea,userInfo as Ta}from"node:os";var Ze=class{static SERVICE="impactus-swarm";static ACCOUNT="master-key";static isAvailable(){try{return Vt("which security",{stdio:"pipe"}),!0}catch{return!1}}static getMasterKey(){if(!this.isAvailable())return this.deriveFallbackKey();try{let e=Vt(`security find-generic-password -s "${this.SERVICE}" -a "${this.ACCOUNT}" -w`,{stdio:"pipe",encoding:"utf8"}).trim();return Buffer.from(e,"base64")}catch{return null}}static setMasterKey(e){if(!this.isAvailable())return;let t=e.toString("base64");try{Vt(`security add-generic-password -s "${this.SERVICE}" -a "${this.ACCOUNT}" -w "${t}" -U`,{stdio:"pipe"})}catch{}}static getOrCreateMasterKey(){let e=this.getMasterKey();return e||(e=me.generateMasterKey(),this.setMasterKey(e)),e}static deriveFallbackKey(){let e=`${Ea()}-${Ta().username}-impactus-swarm-vault`;return wa(e,"impactus-swarm-salt",1e5,32,"sha256")}};var et=class{db;vault;constructor(e){this.db=e;let t=Ze.getOrCreateMasterKey();this.vault=new me(t),this.initializeDefaults()}list(e){return(e?this.db.prepare("SELECT * FROM settings WHERE category = ? ORDER BY key").all(e):this.db.prepare("SELECT * FROM settings ORDER BY key").all()).map(r=>this.rowToSetting(r,!0))}get(e){let t=this.db.prepare("SELECT * FROM settings WHERE key = ?").get(e);return t?this.rowToSetting(t,!0):null}set(e){let t=new Date().toISOString(),r=e.isSecret??!1,s=r?this.vault.encrypt(e.value):e.value,n=this.db.prepare("SELECT * FROM settings WHERE key = ?").get(e.key),i=e.category??n?.category??"general",o=e.label??n?.label??e.key,c=e.description??n?.description??void 0;return this.db.prepare(`INSERT OR REPLACE INTO settings (key, value, isSecret, category, label, description, updatedAt)
103
103
  VALUES (?, ?, ?, ?, ?, ?, ?)`).run(e.key,s,r?1:0,i,o,c??null,t),this.rowToSetting({key:e.key,value:s,isSecret:r?1:0,category:i,label:o,description:c??null,updatedAt:t},!0)}delete(e){return this.db.prepare("DELETE FROM settings WHERE key = ?").run(e).changes>0}getSecret(e){let t=this.db.prepare("SELECT * FROM settings WHERE key = ?").get(e);if(!t)throw new Error(`Setting "${e}" not found`);return t.isSecret?this.vault.decrypt(t.value):t.value}getEnvVarsForAgent(){let e={};for(let t of Se){let r=this.db.prepare("SELECT * FROM settings WHERE key = ?").get(t.settingKey);if(r&&r.value){let s=r.isSecret?this.vault.decrypt(r.value):r.value;s&&(e[t.envVar]=s)}}return e}listWorkspaceSettings(e){let t=this.db.prepare("SELECT * FROM workspace_settings WHERE workspaceId = ? ORDER BY key").all(e),r=new Map;for(let n of t)r.set(n.key,n);let s=[];for(let n of Se){let i=r.get(n.settingKey);if(i)s.push({workspaceId:e,key:i.key,value:i.isSecret?"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022":i.value,isSecret:i.isSecret===1,label:i.label||n.label,source:"workspace",updatedAt:i.updatedAt});else{let o=this.db.prepare("SELECT * FROM settings WHERE key = ?").get(n.settingKey);s.push({workspaceId:e,key:n.settingKey,value:o?o.isSecret?"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022":o.value:"",isSecret:o?o.isSecret===1:!0,label:n.label,source:"system",updatedAt:o?.updatedAt??""})}}return s}setWorkspaceSetting(e){let t=new Date().toISOString(),r=e.isSecret??!0,s=r?this.vault.encrypt(e.value):e.value,n=e.label??e.key;return this.db.prepare(`INSERT OR REPLACE INTO workspace_settings (workspaceId, key, value, isSecret, label, updatedAt)
104
104
  VALUES (?, ?, ?, ?, ?, ?)`).run(e.workspaceId,e.key,s,r?1:0,n,t),{workspaceId:e.workspaceId,key:e.key,value:r?"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022":e.value,isSecret:r,label:n,source:"workspace",updatedAt:t}}deleteWorkspaceSetting(e,t){return this.db.prepare("DELETE FROM workspace_settings WHERE workspaceId = ? AND key = ?").run(e,t).changes>0}getWorkspaceSecret(e,t){let r=this.db.prepare("SELECT * FROM workspace_settings WHERE workspaceId = ? AND key = ?").get(e,t);if(!r)throw new Error(`Workspace setting "${t}" not found for workspace "${e}"`);return r.isSecret?this.vault.decrypt(r.value):r.value}getResolvedApiKeys(e){return Se.map(t=>{let r=this.db.prepare("SELECT * FROM workspace_settings WHERE workspaceId = ? AND key = ?").get(e,t.settingKey);if(r&&r.value)return{provider:t.provider,envVar:t.envVar,label:t.label,source:"workspace",configured:!0};let s=this.db.prepare("SELECT * FROM settings WHERE key = ?").get(t.settingKey);return{provider:t.provider,envVar:t.envVar,label:t.label,source:"system",configured:!!(s&&s.value)}})}getEnvVarsForWorkspace(e){let t={};for(let r of Se){let s=this.db.prepare("SELECT * FROM workspace_settings WHERE workspaceId = ? AND key = ?").get(e,r.settingKey);if(s&&s.value){let i=s.isSecret?this.vault.decrypt(s.value):s.value;if(i){t[r.envVar]=i;continue}}let n=this.db.prepare("SELECT * FROM settings WHERE key = ?").get(r.settingKey);if(n&&n.value){let i=n.isSecret?this.vault.decrypt(n.value):n.value;i&&(t[r.envVar]=i)}}return t}initializeDefaults(){let e=this.db.prepare(`INSERT OR IGNORE INTO settings (key, value, isSecret, category, label, description, updatedAt)
105
- VALUES (?, ?, 0, ?, ?, ?, ?)`),t=new Date().toISOString();for(let r of ts)e.run(r.key,r.value,r.category,r.label,r.description??null,t)}rowToSetting(e,t){return{key:e.key,value:t&&e.isSecret?"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022":e.value,isSecret:e.isSecret===1,category:e.category,label:e.label,description:e.description??void 0,updatedAt:e.updatedAt}}};import{randomUUID as Ta}from"node:crypto";import{execSync as zt}from"node:child_process";var tt=class{db;constructor(e){this.db=e,this.initializeDefaults()}initializeDefaults(){let e=new Date().toISOString(),t=this.db.prepare(`
105
+ VALUES (?, ?, 0, ?, ?, ?, ?)`),t=new Date().toISOString();for(let r of ts)e.run(r.key,r.value,r.category,r.label,r.description??null,t)}rowToSetting(e,t){return{key:e.key,value:t&&e.isSecret?"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022":e.value,isSecret:e.isSecret===1,category:e.category,label:e.label,description:e.description??void 0,updatedAt:e.updatedAt}}};import{randomUUID as Sa}from"node:crypto";import{execSync as zt}from"node:child_process";var tt=class{db;constructor(e){this.db=e,this.initializeDefaults()}initializeDefaults(){let e=new Date().toISOString(),t=this.db.prepare(`
106
106
  INSERT OR IGNORE INTO cli_tools
107
107
  (id, name, logo, category, command, healthCommand, healthSuccessKeywords,
108
108
  versionCommand, authCommand, authSuccessKeywords, docsUrl, envVars, notes,
@@ -113,13 +113,13 @@ You can document your own discoveries for teammates to benefit from.`),s.push(""
113
113
  authCommand = ?, authSuccessKeywords = ?, healthCommand = ?,
114
114
  healthSuccessKeywords = ?, updatedAt = ?
115
115
  WHERE id = ? AND isBuiltIn = 1
116
- `);for(let s of rs){let i=`builtin-${s.command.toLowerCase().replace(/[^a-z0-9]/g,"-")}`;t.run(i,s.name,s.logo??null,s.category,s.command,s.healthCommand,JSON.stringify(s.healthSuccessKeywords??[]),s.versionCommand??null,s.authCommand??null,s.authSuccessKeywords?JSON.stringify(s.authSuccessKeywords):null,s.docsUrl??null,JSON.stringify(s.envVars??{}),s.notes??null,s.enabled?1:0,s.isBuiltIn?1:0,e,e),r.run(s.authCommand??null,s.authSuccessKeywords?JSON.stringify(s.authSuccessKeywords):null,s.healthCommand,JSON.stringify(s.healthSuccessKeywords??[]),e,i)}}rowToCliTool(e){return{id:e.id,name:e.name,logo:e.logo??void 0,category:e.category,command:e.command,healthCommand:e.healthCommand,healthSuccessKeywords:JSON.parse(e.healthSuccessKeywords),versionCommand:e.versionCommand??void 0,authCommand:e.authCommand??void 0,authSuccessKeywords:e.authSuccessKeywords?JSON.parse(e.authSuccessKeywords):void 0,docsUrl:e.docsUrl??void 0,envVars:JSON.parse(e.envVars),notes:e.notes??void 0,enabled:e.enabled===1,isBuiltIn:e.isBuiltIn===1,createdAt:e.createdAt,updatedAt:e.updatedAt}}list(e){return(e?this.db.prepare("SELECT * FROM cli_tools WHERE category = ? ORDER BY name").all(e):this.db.prepare("SELECT * FROM cli_tools ORDER BY name").all()).map(r=>this.rowToCliTool(r))}get(e){let t=this.db.prepare("SELECT * FROM cli_tools WHERE id = ?").get(e);return t?this.rowToCliTool(t):null}create(e){let t=new Date().toISOString(),r=Ta();return this.db.prepare(`INSERT INTO cli_tools
116
+ `);for(let s of rs){let i=`builtin-${s.command.toLowerCase().replace(/[^a-z0-9]/g,"-")}`;t.run(i,s.name,s.logo??null,s.category,s.command,s.healthCommand,JSON.stringify(s.healthSuccessKeywords??[]),s.versionCommand??null,s.authCommand??null,s.authSuccessKeywords?JSON.stringify(s.authSuccessKeywords):null,s.docsUrl??null,JSON.stringify(s.envVars??{}),s.notes??null,s.enabled?1:0,s.isBuiltIn?1:0,e,e),r.run(s.authCommand??null,s.authSuccessKeywords?JSON.stringify(s.authSuccessKeywords):null,s.healthCommand,JSON.stringify(s.healthSuccessKeywords??[]),e,i)}}rowToCliTool(e){return{id:e.id,name:e.name,logo:e.logo??void 0,category:e.category,command:e.command,healthCommand:e.healthCommand,healthSuccessKeywords:JSON.parse(e.healthSuccessKeywords),versionCommand:e.versionCommand??void 0,authCommand:e.authCommand??void 0,authSuccessKeywords:e.authSuccessKeywords?JSON.parse(e.authSuccessKeywords):void 0,docsUrl:e.docsUrl??void 0,envVars:JSON.parse(e.envVars),notes:e.notes??void 0,enabled:e.enabled===1,isBuiltIn:e.isBuiltIn===1,createdAt:e.createdAt,updatedAt:e.updatedAt}}list(e){return(e?this.db.prepare("SELECT * FROM cli_tools WHERE category = ? ORDER BY name").all(e):this.db.prepare("SELECT * FROM cli_tools ORDER BY name").all()).map(r=>this.rowToCliTool(r))}get(e){let t=this.db.prepare("SELECT * FROM cli_tools WHERE id = ?").get(e);return t?this.rowToCliTool(t):null}create(e){let t=new Date().toISOString(),r=Sa();return this.db.prepare(`INSERT INTO cli_tools
117
117
  (id, name, logo, category, command, healthCommand, healthSuccessKeywords,
118
118
  versionCommand, authCommand, authSuccessKeywords, docsUrl, envVars, notes,
119
119
  enabled, isBuiltIn, createdAt, updatedAt)
120
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?)`).run(r,e.name,e.logo??null,e.category,e.command,e.healthCommand,JSON.stringify(e.healthSuccessKeywords??[]),e.versionCommand??null,e.authCommand??null,e.authSuccessKeywords?JSON.stringify(e.authSuccessKeywords):null,e.docsUrl??null,JSON.stringify(e.envVars??{}),e.notes??null,e.enabled!==!1?1:0,t,t),this.get(r)}update(e){let t=this.get(e.id);if(!t)throw new Error(`CLI tool not found: ${e.id}`);let r=new Date().toISOString(),s=[],n=[];return e.name!==void 0&&(s.push("name = ?"),n.push(e.name)),e.logo!==void 0&&(s.push("logo = ?"),n.push(e.logo)),e.category!==void 0&&(s.push("category = ?"),n.push(e.category)),e.command!==void 0&&(s.push("command = ?"),n.push(e.command)),e.healthCommand!==void 0&&(s.push("healthCommand = ?"),n.push(e.healthCommand)),e.healthSuccessKeywords!==void 0&&(s.push("healthSuccessKeywords = ?"),n.push(JSON.stringify(e.healthSuccessKeywords))),e.versionCommand!==void 0&&(s.push("versionCommand = ?"),n.push(e.versionCommand)),e.authCommand!==void 0&&(s.push("authCommand = ?"),n.push(e.authCommand)),e.authSuccessKeywords!==void 0&&(s.push("authSuccessKeywords = ?"),n.push(JSON.stringify(e.authSuccessKeywords))),e.docsUrl!==void 0&&(s.push("docsUrl = ?"),n.push(e.docsUrl)),e.envVars!==void 0&&(s.push("envVars = ?"),n.push(JSON.stringify(e.envVars))),e.notes!==void 0&&(s.push("notes = ?"),n.push(e.notes)),e.enabled!==void 0&&(s.push("enabled = ?"),n.push(e.enabled?1:0)),s.length===0?t:(s.push("updatedAt = ?"),n.push(r),n.push(e.id),this.db.prepare(`UPDATE cli_tools SET ${s.join(", ")} WHERE id = ?`).run(...n),this.get(e.id))}delete(e){let t=this.get(e);if(!t)return!1;if(t.isBuiltIn)throw new Error("Cannot delete built-in CLI tools");return this.db.prepare("DELETE FROM cli_tools WHERE id = ?").run(e),!0}async healthCheck(e){let t=this.get(e);if(!t)throw new Error(`CLI tool not found: ${e}`);let r=new Date().toISOString(),s={id:t.id,name:t.name,installed:!1,healthy:!1,checkedAt:r};try{let n=zt(t.healthCommand,{timeout:1e4,encoding:"utf-8",stdio:"pipe",shell:"/bin/sh"}).toLowerCase();s.installed=!0,t.healthSuccessKeywords.length>0?s.healthy=t.healthSuccessKeywords.some(i=>n.includes(i.toLowerCase())):s.healthy=!0}catch(n){return s.installed=!1,s.healthy=!1,s.error=n instanceof Error?n.message:String(n),s}if(t.versionCommand)try{let n=zt(t.versionCommand,{timeout:5e3,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim();s.version=n}catch{}if(t.authCommand){let n="";try{n=zt(t.authCommand,{timeout:15e3,encoding:"utf-8",stdio:"pipe",shell:"/bin/sh"}).toLowerCase()}catch(i){if(i&&typeof i=="object"){let o=i;n=((o.stdout??"")+" "+(o.stderr??"")).toLowerCase()}}t.authSuccessKeywords&&t.authSuccessKeywords.length>0?s.authenticated=t.authSuccessKeywords.some(i=>n.includes(i.toLowerCase())):s.authenticated=n.length>0}return s}async healthCheckAll(e){let t=this.list(e).filter(s=>s.enabled),r=[];for(let s of t)r.push(await this.healthCheck(s.id));return r}};import{randomUUID as rt}from"node:crypto";var st=class{browser=null;sessions=new Map;broadcast;playwright=null;constructor(e){this.broadcast=e}async ensurePlaywright(){if(this.playwright)return this.playwright;try{return this.playwright=await import("playwright"),this.playwright}catch{throw new Error("Playwright not installed. Run: pnpm add playwright")}}async ensureBrowser(){if(this.browser)return this.browser;let e=await this.ensurePlaywright();return this.browser=await e.chromium.launch({headless:!0}),this.browser}getSession(e){let t=this.sessions.get(e);if(!t)throw new Error(`Browser session ${e} not found`);return t}getTab(e,t){let r=e.tabs.get(t);if(!r)throw new Error(`Browser tab ${t} not found in session ${e.id}`);return r}async getNavigationState(e){try{let t=await e.send("Page.getNavigationHistory");return{canGoBack:t.currentIndex>0,canGoForward:t.currentIndex<t.entries.length-1}}catch{return{canGoBack:!1,canGoForward:!1}}}async startScreencast(e,t,r){await e.send("Page.startScreencast",{format:"jpeg",quality:70,maxWidth:1920,maxHeight:1080,everyNthFrame:1}),e.on("Page.screencastFrame",s=>{this.broadcast("browser.frame",{sessionId:t,tabId:r,data:s.data,frameNumber:s.sessionId,metadata:s.metadata})})}async stopScreencast(e){try{await e.send("Page.stopScreencast")}catch{}}async setupPageEvents(e,t,r){let s=t.id,n=t.tabs.get(r),i=n.cdpSession;await i.send("Runtime.enable"),i.on("Runtime.consoleAPICalled",o=>{let c=o.args?.map(l=>l.type==="string"?l.value:l.type==="number"||l.type==="boolean"?String(l.value):l.type==="undefined"?"undefined":l.value===null?"null":l.preview?.description?l.preview.description:l.description?l.description:l.type)??[];this.broadcast("browser.console",{sessionId:s,tabId:r,type:o.type,args:c,text:c.join(" "),timestamp:Date.now()})}),i.on("Runtime.exceptionThrown",o=>{let c=o.exceptionDetails?.text||o.exceptionDetails?.exception?.description||"Unknown error";this.broadcast("browser.console",{sessionId:s,tabId:r,type:"error",args:[c],text:c,timestamp:Date.now()})}),e.on("framenavigated",async o=>{if(o===e.mainFrame())try{let c=e.url(),l=await e.title().catch(()=>"");n.url=c,n.title=l;let d=await this.getNavigationState(n.cdpSession);this.broadcast("browser.tab.updated",{sessionId:s,tabId:r,url:c,title:l,loading:!0,...d})}catch{}}),e.on("load",async()=>{try{let o=await e.title().catch(()=>"");n.title=o;let c=await this.getNavigationState(n.cdpSession);this.broadcast("browser.tab.updated",{sessionId:s,tabId:r,title:o,loading:!1,...c})}catch{}}),e.on("popup",async o=>{try{let c=rt(),l=await o.context().newCDPSession(o),d=o.url(),u=await o.title().catch(()=>""),p={page:o,cdpSession:l,url:d,title:u};t.tabs.set(c,p),this.setupPageEvents(o,t,c),this.broadcast("browser.tab.created",{sessionId:s,tabId:c,url:d,title:u})}catch{}})}async openSession(e){let r=await(await this.ensureBrowser()).newContext({viewport:{width:1280,height:720}}),s=rt(),n=rt(),i=await r.newPage(),o=await r.newCDPSession(i);e&&await i.goto(e);let c=i.url(),l=await i.title().catch(()=>""),d={page:i,cdpSession:o,url:c,title:l},u={id:s,context:r,tabs:new Map([[n,d]]),activeTabId:n};return this.sessions.set(s,u),await this.setupPageEvents(i,u,n),await this.startScreencast(o,s,n),{sessionId:s,tabId:n}}async closeSession(e){let t=this.getSession(e);for(let[,r]of t.tabs){await this.stopScreencast(r.cdpSession);try{await r.cdpSession.detach()}catch{}}try{await t.context.close()}catch{}this.sessions.delete(e)}async openTab(e,t){let r=this.getSession(e),s=rt(),n=await r.context.newPage(),i=await r.context.newCDPSession(n);t&&await n.goto(t);let o=n.url(),c=await n.title().catch(()=>""),l={page:n,cdpSession:i,url:o,title:c};return r.tabs.set(s,l),await this.setupPageEvents(n,r,s),this.broadcast("browser.tab.created",{sessionId:e,tabId:s,url:o,title:c}),{tabId:s}}async closeTab(e,t){let r=this.getSession(e),s=this.getTab(r,t);r.activeTabId===t&&await this.stopScreencast(s.cdpSession);try{await s.cdpSession.detach()}catch{}try{await s.page.close()}catch{}if(r.tabs.delete(t),this.broadcast("browser.tab.closed",{sessionId:e,tabId:t}),r.activeTabId===t&&r.tabs.size>0){let n=r.tabs.keys().next().value;await this.activateTab(e,n)}}async navigateTab(e,t,r){let s=this.getSession(e),n=this.getTab(s,t),i=r.trim();i&&!i.startsWith("http://")&&!i.startsWith("https://")&&!i.startsWith("about:")&&(i="https://"+i),await n.page.goto(i).catch(o=>{this.broadcast("browser.console",{sessionId:e,tabId:t,type:"error",args:[`Navigation failed: ${o.message}`],text:`Navigation failed: ${o.message}`,timestamp:Date.now()})})}async activateTab(e,t){let r=this.getSession(e),s=this.getTab(r,t);if(r.activeTabId!==t){let i=r.tabs.get(r.activeTabId);i&&await this.stopScreencast(i.cdpSession)}r.activeTabId=t,await this.startScreencast(s.cdpSession,e,t);let n=await this.getNavigationState(s.cdpSession);this.broadcast("browser.tab.updated",{sessionId:e,tabId:t,url:s.url,title:s.title,loading:!1,...n})}async goBack(e,t){let r=this.getSession(e);await this.getTab(r,t).page.goBack()}async goForward(e,t){let r=this.getSession(e);await this.getTab(r,t).page.goForward()}async refresh(e,t){let r=this.getSession(e);await this.getTab(r,t).page.reload()}async sendInput(e,t,r){let s=this.getSession(e),i=this.getTab(s,t).cdpSession,o=["mousePressed","mouseReleased","mouseMoved","mouseWheel"].includes(r.type),c=["keyDown","keyUp","char"].includes(r.type);o?await i.send("Input.dispatchMouseEvent",{type:r.type,x:r.x??0,y:r.y??0,button:r.button||"left",buttons:r.buttons??0,clickCount:r.clickCount||1,deltaX:r.deltaX??0,deltaY:r.deltaY??0,modifiers:r.modifiers||0}):c&&await i.send("Input.dispatchKeyEvent",{type:r.type,key:r.key,code:r.code,text:r.text,windowsVirtualKeyCode:r.windowsVirtualKeyCode||0,nativeVirtualKeyCode:r.windowsVirtualKeyCode||0,modifiers:r.modifiers||0})}async ackFrame(e,t,r){let s=this.getSession(e),n=this.getTab(s,t);try{await n.cdpSession.send("Page.screencastFrameAck",{sessionId:r})}catch{}}async inspectElementAt(e,t,r,s){let n=this.getSession(e),o=this.getTab(n,t).cdpSession;try{await o.send("DOM.enable");let{nodeId:c}=await o.send("DOM.getNodeForLocation",{x:r,y:s,includeUserAgentShadowDOM:!1});if(!c)return{found:!1};let{model:l}=await o.send("DOM.getBoxModel",{nodeId:c}),d=l.border,u={x:d[0],y:d[1],width:d[2]-d[0],height:d[5]-d[1]},{node:p}=await o.send("DOM.describeNode",{nodeId:c}),m=(p.attributes||[]).reduce((f,g,w,E)=>g==="class"&&E[w+1]?E[w+1]:f,""),h=(p.attributes||[]).reduce((f,g,w,E)=>g==="id"&&E[w+1]?E[w+1]:f,"");return{found:!0,boundingBox:u,tagName:p.localName||p.nodeName?.toLowerCase(),className:m,id:h,textContent:(p.nodeValue||"").slice(0,200)}}catch{return{found:!1}}}async highlightElementAt(e,t,r,s,n){let i=this.getSession(e),c=this.getTab(i,t).cdpSession;try{if(!n){await c.send("DOM.hideHighlight");return}await c.send("DOM.enable");let{nodeId:l}=await c.send("DOM.getNodeForLocation",{x:r,y:s,includeUserAgentShadowDOM:!1});if(!l)return;await c.send("DOM.highlightNode",{nodeId:l,highlightConfig:{contentColor:{r:111,g:168,b:220,a:.3},paddingColor:{r:147,g:196,b:125,a:.3},borderColor:{r:255,g:229,b:153,a:.7},marginColor:{r:246,g:178,b:107,a:.3}}})}catch{}}async screenshotRegion(e,t,r){let s=this.getSession(e),i=this.getTab(s,t).cdpSession;try{await i.send("DOM.hideHighlight")}catch{}let o={format:"png"};return r&&(o.clip={x:r.x,y:r.y,width:r.width,height:r.height,scale:1}),{data:(await i.send("Page.captureScreenshot",o)).data,width:r?.width??1280,height:r?.height??720}}async stopAll(){let e=[...this.sessions.keys()];if(await Promise.all(e.map(t=>this.closeSession(t))),this.browser){try{await this.browser.close()}catch{}this.browser=null}}};import{exec as Sa}from"node:child_process";import{promisify as ya}from"node:util";var os=ya(Sa),nt=class{monitors=new Map;portCache=new Map;workspaceTerminals=new Map;broadcast;resolvePid;scanIntervalMs=3e3;constructor(e,t){this.broadcast=e,this.resolvePid=t}async startMonitoring(e,t){this.stopMonitoring(e),this.workspaceTerminals.set(e,t),await this.scan(e);let r=setInterval(()=>{this.scan(e).catch(console.error)},this.scanIntervalMs);this.monitors.set(e,r)}stopMonitoring(e){let t=this.monitors.get(e);t&&(clearInterval(t),this.monitors.delete(e)),this.portCache.delete(e),this.workspaceTerminals.delete(e)}listPorts(e){return this.portCache.get(e)||[]}listAllWorkspacePorts(){let e=new Set,t=[];for(let r of this.portCache.values())for(let s of r){let n=`${s.port}:${s.pid}`;e.has(n)||(e.add(n),t.push(s))}return t.sort((r,s)=>r.port-s.port),t}async listSystemPorts(){return this.detectListeningPorts()}async killPort(e,t){try{process.kill(t,"SIGTERM"),await new Promise(r=>setTimeout(r,2e3));try{process.kill(t,0),process.kill(t,"SIGKILL")}catch{}return{success:!0}}catch(r){return{success:!1,error:r instanceof Error?r.message:String(r)}}}async scan(e){try{let t=this.workspaceTerminals.get(e)||[],r=[];for(let d of t){let u=this.resolvePid(d);u&&u>0&&r.push(u)}if(r.length===0){(this.portCache.get(e)||[]).length>0&&(this.portCache.set(e,[]),this.broadcast("ports.update",{workspaceId:e,ports:[],timestamp:Date.now()}));return}let{allDescendantPids:s,pidToTerminal:n}=await this.buildProcessTree(r,t),o=(await this.detectListeningPorts()).filter(d=>s.has(d.pid));for(let d of o){let u=n.get(d.pid);u&&(d.terminalId=u)}let c=this.portCache.get(e)||[],l=this.portsChanged(c,o);if(this.portCache.set(e,o),l){let d={workspaceId:e,ports:o,timestamp:Date.now()};this.broadcast("ports.update",d)}}catch(t){console.error("[PortMonitor] scan error:",t)}}async buildProcessTree(e,t){let r=new Set(e),s=new Map;try{let{stdout:n}=await os("ps -eo ppid=,pid= 2>/dev/null || true",{timeout:3e3}),i=new Map;for(let o of n.trim().split(`
120
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?)`).run(r,e.name,e.logo??null,e.category,e.command,e.healthCommand,JSON.stringify(e.healthSuccessKeywords??[]),e.versionCommand??null,e.authCommand??null,e.authSuccessKeywords?JSON.stringify(e.authSuccessKeywords):null,e.docsUrl??null,JSON.stringify(e.envVars??{}),e.notes??null,e.enabled!==!1?1:0,t,t),this.get(r)}update(e){let t=this.get(e.id);if(!t)throw new Error(`CLI tool not found: ${e.id}`);let r=new Date().toISOString(),s=[],n=[];return e.name!==void 0&&(s.push("name = ?"),n.push(e.name)),e.logo!==void 0&&(s.push("logo = ?"),n.push(e.logo)),e.category!==void 0&&(s.push("category = ?"),n.push(e.category)),e.command!==void 0&&(s.push("command = ?"),n.push(e.command)),e.healthCommand!==void 0&&(s.push("healthCommand = ?"),n.push(e.healthCommand)),e.healthSuccessKeywords!==void 0&&(s.push("healthSuccessKeywords = ?"),n.push(JSON.stringify(e.healthSuccessKeywords))),e.versionCommand!==void 0&&(s.push("versionCommand = ?"),n.push(e.versionCommand)),e.authCommand!==void 0&&(s.push("authCommand = ?"),n.push(e.authCommand)),e.authSuccessKeywords!==void 0&&(s.push("authSuccessKeywords = ?"),n.push(JSON.stringify(e.authSuccessKeywords))),e.docsUrl!==void 0&&(s.push("docsUrl = ?"),n.push(e.docsUrl)),e.envVars!==void 0&&(s.push("envVars = ?"),n.push(JSON.stringify(e.envVars))),e.notes!==void 0&&(s.push("notes = ?"),n.push(e.notes)),e.enabled!==void 0&&(s.push("enabled = ?"),n.push(e.enabled?1:0)),s.length===0?t:(s.push("updatedAt = ?"),n.push(r),n.push(e.id),this.db.prepare(`UPDATE cli_tools SET ${s.join(", ")} WHERE id = ?`).run(...n),this.get(e.id))}delete(e){let t=this.get(e);if(!t)return!1;if(t.isBuiltIn)throw new Error("Cannot delete built-in CLI tools");return this.db.prepare("DELETE FROM cli_tools WHERE id = ?").run(e),!0}async healthCheck(e){let t=this.get(e);if(!t)throw new Error(`CLI tool not found: ${e}`);let r=new Date().toISOString(),s={id:t.id,name:t.name,installed:!1,healthy:!1,checkedAt:r};try{let n=zt(t.healthCommand,{timeout:1e4,encoding:"utf-8",stdio:"pipe",shell:"/bin/sh"}).toLowerCase();s.installed=!0,t.healthSuccessKeywords.length>0?s.healthy=t.healthSuccessKeywords.some(i=>n.includes(i.toLowerCase())):s.healthy=!0}catch(n){return s.installed=!1,s.healthy=!1,s.error=n instanceof Error?n.message:String(n),s}if(t.versionCommand)try{let n=zt(t.versionCommand,{timeout:5e3,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim();s.version=n}catch{}if(t.authCommand){let n="";try{n=zt(t.authCommand,{timeout:15e3,encoding:"utf-8",stdio:"pipe",shell:"/bin/sh"}).toLowerCase()}catch(i){if(i&&typeof i=="object"){let o=i;n=((o.stdout??"")+" "+(o.stderr??"")).toLowerCase()}}t.authSuccessKeywords&&t.authSuccessKeywords.length>0?s.authenticated=t.authSuccessKeywords.some(i=>n.includes(i.toLowerCase())):s.authenticated=n.length>0}return s}async healthCheckAll(e){let t=this.list(e).filter(s=>s.enabled),r=[];for(let s of t)r.push(await this.healthCheck(s.id));return r}};import{randomUUID as rt}from"node:crypto";var st=class{browser=null;sessions=new Map;broadcast;playwright=null;constructor(e){this.broadcast=e}async ensurePlaywright(){if(this.playwright)return this.playwright;try{return this.playwright=await import("playwright"),this.playwright}catch{throw new Error("Playwright not installed. Run: pnpm add playwright")}}async ensureBrowser(){if(this.browser)return this.browser;let e=await this.ensurePlaywright();return this.browser=await e.chromium.launch({headless:!0}),this.browser}getSession(e){let t=this.sessions.get(e);if(!t)throw new Error(`Browser session ${e} not found`);return t}getTab(e,t){let r=e.tabs.get(t);if(!r)throw new Error(`Browser tab ${t} not found in session ${e.id}`);return r}async getNavigationState(e){try{let t=await e.send("Page.getNavigationHistory");return{canGoBack:t.currentIndex>0,canGoForward:t.currentIndex<t.entries.length-1}}catch{return{canGoBack:!1,canGoForward:!1}}}async startScreencast(e,t,r){await e.send("Page.startScreencast",{format:"jpeg",quality:70,maxWidth:1920,maxHeight:1080,everyNthFrame:1}),e.on("Page.screencastFrame",s=>{this.broadcast("browser.frame",{sessionId:t,tabId:r,data:s.data,frameNumber:s.sessionId,metadata:s.metadata})})}async stopScreencast(e){try{await e.send("Page.stopScreencast")}catch{}}async setupPageEvents(e,t,r){let s=t.id,n=t.tabs.get(r),i=n.cdpSession;await i.send("Runtime.enable"),i.on("Runtime.consoleAPICalled",o=>{let c=o.args?.map(l=>l.type==="string"?l.value:l.type==="number"||l.type==="boolean"?String(l.value):l.type==="undefined"?"undefined":l.value===null?"null":l.preview?.description?l.preview.description:l.description?l.description:l.type)??[];this.broadcast("browser.console",{sessionId:s,tabId:r,type:o.type,args:c,text:c.join(" "),timestamp:Date.now()})}),i.on("Runtime.exceptionThrown",o=>{let c=o.exceptionDetails?.text||o.exceptionDetails?.exception?.description||"Unknown error";this.broadcast("browser.console",{sessionId:s,tabId:r,type:"error",args:[c],text:c,timestamp:Date.now()})}),e.on("framenavigated",async o=>{if(o===e.mainFrame())try{let c=e.url(),l=await e.title().catch(()=>"");n.url=c,n.title=l;let d=await this.getNavigationState(n.cdpSession);this.broadcast("browser.tab.updated",{sessionId:s,tabId:r,url:c,title:l,loading:!0,...d})}catch{}}),e.on("load",async()=>{try{let o=await e.title().catch(()=>"");n.title=o;let c=await this.getNavigationState(n.cdpSession);this.broadcast("browser.tab.updated",{sessionId:s,tabId:r,title:o,loading:!1,...c})}catch{}}),e.on("popup",async o=>{try{let c=rt(),l=await o.context().newCDPSession(o),d=o.url(),u=await o.title().catch(()=>""),p={page:o,cdpSession:l,url:d,title:u};t.tabs.set(c,p),this.setupPageEvents(o,t,c),this.broadcast("browser.tab.created",{sessionId:s,tabId:c,url:d,title:u})}catch{}})}async openSession(e){let r=await(await this.ensureBrowser()).newContext({viewport:{width:1280,height:720}}),s=rt(),n=rt(),i=await r.newPage(),o=await r.newCDPSession(i);e&&await i.goto(e);let c=i.url(),l=await i.title().catch(()=>""),d={page:i,cdpSession:o,url:c,title:l},u={id:s,context:r,tabs:new Map([[n,d]]),activeTabId:n};return this.sessions.set(s,u),await this.setupPageEvents(i,u,n),await this.startScreencast(o,s,n),{sessionId:s,tabId:n}}async closeSession(e){let t=this.getSession(e);for(let[,r]of t.tabs){await this.stopScreencast(r.cdpSession);try{await r.cdpSession.detach()}catch{}}try{await t.context.close()}catch{}this.sessions.delete(e)}async openTab(e,t){let r=this.getSession(e),s=rt(),n=await r.context.newPage(),i=await r.context.newCDPSession(n);t&&await n.goto(t);let o=n.url(),c=await n.title().catch(()=>""),l={page:n,cdpSession:i,url:o,title:c};return r.tabs.set(s,l),await this.setupPageEvents(n,r,s),this.broadcast("browser.tab.created",{sessionId:e,tabId:s,url:o,title:c}),{tabId:s}}async closeTab(e,t){let r=this.getSession(e),s=this.getTab(r,t);r.activeTabId===t&&await this.stopScreencast(s.cdpSession);try{await s.cdpSession.detach()}catch{}try{await s.page.close()}catch{}if(r.tabs.delete(t),this.broadcast("browser.tab.closed",{sessionId:e,tabId:t}),r.activeTabId===t&&r.tabs.size>0){let n=r.tabs.keys().next().value;await this.activateTab(e,n)}}async navigateTab(e,t,r){let s=this.getSession(e),n=this.getTab(s,t),i=r.trim();i&&!i.startsWith("http://")&&!i.startsWith("https://")&&!i.startsWith("about:")&&(i="https://"+i),await n.page.goto(i).catch(o=>{this.broadcast("browser.console",{sessionId:e,tabId:t,type:"error",args:[`Navigation failed: ${o.message}`],text:`Navigation failed: ${o.message}`,timestamp:Date.now()})})}async activateTab(e,t){let r=this.getSession(e),s=this.getTab(r,t);if(r.activeTabId!==t){let i=r.tabs.get(r.activeTabId);i&&await this.stopScreencast(i.cdpSession)}r.activeTabId=t,await this.startScreencast(s.cdpSession,e,t);let n=await this.getNavigationState(s.cdpSession);this.broadcast("browser.tab.updated",{sessionId:e,tabId:t,url:s.url,title:s.title,loading:!1,...n})}async goBack(e,t){let r=this.getSession(e);await this.getTab(r,t).page.goBack()}async goForward(e,t){let r=this.getSession(e);await this.getTab(r,t).page.goForward()}async refresh(e,t){let r=this.getSession(e);await this.getTab(r,t).page.reload()}async sendInput(e,t,r){let s=this.getSession(e),i=this.getTab(s,t).cdpSession,o=["mousePressed","mouseReleased","mouseMoved","mouseWheel"].includes(r.type),c=["keyDown","keyUp","char"].includes(r.type);o?await i.send("Input.dispatchMouseEvent",{type:r.type,x:r.x??0,y:r.y??0,button:r.button||"left",buttons:r.buttons??0,clickCount:r.clickCount||1,deltaX:r.deltaX??0,deltaY:r.deltaY??0,modifiers:r.modifiers||0}):c&&await i.send("Input.dispatchKeyEvent",{type:r.type,key:r.key,code:r.code,text:r.text,windowsVirtualKeyCode:r.windowsVirtualKeyCode||0,nativeVirtualKeyCode:r.windowsVirtualKeyCode||0,modifiers:r.modifiers||0})}async ackFrame(e,t,r){let s=this.getSession(e),n=this.getTab(s,t);try{await n.cdpSession.send("Page.screencastFrameAck",{sessionId:r})}catch{}}async inspectElementAt(e,t,r,s){let n=this.getSession(e),o=this.getTab(n,t).cdpSession;try{await o.send("DOM.enable");let{nodeId:c}=await o.send("DOM.getNodeForLocation",{x:r,y:s,includeUserAgentShadowDOM:!1});if(!c)return{found:!1};let{model:l}=await o.send("DOM.getBoxModel",{nodeId:c}),d=l.border,u={x:d[0],y:d[1],width:d[2]-d[0],height:d[5]-d[1]},{node:p}=await o.send("DOM.describeNode",{nodeId:c}),m=(p.attributes||[]).reduce((f,g,w,E)=>g==="class"&&E[w+1]?E[w+1]:f,""),h=(p.attributes||[]).reduce((f,g,w,E)=>g==="id"&&E[w+1]?E[w+1]:f,"");return{found:!0,boundingBox:u,tagName:p.localName||p.nodeName?.toLowerCase(),className:m,id:h,textContent:(p.nodeValue||"").slice(0,200)}}catch{return{found:!1}}}async highlightElementAt(e,t,r,s,n){let i=this.getSession(e),c=this.getTab(i,t).cdpSession;try{if(!n){await c.send("DOM.hideHighlight");return}await c.send("DOM.enable");let{nodeId:l}=await c.send("DOM.getNodeForLocation",{x:r,y:s,includeUserAgentShadowDOM:!1});if(!l)return;await c.send("DOM.highlightNode",{nodeId:l,highlightConfig:{contentColor:{r:111,g:168,b:220,a:.3},paddingColor:{r:147,g:196,b:125,a:.3},borderColor:{r:255,g:229,b:153,a:.7},marginColor:{r:246,g:178,b:107,a:.3}}})}catch{}}async screenshotRegion(e,t,r){let s=this.getSession(e),i=this.getTab(s,t).cdpSession;try{await i.send("DOM.hideHighlight")}catch{}let o={format:"png"};return r&&(o.clip={x:r.x,y:r.y,width:r.width,height:r.height,scale:1}),{data:(await i.send("Page.captureScreenshot",o)).data,width:r?.width??1280,height:r?.height??720}}async stopAll(){let e=[...this.sessions.keys()];if(await Promise.all(e.map(t=>this.closeSession(t))),this.browser){try{await this.browser.close()}catch{}this.browser=null}}};import{exec as ya}from"node:child_process";import{promisify as va}from"node:util";var os=va(ya),nt=class{monitors=new Map;portCache=new Map;workspaceTerminals=new Map;broadcast;resolvePid;scanIntervalMs=3e3;constructor(e,t){this.broadcast=e,this.resolvePid=t}async startMonitoring(e,t){this.stopMonitoring(e),this.workspaceTerminals.set(e,t),await this.scan(e);let r=setInterval(()=>{this.scan(e).catch(console.error)},this.scanIntervalMs);this.monitors.set(e,r)}stopMonitoring(e){let t=this.monitors.get(e);t&&(clearInterval(t),this.monitors.delete(e)),this.portCache.delete(e),this.workspaceTerminals.delete(e)}listPorts(e){return this.portCache.get(e)||[]}listAllWorkspacePorts(){let e=new Set,t=[];for(let r of this.portCache.values())for(let s of r){let n=`${s.port}:${s.pid}`;e.has(n)||(e.add(n),t.push(s))}return t.sort((r,s)=>r.port-s.port),t}async listSystemPorts(){return this.detectListeningPorts()}async killPort(e,t){try{process.kill(t,"SIGTERM"),await new Promise(r=>setTimeout(r,2e3));try{process.kill(t,0),process.kill(t,"SIGKILL")}catch{}return{success:!0}}catch(r){return{success:!1,error:r instanceof Error?r.message:String(r)}}}async scan(e){try{let t=this.workspaceTerminals.get(e)||[],r=[];for(let d of t){let u=this.resolvePid(d);u&&u>0&&r.push(u)}if(r.length===0){(this.portCache.get(e)||[]).length>0&&(this.portCache.set(e,[]),this.broadcast("ports.update",{workspaceId:e,ports:[],timestamp:Date.now()}));return}let{allDescendantPids:s,pidToTerminal:n}=await this.buildProcessTree(r,t),o=(await this.detectListeningPorts()).filter(d=>s.has(d.pid));for(let d of o){let u=n.get(d.pid);u&&(d.terminalId=u)}let c=this.portCache.get(e)||[],l=this.portsChanged(c,o);if(this.portCache.set(e,o),l){let d={workspaceId:e,ports:o,timestamp:Date.now()};this.broadcast("ports.update",d)}}catch(t){console.error("[PortMonitor] scan error:",t)}}async buildProcessTree(e,t){let r=new Set(e),s=new Map;try{let{stdout:n}=await os("ps -eo ppid=,pid= 2>/dev/null || true",{timeout:3e3}),i=new Map;for(let o of n.trim().split(`
121
121
  `)){let c=o.trim().split(/\s+/);if(c.length<2)continue;let l=parseInt(c[0],10),d=parseInt(c[1],10);if(isNaN(l)||isNaN(d))continue;let u=i.get(l);u||(u=[],i.set(l,u)),u.push(d)}for(let o of t){let c=this.resolvePid(o);if(!c||c<=0)continue;let l=[c];for(s.set(c,o);l.length>0;){let d=l.pop(),u=i.get(d);if(u)for(let p of u)r.has(p)||(r.add(p),s.set(p,o),l.push(p))}}}catch{}return{allDescendantPids:r,pidToTerminal:s}}async detectListeningPorts(){let e=process.platform;try{if(e==="darwin"||e==="linux"){let{stdout:t}=await os("lsof -i -P -n -sTCP:LISTEN 2>/dev/null || true",{timeout:5e3});return this.parseLsofOutput(t)}return[]}catch{return[]}}parseLsofOutput(e){let t=e.trim().split(`
122
- `);if(t.length<2)return[];let r=[],s=new Set;for(let n=1;n<t.length;n++){let i=t[n].split(/\s+/);if(i.length<9)continue;let o=i[0],c=parseInt(i[1],10),l=i[8];if(o==="launchd"||o==="systemd")continue;let d=l.lastIndexOf(":");if(d===-1)continue;let u=l.substring(0,d),p=parseInt(l.substring(d+1),10);if(isNaN(p)||p<=0)continue;let m=`${p}:${c}`;if(s.has(m))continue;s.add(m);let h=u==="*"?"0.0.0.0":u;r.push({port:p,protocol:"tcp",pid:c,process:o,localAddress:h,detectedAt:Date.now()})}return r.sort((n,i)=>n.port-i.port),r}portsChanged(e,t){if(e.length!==t.length)return!0;let r=new Set(e.map(s=>`${s.port}:${s.pid}`));return t.some(s=>!r.has(`${s.port}:${s.pid}`))}dispose(){for(let[e]of this.monitors)this.stopMonitoring(e)}};import{spawn as va}from"node:child_process";import{exec as ba}from"node:child_process";import{promisify as ka}from"node:util";import{randomBytes as Ia}from"node:crypto";var Ra=ka(ba),Aa=/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/,at=class{process=null;url=null;active=!1;startedAt=null;lastError=null;authToken=null;broadcast;constructor(e){this.broadcast=e}async isCloudflaredInstalled(){try{return await Ra("which cloudflared"),!0}catch{return!1}}async startTunnel(e){if(this.active)return;if(!await this.isCloudflaredInstalled()){let i="cloudflared is not installed. Install it from https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/";throw this.lastError=i,this.broadcast("tunnel.status",{active:!1,error:i}),new Error(i)}let r=e?.port??7773,s=["tunnel","--url",`${e?.protocol??"http"}://localhost:${r}`];e?.hostname&&s.push("--hostname",e.hostname),this.process=va("cloudflared",s,{stdio:["ignore","pipe","pipe"]}),this.active=!0,this.startedAt=new Date().toISOString(),this.lastError=null,this.authToken=Ia(32).toString("hex");let n=i=>{let c=i.toString().match(Aa);c&&!this.url&&(this.url=c[0],this.broadcast("tunnel.url",{url:this.url}),this.broadcast("tunnel.status",{active:!0,url:this.url}))};this.process.stdout?.on("data",n),this.process.stderr?.on("data",n),this.process.on("exit",i=>{let o=this.active;if(this.active=!1,this.url=null,this.startedAt=null,this.process=null,o){let c=i!==0?`cloudflared exited with code ${i}`:void 0;c&&(this.lastError=c),this.broadcast("tunnel.status",{active:!1,error:c})}}),this.process.on("error",i=>{this.active=!1,this.url=null,this.startedAt=null,this.process=null,this.lastError=i.message,this.broadcast("tunnel.status",{active:!1,error:i.message})}),this.broadcast("tunnel.status",{active:!0})}stopTunnel(){this.process&&(this.process.kill(),this.active=!1,this.url=null,this.startedAt=null,this.process=null,this.authToken=null,this.broadcast("tunnel.status",{active:!1}))}async getStatus(){let e=await this.isCloudflaredInstalled();return{active:this.active,url:this.url??void 0,pid:this.process?.pid,startedAt:this.startedAt??void 0,error:this.lastError??void 0,isInstalled:e,token:this.authToken??void 0}}getUrl(){return this.url}getToken(){return this.authToken}isActive(){return this.active}validateToken(e){return!this.active||!this.authToken?!0:e===this.authToken}};import{spawn as Ca}from"node:child_process";import{exec as La}from"node:child_process";import{promisify as Ma}from"node:util";var cs=Ma(La),Oa=/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/,ls=10,it=class{tunnels=new Map;broadcast;constructor(e){this.broadcast=e}async startTunnel(e,t){if(this.tunnels.has(e))return;if(this.tunnels.size>=ls)throw new Error(`Maximum of ${ls} port tunnels reached`);try{await cs("which cloudflared")}catch{throw new Error("cloudflared is not installed. Install it from https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/")}let r=`${t??"http"}://localhost:${e}`,s=Ca("cloudflared",["tunnel","--url",r],{stdio:["ignore","pipe","pipe"]}),n={process:s,url:null,active:!0,startedAt:new Date().toISOString(),error:null};this.tunnels.set(e,n),this.broadcastUpdate();let i=o=>{let l=o.toString().match(Oa);l&&!n.url&&(n.url=l[0],this.broadcastUpdate())};s.stdout?.on("data",i),s.stderr?.on("data",i),s.on("exit",o=>{let c=this.tunnels.get(e);c&&c.process===s&&(o!==0&&(c.error=`cloudflared exited with code ${o}`),c.active=!1,this.tunnels.delete(e),this.broadcastUpdate())}),s.on("error",o=>{let c=this.tunnels.get(e);c&&c.process===s&&(c.error=o.message,c.active=!1,this.tunnels.delete(e),this.broadcastUpdate())})}stopTunnel(e){let t=this.tunnels.get(e);if(t){try{t.process.kill()}catch{}this.tunnels.delete(e),this.broadcastUpdate()}}stopAll(){for(let[,e]of this.tunnels)try{e.process.kill()}catch{}this.tunnels.clear(),this.broadcastUpdate()}async checkInstalled(){try{return await cs("which cloudflared"),!0}catch{return!1}}getTunnels(){let e=[];for(let[t,r]of this.tunnels)e.push({port:t,url:r.url??void 0,active:r.active,startedAt:r.startedAt,error:r.error??void 0});return e}getTunnelForPort(e){let t=this.tunnels.get(e);if(t)return{port:e,url:t.url??void 0,active:t.active,startedAt:t.startedAt,error:t.error??void 0}}cleanupStaleTunnels(e){let t=new Set(e);for(let r of this.tunnels.keys())t.has(r)||this.stopTunnel(r)}broadcastUpdate(){this.broadcast("portTunnels.update",{tunnels:this.getTunnels()})}};import{readFileSync as Na,writeFileSync as ds,readdirSync as Da,unlinkSync as Pa,mkdirSync as xa,existsSync as us,statSync as _a}from"node:fs";import{join as ge,basename as Ua}from"node:path";function Fa(a){return a.toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9\-_]/g,"")}function ot(a){return ge(a,".swarm","prd","wireframes")}function ct(a,e){let t=Na(a,"utf-8"),r=_a(a),s=e.replace(/-/g," ").replace(/\b\w/g,n=>n.toUpperCase());return{id:e,name:s,content:t,updatedAt:r.mtime.toISOString()}}function Ba(a){let e=a.toLowerCase();return/login|signup|register|auth/.test(e)?`\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
122
+ `);if(t.length<2)return[];let r=[],s=new Set;for(let n=1;n<t.length;n++){let i=t[n].split(/\s+/);if(i.length<9)continue;let o=i[0],c=parseInt(i[1],10),l=i[8];if(o==="launchd"||o==="systemd")continue;let d=l.lastIndexOf(":");if(d===-1)continue;let u=l.substring(0,d),p=parseInt(l.substring(d+1),10);if(isNaN(p)||p<=0)continue;let m=`${p}:${c}`;if(s.has(m))continue;s.add(m);let h=u==="*"?"0.0.0.0":u;r.push({port:p,protocol:"tcp",pid:c,process:o,localAddress:h,detectedAt:Date.now()})}return r.sort((n,i)=>n.port-i.port),r}portsChanged(e,t){if(e.length!==t.length)return!0;let r=new Set(e.map(s=>`${s.port}:${s.pid}`));return t.some(s=>!r.has(`${s.port}:${s.pid}`))}dispose(){for(let[e]of this.monitors)this.stopMonitoring(e)}};import{spawn as ba}from"node:child_process";import{exec as ka}from"node:child_process";import{promisify as Ia}from"node:util";import{randomBytes as Ra}from"node:crypto";var Aa=Ia(ka),Ca=/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/,at=class{process=null;url=null;active=!1;startedAt=null;lastError=null;authToken=null;broadcast;constructor(e){this.broadcast=e}async isCloudflaredInstalled(){try{return await Aa("which cloudflared"),!0}catch{return!1}}async startTunnel(e){if(this.active)return;if(!await this.isCloudflaredInstalled()){let i="cloudflared is not installed. Install it from https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/";throw this.lastError=i,this.broadcast("tunnel.status",{active:!1,error:i}),new Error(i)}let r=e?.port??7773,s=["tunnel","--url",`${e?.protocol??"http"}://localhost:${r}`];e?.hostname&&s.push("--hostname",e.hostname),this.process=ba("cloudflared",s,{stdio:["ignore","pipe","pipe"]}),this.active=!0,this.startedAt=new Date().toISOString(),this.lastError=null,this.authToken=Ra(32).toString("hex");let n=i=>{let c=i.toString().match(Ca);c&&!this.url&&(this.url=c[0],this.broadcast("tunnel.url",{url:this.url}),this.broadcast("tunnel.status",{active:!0,url:this.url}))};this.process.stdout?.on("data",n),this.process.stderr?.on("data",n),this.process.on("exit",i=>{let o=this.active;if(this.active=!1,this.url=null,this.startedAt=null,this.process=null,o){let c=i!==0?`cloudflared exited with code ${i}`:void 0;c&&(this.lastError=c),this.broadcast("tunnel.status",{active:!1,error:c})}}),this.process.on("error",i=>{this.active=!1,this.url=null,this.startedAt=null,this.process=null,this.lastError=i.message,this.broadcast("tunnel.status",{active:!1,error:i.message})}),this.broadcast("tunnel.status",{active:!0})}stopTunnel(){this.process&&(this.process.kill(),this.active=!1,this.url=null,this.startedAt=null,this.process=null,this.authToken=null,this.broadcast("tunnel.status",{active:!1}))}async getStatus(){let e=await this.isCloudflaredInstalled();return{active:this.active,url:this.url??void 0,pid:this.process?.pid,startedAt:this.startedAt??void 0,error:this.lastError??void 0,isInstalled:e,token:this.authToken??void 0}}getUrl(){return this.url}getToken(){return this.authToken}isActive(){return this.active}validateToken(e){return!this.active||!this.authToken?!0:e===this.authToken}};import{spawn as La}from"node:child_process";import{exec as Ma}from"node:child_process";import{promisify as Oa}from"node:util";var cs=Oa(Ma),Na=/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/,ls=10,it=class{tunnels=new Map;broadcast;constructor(e){this.broadcast=e}async startTunnel(e,t){if(this.tunnels.has(e))return;if(this.tunnels.size>=ls)throw new Error(`Maximum of ${ls} port tunnels reached`);try{await cs("which cloudflared")}catch{throw new Error("cloudflared is not installed. Install it from https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/")}let r=`${t??"http"}://localhost:${e}`,s=La("cloudflared",["tunnel","--url",r],{stdio:["ignore","pipe","pipe"]}),n={process:s,url:null,active:!0,startedAt:new Date().toISOString(),error:null};this.tunnels.set(e,n),this.broadcastUpdate();let i=o=>{let l=o.toString().match(Na);l&&!n.url&&(n.url=l[0],this.broadcastUpdate())};s.stdout?.on("data",i),s.stderr?.on("data",i),s.on("exit",o=>{let c=this.tunnels.get(e);c&&c.process===s&&(o!==0&&(c.error=`cloudflared exited with code ${o}`),c.active=!1,this.tunnels.delete(e),this.broadcastUpdate())}),s.on("error",o=>{let c=this.tunnels.get(e);c&&c.process===s&&(c.error=o.message,c.active=!1,this.tunnels.delete(e),this.broadcastUpdate())})}stopTunnel(e){let t=this.tunnels.get(e);if(t){try{t.process.kill()}catch{}this.tunnels.delete(e),this.broadcastUpdate()}}stopAll(){for(let[,e]of this.tunnels)try{e.process.kill()}catch{}this.tunnels.clear(),this.broadcastUpdate()}async checkInstalled(){try{return await cs("which cloudflared"),!0}catch{return!1}}getTunnels(){let e=[];for(let[t,r]of this.tunnels)e.push({port:t,url:r.url??void 0,active:r.active,startedAt:r.startedAt,error:r.error??void 0});return e}getTunnelForPort(e){let t=this.tunnels.get(e);if(t)return{port:e,url:t.url??void 0,active:t.active,startedAt:t.startedAt,error:t.error??void 0}}cleanupStaleTunnels(e){let t=new Set(e);for(let r of this.tunnels.keys())t.has(r)||this.stopTunnel(r)}broadcastUpdate(){this.broadcast("portTunnels.update",{tunnels:this.getTunnels()})}};import{readFileSync as Da,writeFileSync as ds,readdirSync as Pa,unlinkSync as xa,mkdirSync as _a,existsSync as us,statSync as Ua}from"node:fs";import{join as ge,basename as Fa}from"node:path";function Ba(a){return a.toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9\-_]/g,"")}function ot(a){return ge(a,".swarm","prd","wireframes")}function ct(a,e){let t=Da(a,"utf-8"),r=Ua(a),s=e.replace(/-/g," ").replace(/\b\w/g,n=>n.toUpperCase());return{id:e,name:s,content:t,updatedAt:r.mtime.toISOString()}}function Wa(a){let e=a.toLowerCase();return/login|signup|register|auth/.test(e)?`\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
123
123
  \u2502 LOGIN \u2502
124
124
  \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524
125
125
  \u2502 \u2502
@@ -252,23 +252,23 @@ You can document your own discoveries for teammates to benefit from.`),s.push(""
252
252
  \u2502 \u2502
253
253
  \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524
254
254
  \u2502 FOOTER \u2502
255
- \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518`}var lt=class{broadcast;constructor(e){this.broadcast=e}ensureDir(e){let t=ot(e);return xa(t,{recursive:!0}),t}list(e){let t=this.ensureDir(e);return Da(t).filter(s=>s.endsWith(".txt")).map(s=>{let n=Ua(s,".txt");return ct(ge(t,s),n)})}get(e,t){let r=ot(e),s=ge(r,`${t}.txt`);return us(s)?ct(s,t):null}create(e,t){let r=this.ensureDir(e),s=Fa(t.name),n=ge(r,`${s}.txt`),i;t.content?i=t.content:t.description?i=`# ${t.name}
255
+ \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518`}var lt=class{broadcast;constructor(e){this.broadcast=e}ensureDir(e){let t=ot(e);return _a(t,{recursive:!0}),t}list(e){let t=this.ensureDir(e);return Pa(t).filter(s=>s.endsWith(".txt")).map(s=>{let n=Fa(s,".txt");return ct(ge(t,s),n)})}get(e,t){let r=ot(e),s=ge(r,`${t}.txt`);return us(s)?ct(s,t):null}create(e,t){let r=this.ensureDir(e),s=Ba(t.name),n=ge(r,`${s}.txt`),i;t.content?i=t.content:t.description?i=`# ${t.name}
256
256
  # ${t.description}
257
257
 
258
258
  `:i=`# ${t.name}
259
259
 
260
- `,ds(n,i,"utf-8");let o=ct(n,s);return this.broadcast("wireframe.created",{wireframe:o}),o}update(e,t,r){let s=ot(e),n=ge(s,`${t}.txt`);ds(n,r,"utf-8");let i=ct(n,t);return this.broadcast("wireframe.updated",{wireframe:i}),i}delete(e,t){let r=ot(e),s=ge(r,`${t}.txt`);us(s)&&Pa(s),this.broadcast("wireframe.deleted",{id:t})}generate(e,t,r){let s=Ba(r);return this.update(e,t,s)}};import{randomUUID as Wa}from"node:crypto";var dt=class{db;constructor(e){this.db=e}list(){return this.db.prepare("SELECT * FROM command_templates ORDER BY name ASC").all().map(r=>this.hydrate(r))}get(e){let r=this.db.prepare("SELECT * FROM command_templates WHERE id = ?").get(e);return r?this.hydrate(r):null}create(e){let t=Wa(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO command_templates (id, name, description, command, steps, createdAt, updatedAt)
261
- VALUES (?, ?, ?, ?, ?, ?, ?)`).run(t,e.name,e.description||"",e.command||"",JSON.stringify(e.steps),r,r),this.get(t)}update(e){let t=this.get(e.id);if(!t)return null;let r=new Date().toISOString();return this.db.prepare("UPDATE command_templates SET name = ?, description = ?, command = ?, steps = ?, updatedAt = ? WHERE id = ?").run(e.name??t.name,e.description??t.description,e.command??t.command,e.steps?JSON.stringify(e.steps):JSON.stringify(t.steps),r,e.id),this.get(e.id)}delete(e){return this.db.prepare("DELETE FROM command_templates WHERE id = ?").run(e).changes>0}hydrate(e){return{id:e.id,name:e.name,description:e.description,command:e.command,steps:JSON.parse(e.steps),createdAt:e.createdAt,updatedAt:e.updatedAt}}};import{randomUUID as ps}from"node:crypto";var $a=[{name:"Monorepo",description:"Frontend + Backend + DB + Dev Server",color:"#7C3AED",logo:"\u{1F4E6}",defaultCommand:"claude",terminals:[{label:"Frontend",directory:"apps/web",command:""},{label:"Backend",directory:"apps/api",command:""},{label:"Database",directory:"packages/db",command:""},{label:"Dev Server",directory:".",command:"pnpm install",commandSequence:[{command:"pnpm dev",delay:3e3}]}]},{name:"Fullstack",description:"Client + Server com install automatico",color:"#2563EB",logo:"\u{1F517}",defaultCommand:"",terminals:[{label:"Client",directory:"client",command:"npm install",commandSequence:[{command:"npm run dev",delay:5e3}]},{label:"Server",directory:"server",command:"npm install",commandSequence:[{command:"npm run dev",delay:5e3}]}]},{name:"Multi-Agent",description:"4 agentes Claude em paralelo",color:"#059669",logo:"\u{1F916}",defaultCommand:"claude",terminals:[{label:"Agent 1",directory:".",command:""},{label:"Agent 2",directory:".",command:""},{label:"Agent 3",directory:".",command:""},{label:"Agent 4",directory:".",command:""}]},{name:"Next.js",description:"Create + Dev + Prisma",color:"#000000",logo:"\u25B2",defaultCommand:"",terminals:[{label:"App",directory:".",command:"npm run dev"},{label:"Prisma Studio",directory:".",command:"npx prisma studio"},{label:"Claude",directory:".",command:"claude"}]},{name:"Docker",description:"Build + Up + Logs",color:"#0891B2",logo:"\u{1F433}",defaultCommand:"",terminals:[{label:"Docker Up",directory:".",command:"docker compose up -d",commandSequence:[{command:"docker compose logs -f",delay:3e3}]},{label:"Shell",directory:".",command:""}]},{name:"Python",description:"Venv + Install + Run",color:"#CA8A04",logo:"\u{1F40D}",defaultCommand:"",terminals:[{label:"App",directory:".",command:"python -m venv .venv",commandSequence:[{command:"source .venv/bin/activate",delay:1e3},{command:"pip install -r requirements.txt",delay:500},{command:"python main.py",delay:5e3}]},{label:"Tests",directory:".",command:"source .venv/bin/activate",commandSequence:[{command:"pytest --watch",delay:1e3}]}]},{name:"Simple",description:"Terminal unico",color:"#EA580C",logo:"\u{1F4BB}",defaultCommand:"",terminals:[{label:"Terminal 1",directory:".",command:""}]}],ut=class{db;constructor(e){this.db=e}list(){return this.db.prepare("SELECT * FROM workspace_templates ORDER BY name ASC").all().map(r=>this.hydrate(r))}get(e){let r=this.db.prepare("SELECT * FROM workspace_templates WHERE id = ?").get(e);return r?this.hydrate(r):null}create(e){let t=ps(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO workspace_templates (id, name, description, color, logo, version, defaultCommand, terminals, isBuiltIn, createdAt, updatedAt)
260
+ `,ds(n,i,"utf-8");let o=ct(n,s);return this.broadcast("wireframe.created",{wireframe:o}),o}update(e,t,r){let s=ot(e),n=ge(s,`${t}.txt`);ds(n,r,"utf-8");let i=ct(n,t);return this.broadcast("wireframe.updated",{wireframe:i}),i}delete(e,t){let r=ot(e),s=ge(r,`${t}.txt`);us(s)&&xa(s),this.broadcast("wireframe.deleted",{id:t})}generate(e,t,r){let s=Wa(r);return this.update(e,t,s)}};import{randomUUID as $a}from"node:crypto";var dt=class{db;constructor(e){this.db=e}list(){return this.db.prepare("SELECT * FROM command_templates ORDER BY name ASC").all().map(r=>this.hydrate(r))}get(e){let r=this.db.prepare("SELECT * FROM command_templates WHERE id = ?").get(e);return r?this.hydrate(r):null}create(e){let t=$a(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO command_templates (id, name, description, command, steps, createdAt, updatedAt)
261
+ VALUES (?, ?, ?, ?, ?, ?, ?)`).run(t,e.name,e.description||"",e.command||"",JSON.stringify(e.steps),r,r),this.get(t)}update(e){let t=this.get(e.id);if(!t)return null;let r=new Date().toISOString();return this.db.prepare("UPDATE command_templates SET name = ?, description = ?, command = ?, steps = ?, updatedAt = ? WHERE id = ?").run(e.name??t.name,e.description??t.description,e.command??t.command,e.steps?JSON.stringify(e.steps):JSON.stringify(t.steps),r,e.id),this.get(e.id)}delete(e){return this.db.prepare("DELETE FROM command_templates WHERE id = ?").run(e).changes>0}hydrate(e){return{id:e.id,name:e.name,description:e.description,command:e.command,steps:JSON.parse(e.steps),createdAt:e.createdAt,updatedAt:e.updatedAt}}};import{randomUUID as ps}from"node:crypto";var Ha=[{name:"Monorepo",description:"Frontend + Backend + DB + Dev Server",color:"#7C3AED",logo:"\u{1F4E6}",defaultCommand:"claude",terminals:[{label:"Frontend",directory:"apps/web",command:""},{label:"Backend",directory:"apps/api",command:""},{label:"Database",directory:"packages/db",command:""},{label:"Dev Server",directory:".",command:"pnpm install",commandSequence:[{command:"pnpm dev",delay:3e3}]}]},{name:"Fullstack",description:"Client + Server com install automatico",color:"#2563EB",logo:"\u{1F517}",defaultCommand:"",terminals:[{label:"Client",directory:"client",command:"npm install",commandSequence:[{command:"npm run dev",delay:5e3}]},{label:"Server",directory:"server",command:"npm install",commandSequence:[{command:"npm run dev",delay:5e3}]}]},{name:"Multi-Agent",description:"4 agentes Claude em paralelo",color:"#059669",logo:"\u{1F916}",defaultCommand:"claude",terminals:[{label:"Agent 1",directory:".",command:""},{label:"Agent 2",directory:".",command:""},{label:"Agent 3",directory:".",command:""},{label:"Agent 4",directory:".",command:""}]},{name:"Next.js",description:"Create + Dev + Prisma",color:"#000000",logo:"\u25B2",defaultCommand:"",terminals:[{label:"App",directory:".",command:"npm run dev"},{label:"Prisma Studio",directory:".",command:"npx prisma studio"},{label:"Claude",directory:".",command:"claude"}]},{name:"Docker",description:"Build + Up + Logs",color:"#0891B2",logo:"\u{1F433}",defaultCommand:"",terminals:[{label:"Docker Up",directory:".",command:"docker compose up -d",commandSequence:[{command:"docker compose logs -f",delay:3e3}]},{label:"Shell",directory:".",command:""}]},{name:"Python",description:"Venv + Install + Run",color:"#CA8A04",logo:"\u{1F40D}",defaultCommand:"",terminals:[{label:"App",directory:".",command:"python -m venv .venv",commandSequence:[{command:"source .venv/bin/activate",delay:1e3},{command:"pip install -r requirements.txt",delay:500},{command:"python main.py",delay:5e3}]},{label:"Tests",directory:".",command:"source .venv/bin/activate",commandSequence:[{command:"pytest --watch",delay:1e3}]}]},{name:"Simple",description:"Terminal unico",color:"#EA580C",logo:"\u{1F4BB}",defaultCommand:"",terminals:[{label:"Terminal 1",directory:".",command:""}]}],ut=class{db;constructor(e){this.db=e}list(){return this.db.prepare("SELECT * FROM workspace_templates ORDER BY name ASC").all().map(r=>this.hydrate(r))}get(e){let r=this.db.prepare("SELECT * FROM workspace_templates WHERE id = ?").get(e);return r?this.hydrate(r):null}create(e){let t=ps(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO workspace_templates (id, name, description, color, logo, version, defaultCommand, terminals, isBuiltIn, createdAt, updatedAt)
262
262
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?)`).run(t,e.name,e.description||"",e.color,e.logo||"",e.version||"1.00",e.defaultCommand||"",JSON.stringify(e.terminals),r,r),this.get(t)}update(e){let t=this.get(e.id);if(!t)return null;let r=new Date().toISOString();return this.db.prepare("UPDATE workspace_templates SET name = ?, description = ?, color = ?, logo = ?, version = ?, defaultCommand = ?, terminals = ?, updatedAt = ? WHERE id = ?").run(e.name??t.name,e.description??t.description,e.color??t.color,e.logo??t.logo,e.version??t.version,e.defaultCommand??t.defaultCommand,e.terminals?JSON.stringify(e.terminals):JSON.stringify(t.terminals),r,e.id),this.get(e.id)}delete(e){return this.db.prepare("DELETE FROM workspace_templates WHERE id = ?").run(e).changes>0}seed(){let e=this.db.prepare("SELECT COUNT(*) as count FROM workspace_templates WHERE isBuiltIn = 1"),{count:t}=e.get();if(t>0)return;let r=new Date().toISOString(),s=this.db.prepare(`INSERT INTO workspace_templates (id, name, description, color, logo, version, defaultCommand, terminals, isBuiltIn, createdAt, updatedAt)
263
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`);for(let n of $a)s.run(ps(),n.name,n.description,n.color,n.logo,"1.00",n.defaultCommand,JSON.stringify(n.terminals),r,r)}hydrate(e){return{id:e.id,name:e.name,description:e.description,color:e.color,logo:e.logo,version:e.version||"1.00",defaultCommand:e.defaultCommand,terminals:JSON.parse(e.terminals),isBuiltIn:e.isBuiltIn===1,createdAt:e.createdAt,updatedAt:e.updatedAt}}};import{randomUUID as Ha}from"node:crypto";var pt=class{db;constructor(e){this.db=e}list(e,t){return t?this.db.prepare("SELECT * FROM saved_layouts WHERE areaId = ? ORDER BY createdAt ASC").all(t).map(o=>this.hydrate(o)):this.db.prepare("SELECT * FROM saved_layouts WHERE workspaceId = ? ORDER BY createdAt ASC").all(e).map(n=>this.hydrate(n))}get(e){let r=this.db.prepare("SELECT * FROM saved_layouts WHERE id = ?").get(e);return r?this.hydrate(r):null}save(e){let t=e.areaId||e.workspaceId,r=e.areaId?"areaId":"workspaceId",s=this.db.prepare(`SELECT COUNT(*) as count FROM saved_layouts WHERE ${r} = ?`),{count:n}=s.get(t);if(n>=5)throw new Error(`Maximum of ${5} saved layouts reached`);let i=Ha(),o=new Date().toISOString(),c={tree:e.tree,panels:e.panels,promotedBrowser:e.promotedBrowser};return this.db.prepare(`INSERT INTO saved_layouts (id, workspaceId, areaId, name, isDefault, version, data, createdAt, updatedAt)
263
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`);for(let n of Ha)s.run(ps(),n.name,n.description,n.color,n.logo,"1.00",n.defaultCommand,JSON.stringify(n.terminals),r,r)}hydrate(e){return{id:e.id,name:e.name,description:e.description,color:e.color,logo:e.logo,version:e.version||"1.00",defaultCommand:e.defaultCommand,terminals:JSON.parse(e.terminals),isBuiltIn:e.isBuiltIn===1,createdAt:e.createdAt,updatedAt:e.updatedAt}}};import{randomUUID as qa}from"node:crypto";var pt=class{db;constructor(e){this.db=e}list(e,t){return t?this.db.prepare("SELECT * FROM saved_layouts WHERE areaId = ? ORDER BY createdAt ASC").all(t).map(o=>this.hydrate(o)):this.db.prepare("SELECT * FROM saved_layouts WHERE workspaceId = ? ORDER BY createdAt ASC").all(e).map(n=>this.hydrate(n))}get(e){let r=this.db.prepare("SELECT * FROM saved_layouts WHERE id = ?").get(e);return r?this.hydrate(r):null}save(e){let t=e.areaId||e.workspaceId,r=e.areaId?"areaId":"workspaceId",s=this.db.prepare(`SELECT COUNT(*) as count FROM saved_layouts WHERE ${r} = ?`),{count:n}=s.get(t);if(n>=5)throw new Error(`Maximum of ${5} saved layouts reached`);let i=qa(),o=new Date().toISOString(),c={tree:e.tree,panels:e.panels,promotedBrowser:e.promotedBrowser};return this.db.prepare(`INSERT INTO saved_layouts (id, workspaceId, areaId, name, isDefault, version, data, createdAt, updatedAt)
264
264
  VALUES (?, ?, ?, ?, ?, 1, ?, ?, ?)`).run(i,e.workspaceId,e.areaId||null,e.name,e.isDefault?1:0,JSON.stringify(c),o,o),e.isDefault&&this.clearDefaultExcept(e.workspaceId,i,e.areaId),this.get(i)}update(e,t){let r=this.get(e);if(!r)return null;let s=new Date().toISOString(),n={tree:t.tree??r.tree,panels:t.panels??r.panels,promotedBrowser:t.promotedBrowser!==void 0?t.promotedBrowser:r.promotedBrowser};return this.db.prepare("UPDATE saved_layouts SET name = ?, data = ?, updatedAt = ? WHERE id = ?").run(t.name??r.name,JSON.stringify(n),s,e),this.get(e)}delete(e){return this.db.prepare("DELETE FROM saved_layouts WHERE id = ?").run(e).changes>0}setDefault(e,t,r){this.clearDefaultExcept(e,t,r),r?this.db.prepare("UPDATE saved_layouts SET isDefault = 1 WHERE id = ? AND areaId = ?").run(t,r):this.db.prepare("UPDATE saved_layouts SET isDefault = 1 WHERE id = ? AND workspaceId = ?").run(t,e)}getDefault(e,t){if(t){let i=this.db.prepare("SELECT * FROM saved_layouts WHERE areaId = ? AND isDefault = 1 LIMIT 1").get(t);return i?this.hydrate(i):null}let s=this.db.prepare("SELECT * FROM saved_layouts WHERE workspaceId = ? AND isDefault = 1 LIMIT 1").get(e);return s?this.hydrate(s):null}clearDefaultExcept(e,t,r){r?this.db.prepare("UPDATE saved_layouts SET isDefault = 0 WHERE areaId = ? AND id != ?").run(r,t):this.db.prepare("UPDATE saved_layouts SET isDefault = 0 WHERE workspaceId = ? AND id != ?").run(e,t)}hydrate(e){let t=JSON.parse(e.data);return{id:e.id,workspaceId:e.workspaceId,...e.areaId?{areaId:e.areaId}:{},name:e.name,isDefault:e.isDefault===1,version:e.version,tree:t.tree,panels:t.panels,promotedBrowser:t.promotedBrowser,createdAt:e.createdAt,updatedAt:e.updatedAt}}};import{randomUUID as W}from"node:crypto";var mt=class{db;constructor(e){this.db=e}list(){return this.db.prepare("SELECT * FROM stacks ORDER BY name ASC").all().map(r=>this.hydrate(r))}get(e){let r=this.db.prepare("SELECT * FROM stacks WHERE id = ?").get(e);return r?this.hydrate(r):null}create(e){let t=W(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO stacks (id, name, description, color, logo, version, steps, isBuiltIn, createdAt, updatedAt)
265
265
  VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, ?)`).run(t,e.name,e.description||"",e.color,e.logo||"",e.version||"1.00",JSON.stringify(e.steps),r,r),this.get(t)}update(e){let t=this.get(e.id);if(!t)return null;let r=new Date().toISOString();return this.db.prepare("UPDATE stacks SET name = ?, description = ?, color = ?, logo = ?, version = ?, steps = ?, updatedAt = ? WHERE id = ?").run(e.name??t.name,e.description??t.description,e.color??t.color,e.logo??t.logo,e.version??t.version,e.steps?JSON.stringify(e.steps):JSON.stringify(t.steps),r,e.id),this.get(e.id)}delete(e){return this.db.prepare("DELETE FROM stacks WHERE id = ?").run(e).changes>0}seed(e){let t=this.db.prepare("SELECT COUNT(*) as count FROM stacks WHERE isBuiltIn = 1"),{count:r}=t.get();if(r>0)return;let s=e.list(),n=h=>s.find(f=>f.name===h),i=new Date().toISOString(),o=this.db.prepare(`INSERT INTO stacks (id, name, description, color, logo, version, steps, isBuiltIn, createdAt, updatedAt)
266
- VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`),c=n("Next.js"),l=n("Docker"),d=n("Simple");if(c&&l&&d){let h=W(),f=W(),g=W(),w=[{id:h,templateId:c.id,order:0,targetArea:"new",newAreaName:"App",trigger:{type:"parallel"}},{id:f,templateId:l.id,order:1,targetArea:"new",newAreaName:"Services",trigger:{type:"waitForOutput",dependsOnStepId:h,dependsOnTerminalLabel:"App",waitForText:"Ready",timeoutMs:12e4}},{id:g,templateId:d.id,order:2,targetArea:"current",trigger:{type:"delay",delayMs:2e3,dependsOnStepId:f}}];o.run(W(),"Next Fullstack Pro","Next.js + Docker services + Shadcn UI","#000000","\u{1F680}","1.00",JSON.stringify(w),i,i)}let u=n("Python");if(l&&u){let h=W(),f=W(),g=[{id:h,templateId:l.id,order:0,targetArea:"new",newAreaName:"Database",trigger:{type:"parallel"}},{id:f,templateId:u.id,order:1,targetArea:"new",newAreaName:"API",trigger:{type:"waitForExit",dependsOnStepId:h,dependsOnTerminalLabel:"Docker Up",timeoutMs:6e4}}];o.run(W(),"Python API + DB","Docker DB + Python backend","#CA8A04","\u{1F40D}","1.00",JSON.stringify(g),i,i)}let p=n("Monorepo"),m=n("Multi-Agent");if(p&&m){let h=W(),f=W(),g=[{id:h,templateId:p.id,order:0,targetArea:"new",newAreaName:"Main",trigger:{type:"parallel"}},{id:f,templateId:m.id,order:1,targetArea:"new",newAreaName:"Agents",trigger:{type:"parallel"}}];o.run(W(),"Multi-Agent Monorepo","Monorepo + 4 agentes em paralelo","#7C3AED","\u{1F916}","1.00",JSON.stringify(g),i,i)}}hydrate(e){return{id:e.id,name:e.name,description:e.description,color:e.color,logo:e.logo,version:e.version||"1.00",steps:JSON.parse(e.steps),isBuiltIn:e.isBuiltIn===1,createdAt:e.createdAt,updatedAt:e.updatedAt}}};import{WebSocket as qa}from"ws";function he(a,e){a.readyState===qa.OPEN&&a.send(JSON.stringify(e))}function gs(a,e,t){return new Promise(r=>{let s=Date.now(),n=!1,i=setInterval(()=>{let o=a.has(e);if(o&&(n=!0),n&&!o){clearInterval(i),r();return}Date.now()-s>t&&(clearInterval(i),r())},200)})}function ve(a,e,t,r){return new Promise(s=>{let n=Date.now(),i=setInterval(()=>{if(a.outputContains(e,t)){clearInterval(i),s();return}Date.now()-n>r&&(clearInterval(i),s())},200)})}async function ne(a,e,t,r){let{terminalManager:s,areaManager:n}=e,i=null;for(let o of a){if(i){let c=!r?.ignoreRunOnce&&o.startRunOnce&&o.hasLaunched;!c&&o.startDelay&&o.startDelay>0&&await new Promise(l=>setTimeout(l,o.startDelay)),!c&&o.startWaitFor&&await ve(s,i,o.startWaitFor,6e4)}await s.open({id:o.id,cwd:o.cwd,command:o.command||void 0,commandSequence:o.commandSequence,env:o.env,cols:120,rows:30,closeAfterCommand:o.closeAfterCommand||void 0,closeDelay:o.closeDelay,closeWaitFor:o.closeWaitFor||void 0},r?.completedStepsProvider?{completedSteps:r.completedStepsProvider(o.id),onStepCompleted:(c,l)=>{r.onStepCompleted?.(c,l)}}:void 0),i=o.id}for(let o of a)n.markTerminalLaunched(o.id)}var Xa=300*1e3,gt=class{terminalManager;areaManager;workspaceTemplateManager;workspaceManager;constructor(e){this.terminalManager=e.terminalManager,this.areaManager=e.areaManager,this.workspaceTemplateManager=e.workspaceTemplateManager,this.workspaceManager=e.workspaceManager}async applyStack(e,t){let{stack:r,workspaceId:s,defaultAreaId:n,broadcast:i}=e,o=this.workspaceManager.get(s);if(!o)throw new Error(`Workspace not found: ${s}`);let c=o.rootDirectory,l=[...r.steps].sort((f,g)=>f.order-g.order),d=new Map,u=new Map,p=new Map;for(let f of l){let g,w=new Promise(E=>{g=E});d.set(f.id,w),u.set(f.id,g)}let m=new Promise((f,g)=>setTimeout(()=>g(new Error("Stack orchestration timed out")),Xa)),h=async()=>{let f=l.map(g=>this.runStep({step:g,stack:r,workspaceId:s,defaultAreaId:n,workspaceRootDir:c,stepStarted:d,stepStartedResolve:u,stepTerminalIds:p,broadcast:i,services:t}));await Promise.all(f)};try{await Promise.race([h(),m])}catch(f){console.error("[StackOrchestrator] Error during stack orchestration:",f)}}async runStep(e){let{step:t,stack:r,workspaceId:s,defaultAreaId:n,workspaceRootDir:i,stepStarted:o,stepStartedResolve:c,stepTerminalIds:l,broadcast:d,services:u}=e,{trigger:p}=t;await this.waitForStartCondition({trigger:p,stepStarted:o,stepTerminalIds:l,services:u});let m=this.workspaceTemplateManager.get(t.templateId);if(!m){console.warn(`[StackOrchestrator] Template not found for step ${t.id}: ${t.templateId}`),c.get(t.id)?.();return}let h;if(t.targetArea==="new"){let E=this.areaManager.create({workspaceId:s,name:t.newAreaName||m.name,color:t.newAreaColor||m.color,directory:"",useWorktree:!1,defaultCommand:m.defaultCommand,terminalCount:m.terminals.length,terminals:m.terminals.map(T=>({label:T.label,directory:T.directory,command:T.command,commandSequence:T.commandSequence,runOnce:!1,commandRunOnce:!1,startDelay:T.startDelay??0,startWaitFor:T.startWaitFor??"",startRunOnce:!1,closeAfterCommand:!1,closeDelay:1e3,closeWaitFor:""})),layout:"auto",templateId:m.id});h=E.id,d("area.updated",{workspaceId:s,area:E})}else{let E=this.areaManager.get(n);if(!E){console.warn(`[StackOrchestrator] Default area not found: ${n}`),c.get(t.id)?.();return}let T=E.terminals.map(I=>({id:I.id,label:I.label,directory:I.directory,command:I.command,commandSequence:I.commandSequence,runOnce:I.runOnce,commandRunOnce:I.commandRunOnce,startDelay:I.startDelay,startWaitFor:I.startWaitFor,startRunOnce:I.startRunOnce,closeAfterCommand:I.closeAfterCommand,closeDelay:I.closeDelay,closeWaitFor:I.closeWaitFor})),_=m.terminals.map(I=>({label:I.label,directory:I.directory,command:I.command,commandSequence:I.commandSequence,runOnce:!1,commandRunOnce:!1,startDelay:0,startWaitFor:"",startRunOnce:!1,closeAfterCommand:!1,closeDelay:1e3,closeWaitFor:""})),oe=[...T,..._];this.areaManager.update({id:n,terminalCount:oe.length,terminals:oe}),h=n;let P=this.areaManager.get(n);d("area.updated",{workspaceId:s,area:P})}c.get(t.id)?.(),d("stack.step.started",{stackId:r.id,stepId:t.id,areaId:h});let f=this.areaManager.get(h);if(!f)return;let g=this.areaManager.resolveForLaunch(f,i),w=t.targetArea==="current"?g.slice(g.length-m.terminals.length):g;l.set(t.id,w.map(E=>E.id));try{await ne(w,u,h)}catch(E){console.error(`[StackOrchestrator] Error launching terminals for step ${t.id}:`,E)}d("stack.step.completed",{stackId:r.id,stepId:t.id})}async waitForStartCondition(e){let{trigger:t,stepStarted:r,stepTerminalIds:s,services:n}=e;switch(t.type){case"parallel":{if(t.dependsOnStepId){let i=r.get(t.dependsOnStepId);i&&await i}break}case"delay":{if(t.dependsOnStepId){let i=r.get(t.dependsOnStepId);i&&await i}t.delayMs&&t.delayMs>0&&await new Promise(i=>setTimeout(i,t.delayMs));break}case"waitForOutput":{if(t.dependsOnStepId){let o=r.get(t.dependsOnStepId);o&&await o}let i=this.findTerminalByLabel(t.dependsOnStepId,t.dependsOnTerminalLabel,s,n);i&&t.waitForText&&await ve(n.terminalManager,i,t.waitForText,t.timeoutMs??12e4);break}case"waitForExit":{if(t.dependsOnStepId){let o=r.get(t.dependsOnStepId);o&&await o}let i=this.findTerminalByLabel(t.dependsOnStepId,t.dependsOnTerminalLabel,s,n);i&&await this.waitForTerminalExit(i,t.timeoutMs??6e4,n);break}}}findTerminalByLabel(e,t,r,s){if(!e||!t)return null;let n=r.get(e);if(!n)return null;for(let i of n)if(s.terminalManager.getProcessInfo(i)&&s.areaManager.db.prepare("SELECT label FROM terminal_configs WHERE id = ?").get(i)?.label===t)return i;for(let i of n)if(this.queryTerminalLabel(i)===t)return i;return n[0]??null}queryTerminalLabel(e){return this.areaManager.db.prepare("SELECT label FROM terminal_configs WHERE id = ?").get(e)?.label??null}waitForTerminalExit(e,t,r){return new Promise(s=>{let n=Date.now(),i=setInterval(()=>{let o=r.terminalManager.getProcessInfo(e);if(!o||o.isIdle){clearInterval(i),s();return}Date.now()-n>t&&(clearInterval(i),s())},500)})}};import{execSync as Jt}from"node:child_process";var ja=300*1e3,Ga=2e3,Qt=5e3,hs=[{cli:"claude",command:"claude",authCommand:"claude auth status",versionCommand:"claude --version",parseAuth:a=>{let e=a.toLowerCase();return e.includes("not logged in")||e.includes("login required")?!1:(e.includes("loggedin")||e.includes("logged in")||e.includes("authenticated")||e.includes("isloggedin"),!0)}},{cli:"codex",command:"codex",authCommand:"codex login status",versionCommand:"codex --version",parseAuth:a=>{let e=a.toLowerCase();return e.includes("not logged in")||e.includes("run `codex login`")?!1:(e.includes("logged in"),!0)}},{cli:"gemini",command:"gemini",authCommand:"gemini auth status",versionCommand:"gemini --version",parseAuth:a=>{let e=a.toLowerCase();return e.includes("not logged in")||e.includes("login required")||e.includes("not authenticated")?!1:(e.includes("logged in")||e.includes("authenticated"),!0)}}],ht=class{interval=null;startupTimer=null;lastResult=null;previousStates=new Map;broadcast;constructor(e){this.broadcast=e,this.startupTimer=setTimeout(()=>{this.checkAll(),this.startupTimer=null},Ga),this.interval=setInterval(()=>{this.checkAll()},ja)}async checkAll(){let e=[];for(let r of hs){let s=await this.checkOne(r.cli);e.push(s)}let t={providers:e,checkedAt:new Date().toISOString()};for(let r of e){let s=this.previousStates.get(r.cli);s&&s==="connected"&&r.state==="disconnected"&&this.broadcast("notification.new",{type:"warning",title:`${r.cli} disconnected`,message:`${r.cli} CLI lost authentication. Re-authenticate to continue using it.`,source:"health-check"}),this.previousStates.set(r.cli,r.state)}return this.lastResult=t,this.broadcast("health.status",t),t}async checkOne(e){let t=hs.find(c=>c.cli===e);if(!t)return{cli:e,state:"not_installed",installed:!1,authenticated:!1,lastCheckedAt:new Date().toISOString()};let r;try{r=Jt(`which ${t.command}`,{encoding:"utf8",timeout:Qt,stdio:["pipe","pipe","pipe"]}).trim()}catch{return{cli:e,state:"not_installed",installed:!1,authenticated:!1,lastCheckedAt:new Date().toISOString()}}let s;try{s=Jt(t.versionCommand,{encoding:"utf8",timeout:Qt,stdio:["pipe","pipe","pipe"]}).trim()}catch{}let n=!1,i="disconnected",o;try{let c=Jt(t.authCommand,{encoding:"utf8",timeout:Qt,stdio:["pipe","pipe","pipe"]});n=t.parseAuth(c),i=n?"connected":"disconnected"}catch(c){i="disconnected",o=c instanceof Error?c.message:"Auth check failed"}return{cli:e,state:i,installed:!0,version:s,path:r,authenticated:n,lastCheckedAt:new Date().toISOString(),error:o}}getLastResult(){return this.lastResult}dispose(){this.interval&&(clearInterval(this.interval),this.interval=null),this.startupTimer&&(clearTimeout(this.startupTimer),this.startupTimer=null)}};import{randomUUID as Ka}from"node:crypto";var fs=100,ft=class{notifications=[];broadcast;constructor(e){this.broadcast=e}add(e,t,r,s){let n={id:Ka(),type:e,title:t,message:r,source:s,read:!1,createdAt:new Date().toISOString()};return this.notifications.unshift(n),this.notifications.length>fs&&(this.notifications=this.notifications.slice(0,fs)),this.broadcast("notification.new",n),n}list(){return this.notifications}markRead(e){let t=this.notifications.find(r=>r.id===e);return t?(t.read=!0,!0):!1}clear(e){if(e){let t=this.notifications.findIndex(r=>r.id===e);return t===-1?!1:(this.notifications.splice(t,1),!0)}return this.clearAll(),!0}clearAll(){this.notifications=[]}};import{execFile as Ya}from"node:child_process";import{stat as Va,open as za}from"node:fs/promises";import{join as ws}from"node:path";import{promisify as Ja}from"node:util";var Qa=Ja(Ya),wt=class{async exec(e,t){return Qa("git",e,{cwd:t,maxBuffer:10*1024*1024})}async isGitRepo(e){try{return await this.exec(["rev-parse","--is-inside-work-tree"],e),!0}catch{return!1}}async init(e){let{stdout:t}=await this.exec(["init"],e);return{ok:!0,message:t.trim()}}async status(e){let{stdout:t}=await this.exec(["status","--porcelain=v2","--branch"],e),r=null,s=0,n=0,i=!1,o=[],c=[],l=[];for(let d of t.split(`
266
+ VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`),c=n("Next.js"),l=n("Docker"),d=n("Simple");if(c&&l&&d){let h=W(),f=W(),g=W(),w=[{id:h,templateId:c.id,order:0,targetArea:"new",newAreaName:"App",trigger:{type:"parallel"}},{id:f,templateId:l.id,order:1,targetArea:"new",newAreaName:"Services",trigger:{type:"waitForOutput",dependsOnStepId:h,dependsOnTerminalLabel:"App",waitForText:"Ready",timeoutMs:12e4}},{id:g,templateId:d.id,order:2,targetArea:"current",trigger:{type:"delay",delayMs:2e3,dependsOnStepId:f}}];o.run(W(),"Next Fullstack Pro","Next.js + Docker services + Shadcn UI","#000000","\u{1F680}","1.00",JSON.stringify(w),i,i)}let u=n("Python");if(l&&u){let h=W(),f=W(),g=[{id:h,templateId:l.id,order:0,targetArea:"new",newAreaName:"Database",trigger:{type:"parallel"}},{id:f,templateId:u.id,order:1,targetArea:"new",newAreaName:"API",trigger:{type:"waitForExit",dependsOnStepId:h,dependsOnTerminalLabel:"Docker Up",timeoutMs:6e4}}];o.run(W(),"Python API + DB","Docker DB + Python backend","#CA8A04","\u{1F40D}","1.00",JSON.stringify(g),i,i)}let p=n("Monorepo"),m=n("Multi-Agent");if(p&&m){let h=W(),f=W(),g=[{id:h,templateId:p.id,order:0,targetArea:"new",newAreaName:"Main",trigger:{type:"parallel"}},{id:f,templateId:m.id,order:1,targetArea:"new",newAreaName:"Agents",trigger:{type:"parallel"}}];o.run(W(),"Multi-Agent Monorepo","Monorepo + 4 agentes em paralelo","#7C3AED","\u{1F916}","1.00",JSON.stringify(g),i,i)}}hydrate(e){return{id:e.id,name:e.name,description:e.description,color:e.color,logo:e.logo,version:e.version||"1.00",steps:JSON.parse(e.steps),isBuiltIn:e.isBuiltIn===1,createdAt:e.createdAt,updatedAt:e.updatedAt}}};import{WebSocket as Xa}from"ws";function he(a,e){a.readyState===Xa.OPEN&&a.send(JSON.stringify(e))}function gs(a,e,t){return new Promise(r=>{let s=Date.now(),n=!1,i=setInterval(()=>{let o=a.has(e);if(o&&(n=!0),n&&!o){clearInterval(i),r();return}Date.now()-s>t&&(clearInterval(i),r())},200)})}function ve(a,e,t,r){return new Promise(s=>{let n=Date.now(),i=setInterval(()=>{if(a.outputContains(e,t)){clearInterval(i),s();return}Date.now()-n>r&&(clearInterval(i),s())},200)})}async function ne(a,e,t,r){let{terminalManager:s,areaManager:n}=e,i=null;for(let o of a){if(i){let c=!r?.ignoreRunOnce&&o.startRunOnce&&o.hasLaunched;!c&&o.startDelay&&o.startDelay>0&&await new Promise(l=>setTimeout(l,o.startDelay)),!c&&o.startWaitFor&&await ve(s,i,o.startWaitFor,6e4)}await s.open({id:o.id,cwd:o.cwd,command:o.command||void 0,commandSequence:o.commandSequence,env:o.env,cols:120,rows:30,closeAfterCommand:o.closeAfterCommand||void 0,closeDelay:o.closeDelay,closeWaitFor:o.closeWaitFor||void 0},r?.completedStepsProvider?{completedSteps:r.completedStepsProvider(o.id),onStepCompleted:(c,l)=>{r.onStepCompleted?.(c,l)}}:void 0),i=o.id}for(let o of a)n.markTerminalLaunched(o.id)}var ja=300*1e3,gt=class{terminalManager;areaManager;workspaceTemplateManager;workspaceManager;constructor(e){this.terminalManager=e.terminalManager,this.areaManager=e.areaManager,this.workspaceTemplateManager=e.workspaceTemplateManager,this.workspaceManager=e.workspaceManager}async applyStack(e,t){let{stack:r,workspaceId:s,defaultAreaId:n,broadcast:i}=e,o=this.workspaceManager.get(s);if(!o)throw new Error(`Workspace not found: ${s}`);let c=o.rootDirectory,l=[...r.steps].sort((f,g)=>f.order-g.order),d=new Map,u=new Map,p=new Map;for(let f of l){let g,w=new Promise(E=>{g=E});d.set(f.id,w),u.set(f.id,g)}let m=new Promise((f,g)=>setTimeout(()=>g(new Error("Stack orchestration timed out")),ja)),h=async()=>{let f=l.map(g=>this.runStep({step:g,stack:r,workspaceId:s,defaultAreaId:n,workspaceRootDir:c,stepStarted:d,stepStartedResolve:u,stepTerminalIds:p,broadcast:i,services:t}));await Promise.all(f)};try{await Promise.race([h(),m])}catch(f){console.error("[StackOrchestrator] Error during stack orchestration:",f)}}async runStep(e){let{step:t,stack:r,workspaceId:s,defaultAreaId:n,workspaceRootDir:i,stepStarted:o,stepStartedResolve:c,stepTerminalIds:l,broadcast:d,services:u}=e,{trigger:p}=t;await this.waitForStartCondition({trigger:p,stepStarted:o,stepTerminalIds:l,services:u});let m=this.workspaceTemplateManager.get(t.templateId);if(!m){console.warn(`[StackOrchestrator] Template not found for step ${t.id}: ${t.templateId}`),c.get(t.id)?.();return}let h;if(t.targetArea==="new"){let E=this.areaManager.create({workspaceId:s,name:t.newAreaName||m.name,color:t.newAreaColor||m.color,directory:"",useWorktree:!1,defaultCommand:m.defaultCommand,terminalCount:m.terminals.length,terminals:m.terminals.map(T=>({label:T.label,directory:T.directory,command:T.command,commandSequence:T.commandSequence,runOnce:!1,commandRunOnce:!1,startDelay:T.startDelay??0,startWaitFor:T.startWaitFor??"",startRunOnce:!1,closeAfterCommand:!1,closeDelay:1e3,closeWaitFor:""})),layout:"auto",templateId:m.id});h=E.id,d("area.updated",{workspaceId:s,area:E})}else{let E=this.areaManager.get(n);if(!E){console.warn(`[StackOrchestrator] Default area not found: ${n}`),c.get(t.id)?.();return}let T=E.terminals.map(I=>({id:I.id,label:I.label,directory:I.directory,command:I.command,commandSequence:I.commandSequence,runOnce:I.runOnce,commandRunOnce:I.commandRunOnce,startDelay:I.startDelay,startWaitFor:I.startWaitFor,startRunOnce:I.startRunOnce,closeAfterCommand:I.closeAfterCommand,closeDelay:I.closeDelay,closeWaitFor:I.closeWaitFor})),_=m.terminals.map(I=>({label:I.label,directory:I.directory,command:I.command,commandSequence:I.commandSequence,runOnce:!1,commandRunOnce:!1,startDelay:0,startWaitFor:"",startRunOnce:!1,closeAfterCommand:!1,closeDelay:1e3,closeWaitFor:""})),oe=[...T,..._];this.areaManager.update({id:n,terminalCount:oe.length,terminals:oe}),h=n;let P=this.areaManager.get(n);d("area.updated",{workspaceId:s,area:P})}c.get(t.id)?.(),d("stack.step.started",{stackId:r.id,stepId:t.id,areaId:h});let f=this.areaManager.get(h);if(!f)return;let g=this.areaManager.resolveForLaunch(f,i),w=t.targetArea==="current"?g.slice(g.length-m.terminals.length):g;l.set(t.id,w.map(E=>E.id));try{await ne(w,u,h)}catch(E){console.error(`[StackOrchestrator] Error launching terminals for step ${t.id}:`,E)}d("stack.step.completed",{stackId:r.id,stepId:t.id})}async waitForStartCondition(e){let{trigger:t,stepStarted:r,stepTerminalIds:s,services:n}=e;switch(t.type){case"parallel":{if(t.dependsOnStepId){let i=r.get(t.dependsOnStepId);i&&await i}break}case"delay":{if(t.dependsOnStepId){let i=r.get(t.dependsOnStepId);i&&await i}t.delayMs&&t.delayMs>0&&await new Promise(i=>setTimeout(i,t.delayMs));break}case"waitForOutput":{if(t.dependsOnStepId){let o=r.get(t.dependsOnStepId);o&&await o}let i=this.findTerminalByLabel(t.dependsOnStepId,t.dependsOnTerminalLabel,s,n);i&&t.waitForText&&await ve(n.terminalManager,i,t.waitForText,t.timeoutMs??12e4);break}case"waitForExit":{if(t.dependsOnStepId){let o=r.get(t.dependsOnStepId);o&&await o}let i=this.findTerminalByLabel(t.dependsOnStepId,t.dependsOnTerminalLabel,s,n);i&&await this.waitForTerminalExit(i,t.timeoutMs??6e4,n);break}}}findTerminalByLabel(e,t,r,s){if(!e||!t)return null;let n=r.get(e);if(!n)return null;for(let i of n)if(s.terminalManager.getProcessInfo(i)&&s.areaManager.db.prepare("SELECT label FROM terminal_configs WHERE id = ?").get(i)?.label===t)return i;for(let i of n)if(this.queryTerminalLabel(i)===t)return i;return n[0]??null}queryTerminalLabel(e){return this.areaManager.db.prepare("SELECT label FROM terminal_configs WHERE id = ?").get(e)?.label??null}waitForTerminalExit(e,t,r){return new Promise(s=>{let n=Date.now(),i=setInterval(()=>{let o=r.terminalManager.getProcessInfo(e);if(!o||o.isIdle){clearInterval(i),s();return}Date.now()-n>t&&(clearInterval(i),s())},500)})}};import{execSync as Jt}from"node:child_process";var Ga=300*1e3,Ka=2e3,Qt=5e3,hs=[{cli:"claude",command:"claude",authCommand:"claude auth status",versionCommand:"claude --version",parseAuth:a=>{let e=a.toLowerCase();return e.includes("not logged in")||e.includes("login required")?!1:(e.includes("loggedin")||e.includes("logged in")||e.includes("authenticated")||e.includes("isloggedin"),!0)}},{cli:"codex",command:"codex",authCommand:"codex login status",versionCommand:"codex --version",parseAuth:a=>{let e=a.toLowerCase();return e.includes("not logged in")||e.includes("run `codex login`")?!1:(e.includes("logged in"),!0)}},{cli:"gemini",command:"gemini",authCommand:"gemini auth status",versionCommand:"gemini --version",parseAuth:a=>{let e=a.toLowerCase();return e.includes("not logged in")||e.includes("login required")||e.includes("not authenticated")?!1:(e.includes("logged in")||e.includes("authenticated"),!0)}}],ht=class{interval=null;startupTimer=null;lastResult=null;previousStates=new Map;broadcast;constructor(e){this.broadcast=e,this.startupTimer=setTimeout(()=>{this.checkAll(),this.startupTimer=null},Ka),this.interval=setInterval(()=>{this.checkAll()},Ga)}async checkAll(){let e=[];for(let r of hs){let s=await this.checkOne(r.cli);e.push(s)}let t={providers:e,checkedAt:new Date().toISOString()};for(let r of e){let s=this.previousStates.get(r.cli);s&&s==="connected"&&r.state==="disconnected"&&this.broadcast("notification.new",{type:"warning",title:`${r.cli} disconnected`,message:`${r.cli} CLI lost authentication. Re-authenticate to continue using it.`,source:"health-check"}),this.previousStates.set(r.cli,r.state)}return this.lastResult=t,this.broadcast("health.status",t),t}async checkOne(e){let t=hs.find(c=>c.cli===e);if(!t)return{cli:e,state:"not_installed",installed:!1,authenticated:!1,lastCheckedAt:new Date().toISOString()};let r;try{r=Jt(`which ${t.command}`,{encoding:"utf8",timeout:Qt,stdio:["pipe","pipe","pipe"]}).trim()}catch{return{cli:e,state:"not_installed",installed:!1,authenticated:!1,lastCheckedAt:new Date().toISOString()}}let s;try{s=Jt(t.versionCommand,{encoding:"utf8",timeout:Qt,stdio:["pipe","pipe","pipe"]}).trim()}catch{}let n=!1,i="disconnected",o;try{let c=Jt(t.authCommand,{encoding:"utf8",timeout:Qt,stdio:["pipe","pipe","pipe"]});n=t.parseAuth(c),i=n?"connected":"disconnected"}catch(c){i="disconnected",o=c instanceof Error?c.message:"Auth check failed"}return{cli:e,state:i,installed:!0,version:s,path:r,authenticated:n,lastCheckedAt:new Date().toISOString(),error:o}}getLastResult(){return this.lastResult}dispose(){this.interval&&(clearInterval(this.interval),this.interval=null),this.startupTimer&&(clearTimeout(this.startupTimer),this.startupTimer=null)}};import{randomUUID as Ya}from"node:crypto";var fs=100,ft=class{notifications=[];broadcast;constructor(e){this.broadcast=e}add(e,t,r,s){let n={id:Ya(),type:e,title:t,message:r,source:s,read:!1,createdAt:new Date().toISOString()};return this.notifications.unshift(n),this.notifications.length>fs&&(this.notifications=this.notifications.slice(0,fs)),this.broadcast("notification.new",n),n}list(){return this.notifications}markRead(e){let t=this.notifications.find(r=>r.id===e);return t?(t.read=!0,!0):!1}clear(e){if(e){let t=this.notifications.findIndex(r=>r.id===e);return t===-1?!1:(this.notifications.splice(t,1),!0)}return this.clearAll(),!0}clearAll(){this.notifications=[]}};import{execFile as Va}from"node:child_process";import{stat as za,open as Ja}from"node:fs/promises";import{join as ws}from"node:path";import{promisify as Qa}from"node:util";var Za=Qa(Va),wt=class{async exec(e,t){return Za("git",e,{cwd:t,maxBuffer:10*1024*1024})}async isGitRepo(e){try{return await this.exec(["rev-parse","--is-inside-work-tree"],e),!0}catch{return!1}}async init(e){let{stdout:t}=await this.exec(["init"],e);return{ok:!0,message:t.trim()}}async status(e){let{stdout:t}=await this.exec(["status","--porcelain=v2","--branch"],e),r=null,s=0,n=0,i=!1,o=[],c=[],l=[];for(let d of t.split(`
267
267
  `))if(d.startsWith("# branch.head "))r=d.slice(14);else if(d.startsWith("# branch.ab ")){i=!0;let u=d.match(/\+(\d+) -(\d+)/);u&&(s=parseInt(u[1],10),n=parseInt(u[2],10))}else if(d.startsWith("1 ")||d.startsWith("2 ")){let u=d.split(" "),p=u[1],m=d.startsWith("2 ")&&d.split(" ")[1]||u[u.length-1],h=p[0],f=p[1];h!=="."&&o.push({path:m,status:this.mapStatus(h,d.startsWith("2 ")),insertions:0,deletions:0}),f!=="."&&c.push({path:m,status:this.mapStatus(f,!1),insertions:0,deletions:0})}else d.startsWith("? ")&&l.push(d.slice(2));try{let{stdout:d}=await this.exec(["diff","--numstat","--cached"],e);this.applyNumstat(d,o)}catch{}try{let{stdout:d}=await this.exec(["diff","--numstat"],e);this.applyNumstat(d,c)}catch{}return{branch:r,hasChanges:o.length>0||c.length>0||l.length>0,staged:o,unstaged:c,untracked:l,aheadCount:s,behindCount:n,hasUpstream:i}}async diff(e,t){if(t!==void 0){let m=["diff"];t&&m.push("--cached");let{stdout:h}=await this.exec(m,e);return{...this.parseDiff(h),rawPatch:h}}let r="";try{let{stdout:m}=await this.exec(["diff","HEAD"],e);r=m}catch{let[m,h]=await Promise.all([this.exec(["diff"],e).then(f=>f.stdout).catch(()=>""),this.exec(["diff","--cached"],e).then(f=>f.stdout).catch(()=>"")]);r=[m,h].filter(Boolean).join(`
268
268
  `)}let s=await this.exec(["ls-files","--others","--exclude-standard"],e).then(m=>m.stdout.trim().split(`
269
269
  `).filter(Boolean)).catch(()=>[]),n=200,i=256*1024,o=2*1024*1024,c=s.slice(0,n),l=s.length-c.length,d="";l>0&&(d+=`# ${l} untracked files omitted (limit ${n})
270
270
  `);for(let m of c){if(d.length>=o){d+=`# untracked diff truncated at ${o} bytes
271
- `;break}let h=!1,f=!1;try{let g=await Va(ws(e,m));if(g.size>i&&(f=!0),!f&&g.size>0){let w=await za(ws(e,m),"r");try{let E=Buffer.alloc(Math.min(8192,g.size));await w.read(E,0,E.length,0),E.includes(0)&&(h=!0)}finally{await w.close()}}}catch{f=!0}if(f||h){d+=`diff --git a/${m} b/${m}
271
+ `;break}let h=!1,f=!1;try{let g=await za(ws(e,m));if(g.size>i&&(f=!0),!f&&g.size>0){let w=await Ja(ws(e,m),"r");try{let E=Buffer.alloc(Math.min(8192,g.size));await w.read(E,0,E.length,0),E.includes(0)&&(h=!0)}finally{await w.close()}}}catch{f=!0}if(f||h){d+=`diff --git a/${m} b/${m}
272
272
  new file mode 100644
273
273
  --- /dev/null
274
274
  +++ b/${m}
@@ -278,13 +278,13 @@ ${h?"Binary file":"File too large to preview"} (untracked)
278
278
  `)){if(!s.trim())continue;let n=s.trim().split(" "),i=n[0],o=n[1]==="*",c=n[2]||void 0;r.push({name:i,current:o,remote:c})}return r}async log(e,t){let r=t??20,{stdout:s}=await this.exec(["log","--format=%H||%s||%an||%aI","-n",`${r}`],e),n=[];for(let i of s.trim().split(`
279
279
  `)){if(!i.trim())continue;let[o,c,l,d]=i.split("||");n.push({hash:o,message:c,author:l,date:d})}return n}async createBranch(e,t){return await this.exec(["checkout","-b",t],e),{ok:!0,branch:t}}async checkoutBranch(e,t){return await this.exec(["checkout",t],e),{ok:!0,branch:t}}mapStatus(e,t){if(t)return"renamed";switch(e){case"A":return"added";case"D":return"deleted";case"M":case"T":return"modified";case"R":return"renamed";default:return"modified"}}applyNumstat(e,t){for(let r of e.trim().split(`
280
280
  `)){if(!r.trim())continue;let[s,n,i]=r.split(" "),o=t.find(c=>c.path===i);o&&(o.insertions=s==="-"?0:parseInt(s,10),o.deletions=n==="-"?0:parseInt(n,10))}}parseDiff(e){let t=[],r=0,s=0,n=e.split(/^diff --git /m).filter(Boolean);for(let i of n){let o=i.split(`
281
- `),c,l="",d="modified",u=0;for(let w=0;w<o.length;w++){let E=o[w];if(E.startsWith("--- ")){let T=E.slice(4);T==="/dev/null"?d="added":c=T.replace(/^a\//,"")}else if(E.startsWith("+++ ")){let T=E.slice(4);T==="/dev/null"?(d="deleted",l=c||""):l=T.replace(/^b\//,"")}else if(E.startsWith("@@ ")){u=w;break}else E.startsWith("rename from ")?(c=E.slice(12),d="renamed"):E.startsWith("rename to ")&&(l=E.slice(10),d="renamed")}if(!l&&!c)continue;l||(l=c||"");let p=[],m=null,h=0,f=0;for(let w=u;w<o.length;w++){let E=o[w];if(E.startsWith("@@ ")){let T=E.match(/@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);T&&(h=parseInt(T[1],10),f=parseInt(T[2],10),m={header:E,lines:[]},p.push(m))}else if(m){if(E.startsWith("+")){let T={type:"add",content:E.slice(1),newLineNumber:f};m.lines.push(T),f++,r++}else if(E.startsWith("-")){let T={type:"delete",content:E.slice(1),oldLineNumber:h};m.lines.push(T),h++,s++}else if(E.startsWith(" ")){let T={type:"context",content:E.slice(1),oldLineNumber:h,newLineNumber:f};m.lines.push(T),h++,f++}}}let g={path:l,status:d,hunks:p};c&&c!==l&&(g.oldPath=c),t.push(g)}return{files:t,stats:{filesChanged:t.length,insertions:r,deletions:s}}}};import{execFile as Za}from"node:child_process";import{promisify as ei}from"node:util";var ti=ei(Za),Et=class{constructor(e){this.db=e}async exec(e,t){let r={maxBuffer:10485760};return t&&(r.cwd=t),ti("gh",e,r)}async checkAuth(){try{let{stdout:e,stderr:t}=await this.exec(["auth","status"]),r=e+t,s=r.match(/Logged in to github\.com.*?(?:as|account) (\S+)/i);if(s){let n=r.match(/Token scopes:[\s]*(.+)/i),i=n?n[1].split(",").map(o=>o.trim()).filter(Boolean):void 0;return{authenticated:!0,username:s[1],scopes:i}}return{authenticated:!1}}catch{return{authenticated:!1}}}async listRepos(e){let t=e?.limit??30,r=["repo","list"];e?.owner&&r.push(e.owner),r.push("--json","nameWithOwner,url,sshUrl,isPrivate","--limit",`${t}`);let{stdout:s}=await this.exec(r);return JSON.parse(s).map(i=>({nameWithOwner:i.nameWithOwner,url:i.url,sshUrl:i.sshUrl,isPrivate:i.isPrivate,defaultBranch:"main"}))}async createRepo(e,t){await this.exec(["repo","create",e,t?"--private":"--public","--add-readme"]);let{stdout:r}=await this.exec(["repo","view",e,"--json","nameWithOwner,url,sshUrl,isPrivate"]),s=JSON.parse(r);return{nameWithOwner:s.nameWithOwner,url:s.url,sshUrl:s.sshUrl,isPrivate:s.isPrivate,defaultBranch:"main"}}async createPR(e){let t=["pr","create","--title",e.title,"--body",e.body];e.base&&t.push("--base",e.base),e.head&&t.push("--head",e.head);let{stdout:r}=await this.exec(t,e.cwd),s=r.trim().split(`
281
+ `),c,l="",d="modified",u=0;for(let w=0;w<o.length;w++){let E=o[w];if(E.startsWith("--- ")){let T=E.slice(4);T==="/dev/null"?d="added":c=T.replace(/^a\//,"")}else if(E.startsWith("+++ ")){let T=E.slice(4);T==="/dev/null"?(d="deleted",l=c||""):l=T.replace(/^b\//,"")}else if(E.startsWith("@@ ")){u=w;break}else E.startsWith("rename from ")?(c=E.slice(12),d="renamed"):E.startsWith("rename to ")&&(l=E.slice(10),d="renamed")}if(!l&&!c)continue;l||(l=c||"");let p=[],m=null,h=0,f=0;for(let w=u;w<o.length;w++){let E=o[w];if(E.startsWith("@@ ")){let T=E.match(/@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);T&&(h=parseInt(T[1],10),f=parseInt(T[2],10),m={header:E,lines:[]},p.push(m))}else if(m){if(E.startsWith("+")){let T={type:"add",content:E.slice(1),newLineNumber:f};m.lines.push(T),f++,r++}else if(E.startsWith("-")){let T={type:"delete",content:E.slice(1),oldLineNumber:h};m.lines.push(T),h++,s++}else if(E.startsWith(" ")){let T={type:"context",content:E.slice(1),oldLineNumber:h,newLineNumber:f};m.lines.push(T),h++,f++}}}let g={path:l,status:d,hunks:p};c&&c!==l&&(g.oldPath=c),t.push(g)}return{files:t,stats:{filesChanged:t.length,insertions:r,deletions:s}}}};import{execFile as ei}from"node:child_process";import{promisify as ti}from"node:util";var ri=ti(ei),Et=class{constructor(e){this.db=e}async exec(e,t){let r={maxBuffer:10485760};return t&&(r.cwd=t),ri("gh",e,r)}async checkAuth(){try{let{stdout:e,stderr:t}=await this.exec(["auth","status"]),r=e+t,s=r.match(/Logged in to github\.com.*?(?:as|account) (\S+)/i);if(s){let n=r.match(/Token scopes:[\s]*(.+)/i),i=n?n[1].split(",").map(o=>o.trim()).filter(Boolean):void 0;return{authenticated:!0,username:s[1],scopes:i}}return{authenticated:!1}}catch{return{authenticated:!1}}}async listRepos(e){let t=e?.limit??30,r=["repo","list"];e?.owner&&r.push(e.owner),r.push("--json","nameWithOwner,url,sshUrl,isPrivate","--limit",`${t}`);let{stdout:s}=await this.exec(r);return JSON.parse(s).map(i=>({nameWithOwner:i.nameWithOwner,url:i.url,sshUrl:i.sshUrl,isPrivate:i.isPrivate,defaultBranch:"main"}))}async createRepo(e,t){await this.exec(["repo","create",e,t?"--private":"--public","--add-readme"]);let{stdout:r}=await this.exec(["repo","view",e,"--json","nameWithOwner,url,sshUrl,isPrivate"]),s=JSON.parse(r);return{nameWithOwner:s.nameWithOwner,url:s.url,sshUrl:s.sshUrl,isPrivate:s.isPrivate,defaultBranch:"main"}}async createPR(e){let t=["pr","create","--title",e.title,"--body",e.body];e.base&&t.push("--base",e.base),e.head&&t.push("--head",e.head);let{stdout:r}=await this.exec(t,e.cwd),s=r.trim().split(`
282
282
  `).pop()||"",n=s.match(/\/pull\/(\d+)/);return{number:n?parseInt(n[1],10):0,url:s,title:e.title}}async listPRs(e){let{stdout:t}=await this.exec(["pr","list","--json","number,title,url,state"],e);return JSON.parse(t)}async getDefaultBranch(e){let{stdout:t}=await this.exec(["repo","view","--json","defaultBranchRef","--jq",".defaultBranchRef.name"],e);return t.trim()||"main"}getConfig(e){let t=this.db.prepare("SELECT * FROM workspace_github WHERE workspaceId = ?").get(e);return t?{workspaceId:t.workspaceId,repoNameWithOwner:t.repoNameWithOwner,repoUrl:t.repoUrl,defaultBranch:t.defaultBranch,connectedAt:t.connectedAt}:null}saveConfig(e){this.db.prepare(`INSERT OR REPLACE INTO workspace_github (workspaceId, repoNameWithOwner, repoUrl, defaultBranch, connectedAt)
283
- VALUES (?, ?, ?, ?, ?)`).run(e.workspaceId,e.repoNameWithOwner,e.repoUrl,e.defaultBranch,e.connectedAt)}removeConfig(e){this.db.prepare("DELETE FROM workspace_github WHERE workspaceId = ?").run(e)}};function Es(){return{"terminal.open":async(a,e)=>{let t=a;return await e.services.terminalManager.open(t),{ok:!0}},"terminal.write":(a,e)=>{let t=a;return e.services.terminalManager.write(t.id,t.data),{ok:!0}},"terminal.resize":(a,e)=>{let t=a;return e.services.terminalManager.resize(t.id,t.cols,t.rows),{ok:!0}},"terminal.close":(a,e)=>{let t=a;return e.services.terminalManager.close(t.id),{ok:!0}},"terminal.list":(a,e)=>({ok:!0,terminals:e.services.terminalManager.listTerminals()}),"terminal.processes":(a,e)=>({ok:!0,processes:e.services.terminalManager.getAllProcessInfo()}),"terminal.replay":(a,e)=>{let t=a;return{ok:!0,data:e.services.terminalManager.getOutputBuffer(t.id)||""}},"terminal.restart":async(a,e)=>{let t=a;return e.services.terminalManager.close(t.id),await e.services.terminalManager.open(t),{ok:!0}},"terminal.upload":async(a,e)=>{let t=a,r=50*1024*1024;if(Math.ceil(t.fileData.length*3/4)>r)return e.respondError("File too large (max 50MB)"),null;let n=e.services.terminalManager.getCwd(t.terminalId);if(!n)return e.respondError(`Terminal ${t.terminalId} not found or CWD unavailable`),null;let i=await import("node:fs"),o=await import("node:path"),c=o.basename(t.fileName);if(!c||c==="."||c==="..")return e.respondError("Invalid file name"),null;let l=o.resolve(n,c);if(!l.startsWith(n+o.sep)&&l!==n)return e.respondError("Invalid file path"),null;if(i.existsSync(l)){let p=o.extname(c),m=c.slice(0,c.length-p.length),h=1;for(;i.existsSync(l);)l=o.resolve(n,`${m} (${h})${p}`),h++}let d=Buffer.from(t.fileData,"base64");i.writeFileSync(l,d);let u="'"+l.replace(/'/g,"'\\''")+"'";return e.services.terminalManager.write(t.terminalId,u+" "),{ok:!0,path:l}},"terminal.set-color":(a,e)=>{let t=a;if(t.areaId)e.services.areaManager.setTerminalColor(t.terminalId,t.areaId,t.color);else if(e.services.workspaceManager.get(t.workspaceId)){let s=e.services.areaManager.getDefaultArea(t.workspaceId);s&&e.services.areaManager.setTerminalColor(t.terminalId,s.id,t.color)}return{ok:!0}}}}function Ts(){return{"workspace.list":(a,e)=>e.services.workspaceManager.list(),"workspace.get":(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.id);return r||(e.respondError(`Workspace ${t.id} not found`),null)},"workspace.create":(a,e)=>{let t=a;return e.services.workspaceManager.create(t)},"workspace.update":(a,e)=>{let t=a;return e.services.workspaceManager.update(t)},"workspace.delete":(a,e)=>{let t=a;return{deleted:e.services.workspaceManager.delete(t.id)}},"workspace.launch":async(a,e)=>{let t=a,{workspaceManager:r,areaManager:s,portMonitor:n}=e.services,i=r.get(t.id);if(!i)return e.respondError(`Workspace ${t.id} not found`),null;let o=s.getDefaultArea(i.id);if(!o)return e.respondError(`No default area found for workspace ${t.id}`),null;let c=s.resolveForLaunch(o,i.rootDirectory),l=new Map(o.terminals.map(u=>[u.id,u.color||"default"])),d={ok:!0,terminals:c.map(u=>({id:u.id,label:u.label,cwd:u.cwd,position:u.position,color:l.get(u.id)||"default"}))};return e.respond(d),(async()=>{try{await ne(c,e.services,o.id,{completedStepsProvider:u=>s.getCompletedSteps(u),onStepCompleted:(u,p)=>{s.markStepCompleted(u,p)}}),s.setRunning(o.id,!0),e.services.broadcast("area.status",{id:o.id,workspaceId:t.id,state:"running"}),r.setRunning(t.id,!0),e.services.broadcast("workspace.status",{id:t.id,state:"running"}),n.startMonitoring(t.id,c.map(u=>u.id)).catch(console.error)}catch(u){console.error("[server] workspace.launch async error:",u)}})(),null},"workspace.getSetupConfig":(a,e)=>{let t=a,{workspaceManager:r,areaManager:s}=e.services,n=r.get(t.id);if(!n)return e.respondError(`Workspace ${t.id} not found`),null;let i=s.getDefaultArea(t.id);return{workspace:{id:n.id,name:n.name,color:n.color,rootDirectory:n.rootDirectory,defaultCommand:n.defaultCommand,terminalCount:n.terminalCount,initGit:n.initGit,createdAt:n.createdAt},area:i?{id:i.id,name:i.name,terminalCount:i.terminalCount,layout:i.layout,defaultCommand:i.defaultCommand,ignoreOnLaunchAll:i.ignoreOnLaunchAll??!1}:null,terminals:i?i.terminals.map(o=>({id:o.id,label:o.label,directory:o.directory,command:o.command,commandSequence:o.commandSequence,startDelay:o.startDelay,startWaitFor:o.startWaitFor,startRunOnce:o.startRunOnce,closeAfterCommand:o.closeAfterCommand,closeDelay:o.closeDelay,closeWaitFor:o.closeWaitFor,runOnce:o.runOnce,commandRunOnce:o.commandRunOnce,color:o.color})):[]}},"workspace.relaunch":async(a,e)=>{let t=a,{workspaceManager:r,areaManager:s,terminalManager:n,portMonitor:i}=e.services,o=r.get(t.id);if(!o)return e.respondError(`Workspace ${t.id} not found`),null;let c=s.getDefaultArea(o.id);if(!c)return e.respondError(`No default area found for workspace ${t.id}`),null;let l=s.list(t.id);for(let h of l){for(let f of h.terminals)n.close(f.id);s.setRunning(h.id,!1)}r.setRunning(t.id,!1),i.stopMonitoring(t.id);let u=l.filter(h=>!h.ignoreOnLaunchAll).map(h=>{s.resetAllTerminals(h.id);let f=s.resolveForLaunch(h,o.rootDirectory);return{area:h,resolved:f}});if(u.length===0){s.resetAllTerminals(c.id);let h=s.resolveForLaunch(c,o.rootDirectory);u.push({area:c,resolved:h})}let p=u.find(h=>h.area.id===c.id)??u[0],m=new Map(p.area.terminals.map(h=>[h.id,h.color||"default"]));return e.respond({ok:!0,terminals:p.resolved.map(h=>({id:h.id,label:h.label,cwd:h.cwd,position:h.position,color:m.get(h.id)||"default"}))}),(async()=>{let h=[];await Promise.all(u.map(async({area:f,resolved:g})=>{try{let w=f.trigger;if(w){let E=w.timeoutMs??12e4;w.type==="delay"?await new Promise(T=>setTimeout(T,w.delayMs??0)):w.type==="waitForOutput"&&w.dependsOnTerminalId&&w.waitForText?await ve(n,w.dependsOnTerminalId,w.waitForText,E):w.type==="waitForExit"&&w.dependsOnTerminalId&&await gs(n,w.dependsOnTerminalId,E)}await ne(g,e.services,f.id,{ignoreRunOnce:!0,completedStepsProvider:E=>s.getCompletedSteps(E),onStepCompleted:(E,T)=>{s.markStepCompleted(E,T)}}),s.setRunning(f.id,!0),e.services.broadcast("area.status",{id:f.id,workspaceId:t.id,state:"running"});for(let E of g)h.push(E.id)}catch(w){console.error(`[server] workspace.relaunch error for area ${f.id}:`,w)}})),r.setRunning(t.id,!0),e.services.broadcast("workspace.status",{id:t.id,state:"running"}),h.length>0&&i.startMonitoring(t.id,h).catch(console.error)})(),null},"workspace.stop":(a,e)=>{let t=a,{workspaceManager:r,areaManager:s,terminalManager:n,portMonitor:i}=e.services,o=r.get(t.id);if(!o)return e.respondError(`Workspace ${t.id} not found`),null;let c=s.list(t.id);for(let l of c){for(let d of l.terminals)n.close(d.id);s.setRunning(l.id,!1),e.services.broadcast("area.status",{id:l.id,workspaceId:t.id,state:"stopped"})}for(let l of o.terminals)n.close(l.id);return r.setRunning(t.id,!1),e.services.broadcast("workspace.status",{id:t.id,state:"stopped"}),i.stopMonitoring(t.id),{ok:!0}}}}function Ss(){return{"area.list":(a,e)=>{let t=a;return e.services.areaManager.list(t.workspaceId)},"area.create":(a,e)=>{let t=a;return e.services.areaManager.create(t)},"area.update":(a,e)=>{let t=a;return e.services.areaManager.update(t)},"area.delete":(a,e)=>{let t=a;return{deleted:e.services.areaManager.delete(t.id)}},"area.duplicate":(a,e)=>{let t=a;return e.services.areaManager.duplicate(t.id,t.name)},"area.launch":async(a,e)=>{let t=a,{areaManager:r,workspaceManager:s}=e.services,n=r.get(t.areaId);if(!n)return e.respondError(`Area ${t.areaId} not found`),null;let i=s.get(t.workspaceId);if(!i)return e.respondError(`Workspace ${t.workspaceId} not found`),null;let o=r.resolveForLaunch(n,i.rootDirectory),c=new Map(n.terminals.map(d=>[d.id,d.color||"default"])),l={ok:!0,terminals:o.map(d=>({id:d.id,label:d.label,cwd:d.cwd,position:d.position,color:c.get(d.id)||"default"}))};return e.respond(l),(async()=>{try{await ne(o,e.services,t.areaId,{completedStepsProvider:d=>r.getCompletedSteps(d),onStepCompleted:(d,u)=>{r.markStepCompleted(d,u)}}),r.setRunning(t.areaId,!0),s.setRunning(t.workspaceId,!0),e.services.broadcast("area.status",{id:t.areaId,workspaceId:t.workspaceId,state:"running"}),e.services.broadcast("workspace.status",{id:t.workspaceId,state:"running"})}catch(d){console.error("[server] area.launch async error:",d)}})(),null},"area.stop":(a,e)=>{let t=a,{areaManager:r,workspaceManager:s,terminalManager:n}=e.services,i=r.get(t.areaId);if(!i)return e.respondError(`Area ${t.areaId} not found`),null;for(let l of i.terminals)n.close(l.id);return r.setRunning(t.areaId,!1),r.clearRuntimeState(t.areaId),r.list(t.workspaceId).some(l=>l.id!==t.areaId&&r.isRunning(l.id))||(s.setRunning(t.workspaceId,!1),e.services.broadcast("workspace.status",{id:t.workspaceId,state:"stopped"})),e.services.broadcast("area.status",{id:t.areaId,workspaceId:t.workspaceId,state:"stopped"}),{ok:!0}},"area.save-runtime-state":(a,e)=>{let t=a;return e.services.areaManager.saveRuntimeState(t.areaId,t.data),{ok:!0}},"area.get-runtime-state":(a,e)=>{let t=a;return{data:e.services.areaManager.getRuntimeState(t.areaId)}},"area.clear-runtime-state":(a,e)=>{let t=a;return e.services.areaManager.clearRuntimeState(t.areaId),{ok:!0}}}}function ys(){return{"swarm.create":(a,e)=>{let t=a;return e.services.swarmManager.create(t)},"swarm.launch":async(a,e)=>{let t=a;return await e.services.swarmManager.launch(t.id),{ok:!0}},"swarm.stop":(a,e)=>{let t=a;return e.services.swarmManager.stop(t.id),{ok:!0}},"swarm.pause":(a,e)=>{let t=a;return e.services.swarmManager.pause(t.id),{ok:!0}},"swarm.resume":(a,e)=>{let t=a;return e.services.swarmManager.resume(t.id),{ok:!0}},"swarm.status":(a,e)=>{let t=a,r=e.services.swarmManager.get(t.id);return r?{...r,stats:e.services.swarmManager.getStats(t.id)}:(e.respondError(`Swarm ${t.id} not found`),null)},"swarm.list":(a,e)=>{let t=a;return e.services.swarmManager.list(t.workspaceId)},"swarm.delete":(a,e)=>{let t=a;return{deleted:e.services.swarmManager.delete(t.id)}},"swarm.message":(a,e)=>{let t=a;return e.services.swarmManager.message(t.swarmId,t.agentId,t.message),{ok:!0}},"swarm.agent.add":(a,e)=>{let t=a;return e.services.swarmManager.addAgent(t)},"swarm.agent.remove":(a,e)=>{let t=a;return{removed:e.services.swarmManager.removeAgent(t)}},"swarm.agent.update":(a,e)=>{let t=a;return e.services.swarmManager.updateAgent(t)},"orchestrator.topology.set":(a,e)=>{let t=a;return e.services.swarmManager.setTopology(t.swarmId,t.topology),{ok:!0}},"orchestrator.spawn-cli":async(a,e)=>{let t=a;return await e.services.swarmManager.spawnCLI(t.swarmId,t.agentId,t.config)},"orchestrator.escalation.respond":(a,e)=>{let t=a;return e.services.swarmManager.respondToEscalation(t.escalationId,t.response),{ok:!0}}}}import{mkdir as Zt,writeFile as Tt,cp as ri}from"node:fs/promises";import{basename as si,join as Z,resolve as ni}from"node:path";var be=class{async buildContext(e){let{task:t,agent:r,swarm:s,knowledgeEntries:n,dependencyTasks:i,workspaceDir:o}=e,c=Z(o,".swarm","tasks",t.id);await Zt(c,{recursive:!0});let l=this.assemblePrompt(t,r,n,i),d=Z(c,"CLAUDE.md"),u=this.generateClaudeMd(t,r,s);await Tt(d,u,"utf-8");let p=this.generateTaskMd(t,i);if(await Tt(Z(c,"TASK.md"),p,"utf-8"),s?.knowledge&&s.knowledge.length>0){let m=Z(c,"knowledge");await Zt(m,{recursive:!0});for(let h of s.knowledge)try{let f=si(h.name),g=ni(h.path),w=Z(m,f);await ri(g,w)}catch{}}return{contextDir:c,prompt:l,claudeMdPath:d}}assemblePrompt(e,t,r,s){let n=[];if(n.push(`# Task: ${e.title}`,""),n.push(e.description,""),n.push("## Agent",""),n.push(`- **Name:** ${t.name}`),n.push(`- **Role:** ${t.role}`),n.push(""),t.workScope&&t.workScope.length>0){n.push("## Work Scope","");for(let i of t.workScope)n.push(`- ${i}`);n.push("")}if(s&&s.length>0){n.push("## Dependencies","");for(let i of s)n.push(`### ${i.title} (${i.status})`),i.output&&n.push("","Output:","",i.output),n.push("")}if(r&&r.length>0){n.push("## Knowledge Base","");for(let i of r)n.push(`- ${i.name} (${i.type}): \`${i.path}\``);n.push("")}switch(n.push(`## Approval Mode: ${e.approvalMode}`,""),e.approvalMode){case"auto":n.push("You may proceed autonomously without waiting for human approval.");break;case"semi":n.push("Proceed with implementation but pause before destructive or irreversible actions.");break;case"manual":n.push("Wait for explicit human approval before making any changes.");break}return n.push(""),n.join(`
283
+ VALUES (?, ?, ?, ?, ?)`).run(e.workspaceId,e.repoNameWithOwner,e.repoUrl,e.defaultBranch,e.connectedAt)}removeConfig(e){this.db.prepare("DELETE FROM workspace_github WHERE workspaceId = ?").run(e)}};function Es(){return{"terminal.open":async(a,e)=>{let t=a;return await e.services.terminalManager.open(t),{ok:!0}},"terminal.write":(a,e)=>{let t=a;return e.services.terminalManager.write(t.id,t.data),{ok:!0}},"terminal.resize":(a,e)=>{let t=a;return e.services.terminalManager.resize(t.id,t.cols,t.rows),{ok:!0}},"terminal.close":(a,e)=>{let t=a;return e.services.terminalManager.close(t.id),{ok:!0}},"terminal.list":(a,e)=>({ok:!0,terminals:e.services.terminalManager.listTerminals()}),"terminal.processes":(a,e)=>({ok:!0,processes:e.services.terminalManager.getAllProcessInfo()}),"terminal.replay":(a,e)=>{let t=a;return{ok:!0,data:e.services.terminalManager.getOutputBuffer(t.id)||""}},"terminal.restart":async(a,e)=>{let t=a;return e.services.terminalManager.close(t.id),await e.services.terminalManager.open(t),{ok:!0}},"terminal.upload":async(a,e)=>{let t=a,r=50*1024*1024;if(Math.ceil(t.fileData.length*3/4)>r)return e.respondError("File too large (max 50MB)"),null;let n=e.services.terminalManager.getCwd(t.terminalId);if(!n)return e.respondError(`Terminal ${t.terminalId} not found or CWD unavailable`),null;let i=await import("node:fs"),o=await import("node:path"),c=o.basename(t.fileName);if(!c||c==="."||c==="..")return e.respondError("Invalid file name"),null;let l=o.resolve(n,c);if(!l.startsWith(n+o.sep)&&l!==n)return e.respondError("Invalid file path"),null;if(i.existsSync(l)){let p=o.extname(c),m=c.slice(0,c.length-p.length),h=1;for(;i.existsSync(l);)l=o.resolve(n,`${m} (${h})${p}`),h++}let d=Buffer.from(t.fileData,"base64");i.writeFileSync(l,d);let u="'"+l.replace(/'/g,"'\\''")+"'";return e.services.terminalManager.write(t.terminalId,u+" "),{ok:!0,path:l}},"terminal.set-color":(a,e)=>{let t=a;if(t.areaId)e.services.areaManager.setTerminalColor(t.terminalId,t.areaId,t.color);else if(e.services.workspaceManager.get(t.workspaceId)){let s=e.services.areaManager.getDefaultArea(t.workspaceId);s&&e.services.areaManager.setTerminalColor(t.terminalId,s.id,t.color)}return{ok:!0}}}}function Ts(){return{"workspace.list":(a,e)=>e.services.workspaceManager.list(),"workspace.get":(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.id);return r||(e.respondError(`Workspace ${t.id} not found`),null)},"workspace.create":(a,e)=>{let t=a;return e.services.workspaceManager.create(t)},"workspace.update":(a,e)=>{let t=a;return e.services.workspaceManager.update(t)},"workspace.delete":(a,e)=>{let t=a;return{deleted:e.services.workspaceManager.delete(t.id)}},"workspace.launch":async(a,e)=>{let t=a,{workspaceManager:r,areaManager:s,portMonitor:n}=e.services,i=r.get(t.id);if(!i)return e.respondError(`Workspace ${t.id} not found`),null;let o=s.getDefaultArea(i.id);if(!o)return e.respondError(`No default area found for workspace ${t.id}`),null;let c=s.resolveForLaunch(o,i.rootDirectory),l=new Map(o.terminals.map(u=>[u.id,u.color||"default"])),d={ok:!0,terminals:c.map(u=>({id:u.id,label:u.label,cwd:u.cwd,position:u.position,color:l.get(u.id)||"default"}))};return e.respond(d),(async()=>{try{await ne(c,e.services,o.id,{completedStepsProvider:u=>s.getCompletedSteps(u),onStepCompleted:(u,p)=>{s.markStepCompleted(u,p)}}),s.setRunning(o.id,!0),e.services.broadcast("area.status",{id:o.id,workspaceId:t.id,state:"running"}),r.setRunning(t.id,!0),e.services.broadcast("workspace.status",{id:t.id,state:"running"}),n.startMonitoring(t.id,c.map(u=>u.id)).catch(console.error)}catch(u){console.error("[server] workspace.launch async error:",u)}})(),null},"workspace.getSetupConfig":(a,e)=>{let t=a,{workspaceManager:r,areaManager:s}=e.services,n=r.get(t.id);if(!n)return e.respondError(`Workspace ${t.id} not found`),null;let i=s.getDefaultArea(t.id);return{workspace:{id:n.id,name:n.name,color:n.color,rootDirectory:n.rootDirectory,defaultCommand:n.defaultCommand,terminalCount:n.terminalCount,initGit:n.initGit,createdAt:n.createdAt},area:i?{id:i.id,name:i.name,terminalCount:i.terminalCount,layout:i.layout,defaultCommand:i.defaultCommand,ignoreOnLaunchAll:i.ignoreOnLaunchAll??!1}:null,terminals:i?i.terminals.map(o=>({id:o.id,label:o.label,directory:o.directory,command:o.command,commandSequence:o.commandSequence,startDelay:o.startDelay,startWaitFor:o.startWaitFor,startRunOnce:o.startRunOnce,closeAfterCommand:o.closeAfterCommand,closeDelay:o.closeDelay,closeWaitFor:o.closeWaitFor,runOnce:o.runOnce,commandRunOnce:o.commandRunOnce,color:o.color})):[]}},"workspace.relaunch":async(a,e)=>{let t=a,{workspaceManager:r,areaManager:s,terminalManager:n,portMonitor:i}=e.services,o=r.get(t.id);if(!o)return e.respondError(`Workspace ${t.id} not found`),null;let c=s.getDefaultArea(o.id);if(!c)return e.respondError(`No default area found for workspace ${t.id}`),null;let l=s.list(t.id);for(let h of l){for(let f of h.terminals)n.close(f.id);s.setRunning(h.id,!1)}r.setRunning(t.id,!1),i.stopMonitoring(t.id);let u=l.filter(h=>!h.ignoreOnLaunchAll).map(h=>{s.resetAllTerminals(h.id);let f=s.resolveForLaunch(h,o.rootDirectory);return{area:h,resolved:f}});if(u.length===0){s.resetAllTerminals(c.id);let h=s.resolveForLaunch(c,o.rootDirectory);u.push({area:c,resolved:h})}let p=u.find(h=>h.area.id===c.id)??u[0],m=new Map(p.area.terminals.map(h=>[h.id,h.color||"default"]));return e.respond({ok:!0,terminals:p.resolved.map(h=>({id:h.id,label:h.label,cwd:h.cwd,position:h.position,color:m.get(h.id)||"default"}))}),(async()=>{let h=[];await Promise.all(u.map(async({area:f,resolved:g})=>{try{let w=f.trigger;if(w){let E=w.timeoutMs??12e4;w.type==="delay"?await new Promise(T=>setTimeout(T,w.delayMs??0)):w.type==="waitForOutput"&&w.dependsOnTerminalId&&w.waitForText?await ve(n,w.dependsOnTerminalId,w.waitForText,E):w.type==="waitForExit"&&w.dependsOnTerminalId&&await gs(n,w.dependsOnTerminalId,E)}await ne(g,e.services,f.id,{ignoreRunOnce:!0,completedStepsProvider:E=>s.getCompletedSteps(E),onStepCompleted:(E,T)=>{s.markStepCompleted(E,T)}}),s.setRunning(f.id,!0),e.services.broadcast("area.status",{id:f.id,workspaceId:t.id,state:"running"});for(let E of g)h.push(E.id)}catch(w){console.error(`[server] workspace.relaunch error for area ${f.id}:`,w)}})),r.setRunning(t.id,!0),e.services.broadcast("workspace.status",{id:t.id,state:"running"}),h.length>0&&i.startMonitoring(t.id,h).catch(console.error)})(),null},"workspace.stop":(a,e)=>{let t=a,{workspaceManager:r,areaManager:s,terminalManager:n,portMonitor:i}=e.services,o=r.get(t.id);if(!o)return e.respondError(`Workspace ${t.id} not found`),null;let c=s.list(t.id);for(let l of c){for(let d of l.terminals)n.close(d.id);s.setRunning(l.id,!1),e.services.broadcast("area.status",{id:l.id,workspaceId:t.id,state:"stopped"})}for(let l of o.terminals)n.close(l.id);return r.setRunning(t.id,!1),e.services.broadcast("workspace.status",{id:t.id,state:"stopped"}),i.stopMonitoring(t.id),{ok:!0}}}}function Ss(){return{"area.list":(a,e)=>{let t=a;return e.services.areaManager.list(t.workspaceId)},"area.create":(a,e)=>{let t=a;return e.services.areaManager.create(t)},"area.update":(a,e)=>{let t=a;return e.services.areaManager.update(t)},"area.delete":(a,e)=>{let t=a;return{deleted:e.services.areaManager.delete(t.id)}},"area.duplicate":(a,e)=>{let t=a;return e.services.areaManager.duplicate(t.id,t.name)},"area.launch":async(a,e)=>{let t=a,{areaManager:r,workspaceManager:s}=e.services,n=r.get(t.areaId);if(!n)return e.respondError(`Area ${t.areaId} not found`),null;let i=s.get(t.workspaceId);if(!i)return e.respondError(`Workspace ${t.workspaceId} not found`),null;let o=r.resolveForLaunch(n,i.rootDirectory),c=new Map(n.terminals.map(d=>[d.id,d.color||"default"])),l={ok:!0,terminals:o.map(d=>({id:d.id,label:d.label,cwd:d.cwd,position:d.position,color:c.get(d.id)||"default"}))};return e.respond(l),(async()=>{try{await ne(o,e.services,t.areaId,{completedStepsProvider:d=>r.getCompletedSteps(d),onStepCompleted:(d,u)=>{r.markStepCompleted(d,u)}}),r.setRunning(t.areaId,!0),s.setRunning(t.workspaceId,!0),e.services.broadcast("area.status",{id:t.areaId,workspaceId:t.workspaceId,state:"running"}),e.services.broadcast("workspace.status",{id:t.workspaceId,state:"running"})}catch(d){console.error("[server] area.launch async error:",d)}})(),null},"area.stop":(a,e)=>{let t=a,{areaManager:r,workspaceManager:s,terminalManager:n}=e.services,i=r.get(t.areaId);if(!i)return e.respondError(`Area ${t.areaId} not found`),null;for(let l of i.terminals)n.close(l.id);return r.setRunning(t.areaId,!1),r.clearRuntimeState(t.areaId),r.list(t.workspaceId).some(l=>l.id!==t.areaId&&r.isRunning(l.id))||(s.setRunning(t.workspaceId,!1),e.services.broadcast("workspace.status",{id:t.workspaceId,state:"stopped"})),e.services.broadcast("area.status",{id:t.areaId,workspaceId:t.workspaceId,state:"stopped"}),{ok:!0}},"area.save-runtime-state":(a,e)=>{let t=a;return e.services.areaManager.saveRuntimeState(t.areaId,t.data),{ok:!0}},"area.get-runtime-state":(a,e)=>{let t=a;return{data:e.services.areaManager.getRuntimeState(t.areaId)}},"area.clear-runtime-state":(a,e)=>{let t=a;return e.services.areaManager.clearRuntimeState(t.areaId),{ok:!0}}}}function ys(){return{"swarm.create":(a,e)=>{let t=a;return e.services.swarmManager.create(t)},"swarm.launch":async(a,e)=>{let t=a;return await e.services.swarmManager.launch(t.id),{ok:!0}},"swarm.stop":(a,e)=>{let t=a;return e.services.swarmManager.stop(t.id),{ok:!0}},"swarm.pause":(a,e)=>{let t=a;return e.services.swarmManager.pause(t.id),{ok:!0}},"swarm.resume":(a,e)=>{let t=a;return e.services.swarmManager.resume(t.id),{ok:!0}},"swarm.status":(a,e)=>{let t=a,r=e.services.swarmManager.get(t.id);return r?{...r,stats:e.services.swarmManager.getStats(t.id)}:(e.respondError(`Swarm ${t.id} not found`),null)},"swarm.list":(a,e)=>{let t=a;return e.services.swarmManager.list(t.workspaceId)},"swarm.delete":(a,e)=>{let t=a;return{deleted:e.services.swarmManager.delete(t.id)}},"swarm.message":(a,e)=>{let t=a;return e.services.swarmManager.message(t.swarmId,t.agentId,t.message),{ok:!0}},"swarm.agent.add":(a,e)=>{let t=a;return e.services.swarmManager.addAgent(t)},"swarm.agent.remove":(a,e)=>{let t=a;return{removed:e.services.swarmManager.removeAgent(t)}},"swarm.agent.update":(a,e)=>{let t=a;return e.services.swarmManager.updateAgent(t)},"orchestrator.topology.set":(a,e)=>{let t=a;return e.services.swarmManager.setTopology(t.swarmId,t.topology),{ok:!0}},"orchestrator.spawn-cli":async(a,e)=>{let t=a;return await e.services.swarmManager.spawnCLI(t.swarmId,t.agentId,t.config)},"orchestrator.escalation.respond":(a,e)=>{let t=a;return e.services.swarmManager.respondToEscalation(t.escalationId,t.response),{ok:!0}}}}import{mkdir as Zt,writeFile as Tt,cp as si}from"node:fs/promises";import{basename as ni,join as Z,resolve as ai}from"node:path";var be=class{async buildContext(e){let{task:t,agent:r,swarm:s,knowledgeEntries:n,dependencyTasks:i,workspaceDir:o}=e,c=Z(o,".swarm","tasks",t.id);await Zt(c,{recursive:!0});let l=this.assemblePrompt(t,r,n,i),d=Z(c,"CLAUDE.md"),u=this.generateClaudeMd(t,r,s);await Tt(d,u,"utf-8");let p=this.generateTaskMd(t,i);if(await Tt(Z(c,"TASK.md"),p,"utf-8"),s?.knowledge&&s.knowledge.length>0){let m=Z(c,"knowledge");await Zt(m,{recursive:!0});for(let h of s.knowledge)try{let f=ni(h.name),g=ai(h.path),w=Z(m,f);await si(g,w)}catch{}}return{contextDir:c,prompt:l,claudeMdPath:d}}assemblePrompt(e,t,r,s){let n=[];if(n.push(`# Task: ${e.title}`,""),n.push(e.description,""),n.push("## Agent",""),n.push(`- **Name:** ${t.name}`),n.push(`- **Role:** ${t.role}`),n.push(""),t.workScope&&t.workScope.length>0){n.push("## Work Scope","");for(let i of t.workScope)n.push(`- ${i}`);n.push("")}if(s&&s.length>0){n.push("## Dependencies","");for(let i of s)n.push(`### ${i.title} (${i.status})`),i.output&&n.push("","Output:","",i.output),n.push("")}if(r&&r.length>0){n.push("## Knowledge Base","");for(let i of r)n.push(`- ${i.name} (${i.type}): \`${i.path}\``);n.push("")}switch(n.push(`## Approval Mode: ${e.approvalMode}`,""),e.approvalMode){case"auto":n.push("You may proceed autonomously without waiting for human approval.");break;case"semi":n.push("Proceed with implementation but pause before destructive or irreversible actions.");break;case"manual":n.push("Wait for explicit human approval before making any changes.");break}return n.push(""),n.join(`
284
284
  `)}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(`
285
285
  `)}async buildStandaloneContext(e){let{task:t,prompt:r,workspaceDir:s}=e,n=Z(s,".swarm","tasks",t.id);await Zt(n,{recursive:!0});let i=this.generateTaskMd(t);await Tt(Z(n,"TASK.md"),i,"utf-8");let o=Z(n,"CLAUDE.md"),c=[`# Task: ${t.title}`,"","## Mission",r,"","## Current Task",`- **ID:** ${t.id}`,`- **Title:** ${t.title}`,`- **Approval Mode:** ${t.approvalMode}`,""].join(`
286
286
  `);return await Tt(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(`
287
- `)}};function vs(){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 P=c.workspaceId?n.get(c.workspaceId):null,I=t.workspaceDir||P?.rootDirectory||process.cwd(),U=[];for(let re=0;re<t.terminals.length;re++){let k=t.terminals[re],H=`task-${c.id}-${re}-${Date.now()}`,j;if(k.command)j=k.command;else if(k.cli){let J=await new be().buildStandaloneContext({task:c,cli:k.cli,prompt:k.prompt,workspaceDir:I}),se=o.get(k.cli);j=se?se.buildCommand({mission:J.prompt,cwd:"",autoApprove:k.autoApprove??!1}):k.cli,k.cli==="claude"&&j.startsWith("claude")&&(j=j.replace(/^claude/,"claude -p"))}else j="bash";if(await s.open({id:H,cwd:I,command:j,env:t.env,cols:120,rows:30}),k.command){let z=k.promptDelay??3e3;if(k.commandSequence&&k.commandSequence.length>0){let J=0;for(let se of k.commandSequence)J+=se.delay,setTimeout(()=>{s.write(H,se.command+"\r")},J);k.prompt&&setTimeout(()=>{s.write(H,k.prompt+"\r")},J+z)}else k.prompt&&setTimeout(()=>{s.write(H,k.prompt+"\r")},z)}let At=k.cli||k.command||"shell";r.addTerminal(c.id,H,At,k.prompt,k.autoApprove??!1),U.push(H)}return r.move(c.id,"running"),{taskId:c.id,terminalIds:U,workDir:I}}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(P=>P.id===l);if(!u)return e.respondError(`Agent ${l} not found in swarm`),null;let m=t.includeKnowledge!==!1?d.knowledge:void 0,h;t.includeDependencies&&c.dependencies.length>0&&(h=c.dependencies.map(P=>r.get(P)).filter(P=>P!==null));let g=await new be().buildContext({task:c,agent:u,swarm:d,knowledgeEntries:m,dependencyTasks:h,workspaceDir:d.directory}),w=o.get(u.cli),E=w?w.buildCommand({mission:g.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:E,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 bs(){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 ks(){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 Is(){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 Rs(){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 As(){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 ee from"node:fs";import*as St from"node:os";import*as D from"node:path";import Cs from"node:fs";import Ls from"node:path";import{spawn as ai}from"node:child_process";var ii={"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"},er=class{detectInstalledEditors(){let e=new Set,t=(process.env.PATH||"").split(Ls.delimiter),r=process.platform==="darwin";for(let s of Yt){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(Cs.existsSync(Ls.join(n,s.command))){e.add(s.id);break}}catch{}}if(r)try{let s=Cs.readdirSync("/Applications");for(let n of s){let i=ii[n];i&&!e.has(i)&&e.add(i)}}catch{}return Array.from(e)}openInEditor(e,t){try{let r=Yt.find(o=>o.id===e);if(!r)return{ok:!1,error:`Unknown editor: ${e}`};let s,n;return e==="finder"?(s="open",n=[t]):e==="terminal"?(s="open",n=["-a","Terminal",t]):(s=r.command,n=[t]),ai(s,n,{detached:!0,stdio:"ignore"}).unref(),{ok:!0}}catch(r){return{ok:!1,error:r instanceof Error?r.message:String(r)}}}},tr=new er;function Ms(){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=St.homedir(),r=e.path||t;r==="~"?r=t:r.startsWith("~/")&&(r=D.join(t,r.slice(2))),r=D.resolve(r);try{let s=ee.readdirSync(r),n=[];for(let i of s){if(!e.showHidden&&i.startsWith("."))continue;let o=D.join(r,i);try{ee.statSync(o).isDirectory()&&n.push({name:i,path:o})}catch{}}return n.sort((i,o)=>i.name.localeCompare(o.name)),{current:r,parent:D.dirname(r),home:t,dirs:n}}catch(s){return{current:r,parent:D.dirname(r),home:t,dirs:[],error:s.message}}},"system.createDir":a=>{let t=a.path,r=St.homedir();t.startsWith("~/")&&(t=D.join(r,t.slice(2))),t=D.resolve(t);try{return ee.mkdirSync(t,{recursive:!0}),{ok:!0,path:t}}catch(s){return{ok:!1,error:s.message}}},"system.homeDir":()=>{let a=St.homedir(),e=[{name:"Home",path:a},{name:"Desktop",path:D.join(a,"Desktop")},{name:"Documents",path:D.join(a,"Documents")},{name:"Downloads",path:D.join(a,"Downloads")},{name:"Development",path:D.join(a,"Development")},{name:"Development",path:D.join(a,"Documents","Development")},{name:"Projects",path:D.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{ee.statSync(s.path),t.push(s),r.add(s.name)}catch{}continue}try{ee.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)=>await e.services.providerRegistry.detectInstalled(),"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:tr.detectInstalledEditors()}),"ide.open":a=>{let e=a;return tr.openInEditor(e.editor,e.cwd)},ping:()=>({ok:!0,ts:Date.now()})}}function Os(){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)}},"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.areaId||t.workspaceId)},"layout.save":(a,e)=>{let t=a;return e.services.layoutManager.save(t.areaId?{...t,workspaceId:t.areaId}: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.areaId||t.workspaceId,t.layoutId),{ok:!0}}}}import{readdir as Ds,stat as ke,readFile as yt,writeFile as rr,mkdir as Ie,access as Ps,rm as oi,rename as ci}from"node:fs/promises";import{join as vt,resolve as L,relative as li,dirname as xs}from"node:path";function _s(){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 p;try{p=await Ds(u,{withFileTypes:!0})}catch{return}for(let m of p){if(l.length>=o*5)return;if(n.has(m.name)||m.isSymbolicLink())continue;let h=vt(u,m.name);if(m.isDirectory())await d(h);else if(m.isFile()){let f="."+(m.name.split(".").pop()?.toLowerCase()||"");if(i.has(f))continue;let g=li(s,h);if(c&&!g.toLowerCase().includes(c)&&!m.name.toLowerCase().includes(c))continue;try{let w=await ke(h);l.push({path:g,basename:m.name,size:w.size,modifiedAt:w.mtime.toISOString()})}catch{}}}}return await d(s),l.sort((u,p)=>p.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)+"/")&&i!==L(s))return e.respondError("Path traversal not allowed"),null;try{let o=await ke(i),c=jt(i),l=Kt(i),u=l?10485760:n;return o.size>u?(e.respondError(`File too large: ${o.size} bytes (max ${u})`),null):l?{content:(await yt(i)).toString("base64"),language:c,size:o.size,path:t.filePath,encoding:"base64",mimeType:Gt(i)}:{content:await yt(i,"utf-8"),language:c,size:o.size,path:t.filePath,encoding:"utf-8",mimeType:Gt(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)+"/")&&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,p){if(p<=0)return[];let m;try{m=await Ds(d,{withFileTypes:!0})}catch{return[]}let h=[],f=[],g=[];for(let w of m)c.has(w.name)||w.isSymbolicLink()||(w.isDirectory()?f.push(w):w.isFile()&&g.push(w));f.sort((w,E)=>w.name.toLowerCase().localeCompare(E.name.toLowerCase())),g.sort((w,E)=>w.name.toLowerCase().localeCompare(E.name.toLowerCase()));for(let w of[...f,...g]){let E=vt(d,w.name),T=u?`${u}/${w.name}`:w.name;if(w.isDirectory()){let _=await l(E,T,p-1);h.push({name:w.name,path:T,type:"directory",children:_})}else{let _;try{_=(await ke(E)).size}catch{}h.push({name:w.name,path:T,type:"file",size:_})}}return h}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)+"/")&&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=vt(n,"..");return await Ie(o,{recursive:!0}),await rr(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)+"/")&&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 Ps(n),e.respondError(`File already exists: ${t.filePath}`),null}catch{}try{let o=vt(n,"..");return await Ie(o,{recursive:!0}),await rr(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+"/"))return e.respondError("Path traversal not allowed"),null;if(n===i)return e.respondError("Cannot delete workspace root"),null;let o;try{o=(await ke(n)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.filePath}`),null}let c=t.recursive??!0,l,d;if(o==="file")try{Kt(n)?(l=(await yt(n)).toString("base64"),d="base64"):(l=await yt(n,"utf-8"),d="utf-8")}catch{}try{return await oi(n,{recursive:c,force:!1}),{ok:!0,path:t.filePath,type:o,content:l,encoding:d}}catch(u){let p=u instanceof Error?u.message:"Failed to delete";return e.respondError(p),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+"/")||!o.startsWith(n+"/"))return e.respondError("Path traversal not allowed"),null;let c;try{c=(await ke(i)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.sourcePath}`),null}try{let l=xs(o);return await Ie(l,{recursive:!0}),await ci(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+"/"))return e.respondError("Path traversal not allowed"),null;try{return await Ps(n),e.respondError(`Already exists: ${t.filePath}`),null}catch{}try{if(t.type==="directory")await Ie(n,{recursive:!0});else{let o=xs(n);await Ie(o,{recursive:!0}),await rr(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 Us(){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)},"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 Fs(){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 Bs(){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 Ws(){return{...Es(),...Ts(),...Ss(),...ys(),...vs(),...bs(),...ks(),...Is(),...Rs(),...As(),...Ms(),...Os(),..._s(),...Us(),...Fs(),...Bs()}}var pi=new Set(["127.0.0.1","::1","::ffff:127.0.0.1","localhost"]);function mi(a){let e=a.socket.remoteAddress;return e?pi.has(e):!1}function gi(a){try{return new URL(a.url||"/",`http://${a.headers.host||"localhost"}`).searchParams.get("token")}catch{return null}}function $s(a,e){let t={fn:()=>{}},r={mgr:null},s=new at((y,b)=>t.fn(y,b)),n=new di({server:a,path:"/ws",verifyClient:(y,b)=>{if(mi(y.req)){b(!0);return}if(s.isActive()){let M=gi(y.req);s.validateToken(M)?b(!0):b(!1,401,"Unauthorized: invalid or missing token");return}b(!1,403,"Remote connections not allowed without tunnel")}}),i=[],o=new Set,c=new WeakMap,l,d,u=setInterval(()=>{for(let y of o){if(!c.get(y)){y.terminate();continue}c.set(y,!1),y.ping()}},3e4);n.on("close",()=>{clearInterval(u),hr.dispose()});function p(y,b){let F=JSON.stringify({type:"push",channel:y,data:b});for(let v of o)v.readyState===ui.OPEN&&v.send(F);for(let v of i)try{v(F)}catch{}if(y==="terminal.output"){let v=b;P.onTerminalOutput(v.id,v.data)}if(y==="terminal.exited"){let v=b,C=U.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let{allDone:q,hasError:G}=U.markTerminalExited(C.id,v.id,v.exitCode);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:v.exitCode,allDone:q}),q){let ce=G?"blocked":"waiting";U.move(C.id,ce)}}}if(y==="ports.update"&&r.mgr)try{let v=b;r.mgr.cleanupStaleTunnels(v.ports.map(C=>C.port))}catch(v){console.error("[PortTunnelManager] cleanup error:",v)}if(y==="terminal.process"){let v=b;if(v.process.isIdle){let C=U.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let G=U.getTaskTerminals(C.id).find(ce=>ce.terminalId===v.id);if(G&&G.status==="running"){let{allDone:ce,hasError:rn}=U.markTerminalExited(C.id,v.id,0);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:0,allDone:ce}),ce){let sn=rn?"blocked":"waiting";U.move(C.id,sn)}}}}}}e.prepare("UPDATE workspace_state SET isRunning = 0").run(),e.prepare("UPDATE area_state SET isRunning = 0").run();let m=new Pe(p),h=e.prepare("SELECT id FROM terminal_configs").all(),f=new Set(h.map(y=>y.id));try{let y=e.prepare("SELECT data FROM area_runtime_state").all();for(let b of y){let M=JSON.parse(b.data);if(M.terminals)for(let F of M.terminals)f.add(F.id)}}catch{}let g=m.recoverSessions(f);if(g.length>0){let y=e.prepare("SELECT workspaceId, areaId FROM terminal_configs WHERE id = ?"),b=e.prepare("INSERT INTO workspace_state (workspaceId, isRunning) VALUES (?, 1) ON CONFLICT(workspaceId) DO UPDATE SET isRunning = 1"),M=e.prepare("INSERT INTO area_state (areaId, isRunning) VALUES (?, 1) ON CONFLICT(areaId) DO UPDATE SET isRunning = 1"),F=new Map;try{let v=e.prepare("SELECT areaId, data FROM area_runtime_state").all();for(let C of v){let q=JSON.parse(C.data);if(q.terminals)for(let G of q.terminals)F.set(G.id,C.areaId)}}catch{}for(let v of g){let C=y.get(v);if(C)b.run(C.workspaceId),C.areaId&&M.run(C.areaId);else{let q=F.get(v);if(q){let G=e.prepare("SELECT workspaceId FROM areas WHERE id = ?").get(q);G&&(b.run(G.workspaceId),M.run(q))}}}console.log("[server] Restored running state for workspaces with recovered terminals")}let w=new _e(e),E=new xe(e,w),T=new Ye,_=new et(e),oe=new tt(e),P=new je(e,m,p,T),I=new Ge,U=new Ke(e,p),pr=new Qe(p),re=new st(p),k=new nt(p,y=>{let b=m.getProcessInfo(y);return b&&b.pid>0?b.pid:null});t.fn=p;let H=new it((y,b)=>t.fn(y,b));r.mgr=H;let j=new lt(p),At=new dt(e),z=new ut(e);z.seed();let J=new mt(e);J.seed(z);let se=new gt({terminalManager:m,areaManager:w,workspaceTemplateManager:z,workspaceManager:E}),mr=new pt(e),gr=new ft(p),hr=new ht((y,b)=>{if(p(y,b),y==="notification.new"){let M=b;gr.add(M.type,M.title,M.message,M.source)}}),en=new wt,tn=new Et(e);P.setTaskManager(U),P.setSettingsManager(_);let fr={terminalManager:m,workspaceManager:E,areaManager:w,swarmManager:P,skillsRegistry:I,taskManager:U,providerRegistry:T,prdBuilder:pr,settingsManager:_,cliToolsManager:oe,browserManager:re,tunnel:s,portTunnelManager:H,wireframeManager:j,templateManager:At,workspaceTemplateManager:z,stackManager:J,stackOrchestrator:se,layoutManager:mr,healthCheckService:hr,notificationService:gr,portMonitor:k,gitManager:en,gitHubCliManager:tn,relayClient:null,broadcast:p},wr=Ws();return n.on("connection",(y,b)=>{o.add(y),c.set(y,!0),y.on("pong",()=>{c.set(y,!0)});let M=!1;l&&(clearTimeout(l),l=void 0,M=!0),d&&(clearTimeout(d),d=void 0,M=!0),M&&console.log("[server] Client reconnected \u2014 cancelling cleanup timers"),y.on("message",F=>{let v;try{v=JSON.parse(F.toString())}catch{return}sr(v,y,fr,wr)}),y.on("close",()=>{if(o.delete(y),o.size===0){console.log("[server] All clients disconnected \u2014 starting grace periods"),l=setTimeout(()=>{console.log("[server] 30s grace expired \u2014 cleaning up non-critical resources"),re.stopAll(),k.dispose(),H.stopAll(),l=void 0},3e4);let F=m.useTmux?1440*60*1e3:14400*1e3;d=setTimeout(()=>{let v=F/36e5;console.log(`[server] ${v}h timeout \u2014 closing all terminals`),m.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(),d=void 0},F)}})}),{wss:n,terminalManager:m,workspaceManager:E,swarmManager:P,settingsManager:_,broadcast:p,externalSenders:i,services:fr,routes:wr,getClientCount:()=>o.size}}async function sr(a,e,t,r){let{id:s,method:n,params:i}=a,o=r[n];if(!o){he(e,{id:s,error:{message:`Unknown method: ${n}`}});return}let c=!1,l={ws:e,id:s,services:t,respond:d=>{c=!0,he(e,{id:s,result:d})},respondError:d=>{c=!0,he(e,{id:s,error:{message:d}})}};try{let d=await o(i,l);!c&&d!==null&&d!==void 0&&he(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";he(e,{id:s,error:{message:u}})}}}import{DatabaseSync as hi}from"node:sqlite";import{mkdirSync as fi,existsSync as wi}from"node:fs";import{join as Hs}from"node:path";import{homedir as Ei}from"node:os";import{randomUUID as Ti}from"node:crypto";var nr=Hs(Ei(),".impactus-swarm"),Si=Hs(nr,"swarm.db");function qs(){wi(nr)||fi(nr,{recursive:!0});let a=new hi(Si);a.exec("PRAGMA journal_mode = WAL"),a.exec("PRAGMA foreign_keys = ON"),a.exec(`
287
+ `)}};function vs(){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 P=c.workspaceId?n.get(c.workspaceId):null,I=t.workspaceDir||P?.rootDirectory||process.cwd(),U=[];for(let re=0;re<t.terminals.length;re++){let k=t.terminals[re],H=`task-${c.id}-${re}-${Date.now()}`,j;if(k.command)j=k.command;else if(k.cli){let J=await new be().buildStandaloneContext({task:c,cli:k.cli,prompt:k.prompt,workspaceDir:I}),se=o.get(k.cli);j=se?se.buildCommand({mission:J.prompt,cwd:"",autoApprove:k.autoApprove??!1}):k.cli,k.cli==="claude"&&j.startsWith("claude")&&(j=j.replace(/^claude/,"claude -p"))}else j="bash";if(await s.open({id:H,cwd:I,command:j,env:t.env,cols:120,rows:30}),k.command){let z=k.promptDelay??3e3;if(k.commandSequence&&k.commandSequence.length>0){let J=0;for(let se of k.commandSequence)J+=se.delay,setTimeout(()=>{s.write(H,se.command+"\r")},J);k.prompt&&setTimeout(()=>{s.write(H,k.prompt+"\r")},J+z)}else k.prompt&&setTimeout(()=>{s.write(H,k.prompt+"\r")},z)}let At=k.cli||k.command||"shell";r.addTerminal(c.id,H,At,k.prompt,k.autoApprove??!1),U.push(H)}return r.move(c.id,"running"),{taskId:c.id,terminalIds:U,workDir:I}}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(P=>P.id===l);if(!u)return e.respondError(`Agent ${l} not found in swarm`),null;let m=t.includeKnowledge!==!1?d.knowledge:void 0,h;t.includeDependencies&&c.dependencies.length>0&&(h=c.dependencies.map(P=>r.get(P)).filter(P=>P!==null));let g=await new be().buildContext({task:c,agent:u,swarm:d,knowledgeEntries:m,dependencyTasks:h,workspaceDir:d.directory}),w=o.get(u.cli),E=w?w.buildCommand({mission:g.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:E,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 bs(){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 ks(){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 Is(){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 Rs(){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 As(){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 ee from"node:fs";import*as St from"node:os";import*as D from"node:path";import Cs from"node:fs";import Ls from"node:path";import{spawn as ii}from"node:child_process";var oi={"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"},er=class{detectInstalledEditors(){let e=new Set,t=(process.env.PATH||"").split(Ls.delimiter),r=process.platform==="darwin";for(let s of Yt){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(Cs.existsSync(Ls.join(n,s.command))){e.add(s.id);break}}catch{}}if(r)try{let s=Cs.readdirSync("/Applications");for(let n of s){let i=oi[n];i&&!e.has(i)&&e.add(i)}}catch{}return Array.from(e)}openInEditor(e,t){try{let r=Yt.find(o=>o.id===e);if(!r)return{ok:!1,error:`Unknown editor: ${e}`};let s,n;return e==="finder"?(s="open",n=[t]):e==="terminal"?(s="open",n=["-a","Terminal",t]):(s=r.command,n=[t]),ii(s,n,{detached:!0,stdio:"ignore"}).unref(),{ok:!0}}catch(r){return{ok:!1,error:r instanceof Error?r.message:String(r)}}}},tr=new er;function Ms(){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=St.homedir(),r=e.path||t;r==="~"?r=t:r.startsWith("~/")&&(r=D.join(t,r.slice(2))),r=D.resolve(r);try{let s=ee.readdirSync(r),n=[];for(let i of s){if(!e.showHidden&&i.startsWith("."))continue;let o=D.join(r,i);try{ee.statSync(o).isDirectory()&&n.push({name:i,path:o})}catch{}}return n.sort((i,o)=>i.name.localeCompare(o.name)),{current:r,parent:D.dirname(r),home:t,dirs:n}}catch(s){return{current:r,parent:D.dirname(r),home:t,dirs:[],error:s.message}}},"system.createDir":a=>{let t=a.path,r=St.homedir();t.startsWith("~/")&&(t=D.join(r,t.slice(2))),t=D.resolve(t);try{return ee.mkdirSync(t,{recursive:!0}),{ok:!0,path:t}}catch(s){return{ok:!1,error:s.message}}},"system.homeDir":()=>{let a=St.homedir(),e=[{name:"Home",path:a},{name:"Desktop",path:D.join(a,"Desktop")},{name:"Documents",path:D.join(a,"Documents")},{name:"Downloads",path:D.join(a,"Downloads")},{name:"Development",path:D.join(a,"Development")},{name:"Development",path:D.join(a,"Documents","Development")},{name:"Projects",path:D.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{ee.statSync(s.path),t.push(s),r.add(s.name)}catch{}continue}try{ee.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)=>await e.services.providerRegistry.detectInstalled(),"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:tr.detectInstalledEditors()}),"ide.open":a=>{let e=a;return tr.openInEditor(e.editor,e.cwd)},ping:()=>({ok:!0,ts:Date.now()})}}function Os(){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)}},"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.areaId||t.workspaceId)},"layout.save":(a,e)=>{let t=a;return e.services.layoutManager.save(t.areaId?{...t,workspaceId:t.areaId}: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.areaId||t.workspaceId,t.layoutId),{ok:!0}}}}import{readdir as Ds,stat as ke,readFile as yt,writeFile as rr,mkdir as Ie,access as Ps,rm as ci,rename as li}from"node:fs/promises";import{join as vt,resolve as L,relative as di,dirname as xs}from"node:path";function _s(){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 p;try{p=await Ds(u,{withFileTypes:!0})}catch{return}for(let m of p){if(l.length>=o*5)return;if(n.has(m.name)||m.isSymbolicLink())continue;let h=vt(u,m.name);if(m.isDirectory())await d(h);else if(m.isFile()){let f="."+(m.name.split(".").pop()?.toLowerCase()||"");if(i.has(f))continue;let g=di(s,h);if(c&&!g.toLowerCase().includes(c)&&!m.name.toLowerCase().includes(c))continue;try{let w=await ke(h);l.push({path:g,basename:m.name,size:w.size,modifiedAt:w.mtime.toISOString()})}catch{}}}}return await d(s),l.sort((u,p)=>p.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)+"/")&&i!==L(s))return e.respondError("Path traversal not allowed"),null;try{let o=await ke(i),c=jt(i),l=Kt(i),u=l?10485760:n;return o.size>u?(e.respondError(`File too large: ${o.size} bytes (max ${u})`),null):l?{content:(await yt(i)).toString("base64"),language:c,size:o.size,path:t.filePath,encoding:"base64",mimeType:Gt(i)}:{content:await yt(i,"utf-8"),language:c,size:o.size,path:t.filePath,encoding:"utf-8",mimeType:Gt(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)+"/")&&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,p){if(p<=0)return[];let m;try{m=await Ds(d,{withFileTypes:!0})}catch{return[]}let h=[],f=[],g=[];for(let w of m)c.has(w.name)||w.isSymbolicLink()||(w.isDirectory()?f.push(w):w.isFile()&&g.push(w));f.sort((w,E)=>w.name.toLowerCase().localeCompare(E.name.toLowerCase())),g.sort((w,E)=>w.name.toLowerCase().localeCompare(E.name.toLowerCase()));for(let w of[...f,...g]){let E=vt(d,w.name),T=u?`${u}/${w.name}`:w.name;if(w.isDirectory()){let _=await l(E,T,p-1);h.push({name:w.name,path:T,type:"directory",children:_})}else{let _;try{_=(await ke(E)).size}catch{}h.push({name:w.name,path:T,type:"file",size:_})}}return h}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)+"/")&&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=vt(n,"..");return await Ie(o,{recursive:!0}),await rr(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)+"/")&&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 Ps(n),e.respondError(`File already exists: ${t.filePath}`),null}catch{}try{let o=vt(n,"..");return await Ie(o,{recursive:!0}),await rr(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+"/"))return e.respondError("Path traversal not allowed"),null;if(n===i)return e.respondError("Cannot delete workspace root"),null;let o;try{o=(await ke(n)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.filePath}`),null}let c=t.recursive??!0,l,d;if(o==="file")try{Kt(n)?(l=(await yt(n)).toString("base64"),d="base64"):(l=await yt(n,"utf-8"),d="utf-8")}catch{}try{return await ci(n,{recursive:c,force:!1}),{ok:!0,path:t.filePath,type:o,content:l,encoding:d}}catch(u){let p=u instanceof Error?u.message:"Failed to delete";return e.respondError(p),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+"/")||!o.startsWith(n+"/"))return e.respondError("Path traversal not allowed"),null;let c;try{c=(await ke(i)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.sourcePath}`),null}try{let l=xs(o);return await Ie(l,{recursive:!0}),await li(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+"/"))return e.respondError("Path traversal not allowed"),null;try{return await Ps(n),e.respondError(`Already exists: ${t.filePath}`),null}catch{}try{if(t.type==="directory")await Ie(n,{recursive:!0});else{let o=xs(n);await Ie(o,{recursive:!0}),await rr(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 Us(){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)},"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 Fs(){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 Bs(){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 Ws(){return{...Es(),...Ts(),...Ss(),...ys(),...vs(),...bs(),...ks(),...Is(),...Rs(),...As(),...Ms(),...Os(),..._s(),...Us(),...Fs(),...Bs()}}var mi=new Set(["127.0.0.1","::1","::ffff:127.0.0.1","localhost"]);function gi(a){let e=a.socket.remoteAddress;return e?mi.has(e):!1}function hi(a){try{return new URL(a.url||"/",`http://${a.headers.host||"localhost"}`).searchParams.get("token")}catch{return null}}function $s(a,e){let t={fn:()=>{}},r={mgr:null},s=new at((y,b)=>t.fn(y,b)),n=new ui({server:a,path:"/ws",verifyClient:(y,b)=>{if(gi(y.req)){b(!0);return}if(s.isActive()){let M=hi(y.req);s.validateToken(M)?b(!0):b(!1,401,"Unauthorized: invalid or missing token");return}b(!1,403,"Remote connections not allowed without tunnel")}}),i=[],o=new Set,c=new WeakMap,l,d,u=setInterval(()=>{for(let y of o){if(!c.get(y)){y.terminate();continue}c.set(y,!1),y.ping()}},3e4);n.on("close",()=>{clearInterval(u),hr.dispose()});function p(y,b){let F=JSON.stringify({type:"push",channel:y,data:b});for(let v of o)v.readyState===pi.OPEN&&v.send(F);for(let v of i)try{v(F)}catch{}if(y==="terminal.output"){let v=b;P.onTerminalOutput(v.id,v.data)}if(y==="terminal.exited"){let v=b,C=U.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let{allDone:q,hasError:G}=U.markTerminalExited(C.id,v.id,v.exitCode);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:v.exitCode,allDone:q}),q){let ce=G?"blocked":"waiting";U.move(C.id,ce)}}}if(y==="ports.update"&&r.mgr)try{let v=b;r.mgr.cleanupStaleTunnels(v.ports.map(C=>C.port))}catch(v){console.error("[PortTunnelManager] cleanup error:",v)}if(y==="terminal.process"){let v=b;if(v.process.isIdle){let C=U.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let G=U.getTaskTerminals(C.id).find(ce=>ce.terminalId===v.id);if(G&&G.status==="running"){let{allDone:ce,hasError:rn}=U.markTerminalExited(C.id,v.id,0);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:0,allDone:ce}),ce){let sn=rn?"blocked":"waiting";U.move(C.id,sn)}}}}}}e.prepare("UPDATE workspace_state SET isRunning = 0").run(),e.prepare("UPDATE area_state SET isRunning = 0").run();let m=new Pe(p),h=e.prepare("SELECT id FROM terminal_configs").all(),f=new Set(h.map(y=>y.id));try{let y=e.prepare("SELECT data FROM area_runtime_state").all();for(let b of y){let M=JSON.parse(b.data);if(M.terminals)for(let F of M.terminals)f.add(F.id)}}catch{}let g=m.recoverSessions(f);if(g.length>0){let y=e.prepare("SELECT workspaceId, areaId FROM terminal_configs WHERE id = ?"),b=e.prepare("INSERT INTO workspace_state (workspaceId, isRunning) VALUES (?, 1) ON CONFLICT(workspaceId) DO UPDATE SET isRunning = 1"),M=e.prepare("INSERT INTO area_state (areaId, isRunning) VALUES (?, 1) ON CONFLICT(areaId) DO UPDATE SET isRunning = 1"),F=new Map;try{let v=e.prepare("SELECT areaId, data FROM area_runtime_state").all();for(let C of v){let q=JSON.parse(C.data);if(q.terminals)for(let G of q.terminals)F.set(G.id,C.areaId)}}catch{}for(let v of g){let C=y.get(v);if(C)b.run(C.workspaceId),C.areaId&&M.run(C.areaId);else{let q=F.get(v);if(q){let G=e.prepare("SELECT workspaceId FROM areas WHERE id = ?").get(q);G&&(b.run(G.workspaceId),M.run(q))}}}console.log("[server] Restored running state for workspaces with recovered terminals")}let w=new _e(e),E=new xe(e,w),T=new Ye,_=new et(e),oe=new tt(e),P=new je(e,m,p,T),I=new Ge,U=new Ke(e,p),pr=new Qe(p),re=new st(p),k=new nt(p,y=>{let b=m.getProcessInfo(y);return b&&b.pid>0?b.pid:null});t.fn=p;let H=new it((y,b)=>t.fn(y,b));r.mgr=H;let j=new lt(p),At=new dt(e),z=new ut(e);z.seed();let J=new mt(e);J.seed(z);let se=new gt({terminalManager:m,areaManager:w,workspaceTemplateManager:z,workspaceManager:E}),mr=new pt(e),gr=new ft(p),hr=new ht((y,b)=>{if(p(y,b),y==="notification.new"){let M=b;gr.add(M.type,M.title,M.message,M.source)}}),en=new wt,tn=new Et(e);P.setTaskManager(U),P.setSettingsManager(_);let fr={terminalManager:m,workspaceManager:E,areaManager:w,swarmManager:P,skillsRegistry:I,taskManager:U,providerRegistry:T,prdBuilder:pr,settingsManager:_,cliToolsManager:oe,browserManager:re,tunnel:s,portTunnelManager:H,wireframeManager:j,templateManager:At,workspaceTemplateManager:z,stackManager:J,stackOrchestrator:se,layoutManager:mr,healthCheckService:hr,notificationService:gr,portMonitor:k,gitManager:en,gitHubCliManager:tn,relayClient:null,broadcast:p},wr=Ws();return n.on("connection",(y,b)=>{o.add(y),c.set(y,!0),y.on("pong",()=>{c.set(y,!0)});let M=!1;l&&(clearTimeout(l),l=void 0,M=!0),d&&(clearTimeout(d),d=void 0,M=!0),M&&console.log("[server] Client reconnected \u2014 cancelling cleanup timers"),y.on("message",F=>{let v;try{v=JSON.parse(F.toString())}catch{return}sr(v,y,fr,wr)}),y.on("close",()=>{if(o.delete(y),o.size===0){console.log("[server] All clients disconnected \u2014 starting grace periods"),l=setTimeout(()=>{console.log("[server] 30s grace expired \u2014 cleaning up non-critical resources"),re.stopAll(),k.dispose(),H.stopAll(),l=void 0},3e4);let F=m.useTmux?1440*60*1e3:14400*1e3;d=setTimeout(()=>{let v=F/36e5;console.log(`[server] ${v}h timeout \u2014 closing all terminals`),m.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(),d=void 0},F)}})}),{wss:n,terminalManager:m,workspaceManager:E,swarmManager:P,settingsManager:_,broadcast:p,externalSenders:i,services:fr,routes:wr,getClientCount:()=>o.size}}async function sr(a,e,t,r){let{id:s,method:n,params:i}=a,o=r[n];if(!o){he(e,{id:s,error:{message:`Unknown method: ${n}`}});return}let c=!1,l={ws:e,id:s,services:t,respond:d=>{c=!0,he(e,{id:s,result:d})},respondError:d=>{c=!0,he(e,{id:s,error:{message:d}})}};try{let d=await o(i,l);!c&&d!==null&&d!==void 0&&he(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";he(e,{id:s,error:{message:u}})}}}import{DatabaseSync as fi}from"node:sqlite";import{mkdirSync as wi,existsSync as Ei}from"node:fs";import{join as Hs}from"node:path";import{homedir as Ti}from"node:os";import{randomUUID as Si}from"node:crypto";var nr=Hs(Ti(),".impactus-swarm"),yi=Hs(nr,"swarm.db");function qs(){Ei(nr)||wi(nr,{recursive:!0});let a=new fi(yi);a.exec("PRAGMA journal_mode = WAL"),a.exec("PRAGMA foreign_keys = ON"),a.exec(`
288
288
  CREATE TABLE IF NOT EXISTS workspaces (
289
289
  id TEXT PRIMARY KEY,
290
290
  name TEXT NOT NULL,
@@ -603,7 +603,7 @@ ${h?"Binary file":"File too large to preview"} (untracked)
603
603
  connectedAt TEXT NOT NULL,
604
604
  FOREIGN KEY (workspaceId) REFERENCES workspaces(id) ON DELETE CASCADE
605
605
  )
606
- `);try{a.exec("ALTER TABLE workspaces ADD COLUMN initGit INTEGER NOT NULL DEFAULT 1")}catch{}try{a.exec("ALTER TABLE terminal_configs ADD COLUMN areaId TEXT")}catch{}try{a.exec("ALTER TABLE saved_layouts ADD COLUMN areaId TEXT")}catch{}try{a.exec("ALTER TABLE swarms ADD COLUMN areaId TEXT")}catch{}try{a.exec("ALTER TABLE workspaces ADD COLUMN stackId TEXT")}catch{}try{a.exec("ALTER TABLE areas ADD COLUMN templateId TEXT")}catch{}try{a.exec("ALTER TABLE areas ADD COLUMN ignoreOnLaunchAll INTEGER NOT NULL DEFAULT 0")}catch{}try{a.exec("ALTER TABLE areas ADD COLUMN trigger TEXT")}catch{}try{a.exec("ALTER TABLE workspaces ADD COLUMN imageUrl TEXT")}catch{}try{a.exec("ALTER TABLE workspace_templates ADD COLUMN version TEXT NOT NULL DEFAULT '1.00'")}catch{}try{a.exec("ALTER TABLE stacks ADD COLUMN version TEXT NOT NULL DEFAULT '1.00'")}catch{}return yi(a),a}function yi(a){let t=a.prepare(`
606
+ `);try{a.exec("ALTER TABLE workspaces ADD COLUMN initGit INTEGER NOT NULL DEFAULT 1")}catch{}try{a.exec("ALTER TABLE terminal_configs ADD COLUMN areaId TEXT")}catch{}try{a.exec("ALTER TABLE saved_layouts ADD COLUMN areaId TEXT")}catch{}try{a.exec("ALTER TABLE swarms ADD COLUMN areaId TEXT")}catch{}try{a.exec("ALTER TABLE workspaces ADD COLUMN stackId TEXT")}catch{}try{a.exec("ALTER TABLE areas ADD COLUMN templateId TEXT")}catch{}try{a.exec("ALTER TABLE areas ADD COLUMN ignoreOnLaunchAll INTEGER NOT NULL DEFAULT 0")}catch{}try{a.exec("ALTER TABLE areas ADD COLUMN trigger TEXT")}catch{}try{a.exec("ALTER TABLE workspaces ADD COLUMN imageUrl TEXT")}catch{}try{a.exec("ALTER TABLE workspace_templates ADD COLUMN version TEXT NOT NULL DEFAULT '1.00'")}catch{}try{a.exec("ALTER TABLE stacks ADD COLUMN version TEXT NOT NULL DEFAULT '1.00'")}catch{}return vi(a),a}function vi(a){let t=a.prepare(`
607
607
  SELECT w.id, w.name, w.color, w.defaultCommand, w.terminalCount, w.layout
608
608
  FROM workspaces w
609
609
  LEFT JOIN areas a ON a.workspaceId = w.id
@@ -611,7 +611,7 @@ ${h?"Binary file":"File too large to preview"} (untracked)
611
611
  `).all();if(t.length===0)return;let r=new Date().toISOString(),s=a.prepare(`
612
612
  INSERT INTO areas (id, workspaceId, name, color, directory, useWorktree, defaultCommand, terminalCount, layout, "order", isDefault, createdAt, updatedAt)
613
613
  VALUES (?, ?, ?, ?, '', 0, ?, ?, ?, 0, 1, ?, ?)
614
- `),n=a.prepare("INSERT OR IGNORE INTO area_state (areaId) VALUES (?)"),i=a.prepare("UPDATE terminal_configs SET areaId = ? WHERE workspaceId = ? AND (areaId IS NULL OR areaId = '')"),o=a.prepare("UPDATE saved_layouts SET areaId = ? WHERE workspaceId = ? AND (areaId IS NULL OR areaId = '')"),c=a.prepare("UPDATE swarms SET areaId = ? WHERE workspaceId = ? AND (areaId IS NULL OR areaId = '')");for(let l of t){let d=Ti();s.run(d,l.id,"Principal",l.color,l.defaultCommand,l.terminalCount,l.layout,r,r),n.run(d),i.run(d,l.id),o.run(d,l.id),c.run(d,l.id)}}import ae from"ws";var Xs={debug:0,info:1,warn:2,error:3},vi=process.env.LOG_LEVEL?.toLowerCase()??"info";function bi(a){return!a||Object.keys(a).length===0?"":` | ${Object.entries(a).map(([t,r])=>`${t}=${r}`).join(" ")}`}var ar=class{constructor(e){this.module=e}log(e,t,r){if(Xs[e]<Xs[vi])return;let s=new Date().toISOString(),n=e.toUpperCase().padEnd(5),i=`[${s}] [${n}] [${this.module}] ${t}${bi(r)}`;switch(e){case"error":console.error(i);break;case"warn":console.warn(i);break;default:console.log(i);break}}debug(e,t){this.log("debug",e,t)}info(e,t){this.log("info",e,t)}warn(e,t){this.log("warn",e,t)}error(e,t){this.log("error",e,t)}};function js(a){return new ar(a)}var x=js("relay"),ki=15e3,Ii=15e3,Ri=480*60*1e3,bt=class a{ws=null;_code=null;relayUrl;allowedIps;reconnectDelay=1e3;maxReconnectDelay=3e4;shouldReconnect=!0;pingTimer=null;pongTimer=null;sessionTimer=null;connectedAt=null;lastCode=null;reconnectToken=null;lastStableConnectTime=0;rapidDisconnectCount=0;static STABILITY_THRESHOLD_MS=3e4;static MAX_RAPID_FAILURES=10;static REGISTRATION_TIMEOUT_MS=15e3;onMessage;onCodeChange;constructor(e,t=[]){this.relayUrl=e,this.allowedIps=t}get code(){return this._code}get connected(){return this.ws?.readyState===ae.OPEN}getStatus(){return{code:this._code,connected:this.connected,connectedAt:this.connectedAt,relayUrl:this.relayUrl}}connect(){return new Promise((e,t)=>{let r=`${this.relayUrl.replace(/^http/,"ws")}/ws/server`;this.ws=new ae(r);let s=!1,n=null,i=()=>{n&&(clearTimeout(n),n=null)};n=setTimeout(()=>{if(!s){s=!0,i(),x.error("Registration timeout \u2014 no response from relay server");try{this.ws?.terminate()}catch{}t(new Error("Registration timeout"))}},a.REGISTRATION_TIMEOUT_MS),this.ws.on("open",()=>{this.lastStableConnectTime=Date.now(),this.connectedAt=new Date().toISOString(),x.info("WebSocket opened",{attemptingReclaim:!!(this.lastCode&&this.reconnectToken),lastCode:this.lastCode}),this.lastCode&&this.reconnectToken?this.ws.send(JSON.stringify({type:"reconnect",code:this.lastCode,reconnect_token:this.reconnectToken,allowed_ips:this.allowedIps})):this.ws.send(JSON.stringify({type:"register",allowed_ips:this.allowedIps})),this.startPing(),this.startSessionTimer()}),this.ws.on("message",o=>{let c=o.toString();try{let l=JSON.parse(c);if(l.type==="registered"&&l.code){i(),this._code=l.code,this.lastCode=l.code,l.reconnect_token&&(this.reconnectToken=l.reconnect_token),x.info("Registered with relay",{code:l.code,reclaimed:!!l.reclaimed}),s||(s=!0,e(l.code)),this.onCodeChange?.(l.code);return}if(l.type==="pong"){this.pongTimer&&(clearTimeout(this.pongTimer),this.pongTimer=null);return}if(l.type==="ping"){try{this.ws.send(JSON.stringify({type:"pong"}))}catch{}return}}catch{}if(this.onMessage&&this.ws){let l=this.createVirtualWs();this.onMessage(c,l)}}),this.ws.on("pong",()=>{this.pongTimer&&(clearTimeout(this.pongTimer),this.pongTimer=null)}),this.ws.on("close",(o,c)=>{i(),x.warn("Connection closed",{closeCode:o,reason:c.toString()||"none",connectionDuration:`${Date.now()-this.lastStableConnectTime}ms`,lastCode:this.lastCode}),s||(s=!0,t(new Error("Connection closed before registration"))),this.handleDisconnect()}),this.ws.on("error",o=>{x.error("Connection error",{error:o.message})})})}async reconnect(){if(this.stopPing(),this.stopSessionTimer(),this.ws){this.ws.removeAllListeners();try{this.ws.close()}catch{}this.ws=null}return this._code=null,this.lastCode=null,this.reconnectToken=null,this.rapidDisconnectCount=0,this.reconnectDelay=1e3,this.connect()}createVirtualWs(){let e=this;return{readyState:ae.OPEN,send(t){e.ws?.readyState===ae.OPEN&&e.ws.send(t)}}}send(e){this.ws?.readyState===ae.OPEN&&this.ws.send(e)}close(){this.shouldReconnect=!1,this.stopPing(),this.stopSessionTimer(),this.ws?.close()}startPing(){this.stopPing(),this.pingTimer=setInterval(()=>{if(this.ws?.readyState===ae.OPEN){try{this.ws.send(JSON.stringify({type:"ping"}))}catch{}try{this.ws.ping()}catch{}this.pongTimer&&clearTimeout(this.pongTimer),this.pongTimer=setTimeout(()=>{this.ws?.readyState===ae.OPEN&&(x.warn("Pong timeout \u2014 forcing reconnect"),this.ws.terminate()),this.pongTimer=null},Ii)}},ki)}stopPing(){this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=null),this.pongTimer&&(clearTimeout(this.pongTimer),this.pongTimer=null)}startSessionTimer(){this.stopSessionTimer(),this.sessionTimer=setTimeout(()=>{x.info("Session expired (8h) \u2014 reconnecting"),this.reconnect().then(e=>x.info("Session refreshed with new code",{code:e})).catch(()=>x.error("Session refresh failed"))},Ri)}stopSessionTimer(){this.sessionTimer&&(clearTimeout(this.sessionTimer),this.sessionTimer=null)}handleDisconnect(){let e=this.lastStableConnectTime>0?Date.now()-this.lastStableConnectTime:0;if(this._code=null,this.connectedAt=null,this.stopPing(),this.stopSessionTimer(),!this.shouldReconnect)return;if(e<a.STABILITY_THRESHOLD_MS?this.rapidDisconnectCount++:(this.rapidDisconnectCount=0,this.reconnectDelay=1e3),this.rapidDisconnectCount>=a.MAX_RAPID_FAILURES){x.error("Max rapid disconnects reached \u2014 stopping reconnection",{maxFailures:a.MAX_RAPID_FAILURES});return}let t=this.reconnectDelay*(.75+Math.random()*.5),r=Math.round(t);this.rapidDisconnectCount<=1?x.info("Disconnected, reconnecting",{delay:`${r}ms`,rapidDisconnects:this.rapidDisconnectCount}):this.rapidDisconnectCount%5===0&&x.warn("Rapid disconnect",{count:this.rapidDisconnectCount,delay:`${r}ms`}),setTimeout(async()=>{try{let s=await this.connect();this.rapidDisconnectCount>1?x.info("Reconnected",{code:s,attempts:this.rapidDisconnectCount}):x.info("Reconnected",{code:s})}catch(s){x.error("Reconnection failed",{error:s?.message})}},r),this.reconnectDelay=Math.min(this.reconnectDelay*2,this.maxReconnectDelay)}};function Gs(){return process.env.PORT?parseInt(process.env.PORT):process.env.ELECTRON_RUN_AS_NODE?process.platform==="win32"?"\\\\.\\pipe\\impactus-swarm":"/tmp/impactus-swarm.sock":7773}var $="\x1B[",S=`${$}0m`,kt=`${$}1m`,A=`${$}2m`,Ks=`${$}31m`,fe=`${$}32m`,ir=`${$}33m`,V=`${$}36m`,It=`${$}37m`,vp=`${$}41m`,Ai="\x1B[?25l",Ci="\x1B[?25h",Li=`${$}2J${$}H`,B={tl:"\u2554",tr:"\u2557",bl:"\u255A",br:"\u255D",h:"\u2550",v:"\u2551",ml:"\u2560",mr:"\u2563",dash:"\u2500"};function te(a,e,t="left"){let r=Re(a),s=Math.max(0,e-r.length);return t==="right"?" ".repeat(s)+a:a+" ".repeat(s)}function Re(a){return a.replace(/\x1b\[[0-9;]*m/g,"")}function or(a,e){return a.length>e?a.slice(0,e-1)+"\u2026":a}function Ys(a){let e=Math.floor(a/1e3),t=Math.floor(e/3600),r=Math.floor(e%3600/60),s=e%60;return t>0?`${t}h ${r}m`:`${r}m ${s}s`}function Mi(a){return a<1024*1024?`${(a/1024).toFixed(0)} KB`:`${(a/(1024*1024)).toFixed(1)} MB`}function Oi(){let a=new Date;return String(a.getHours()).padStart(2,"0")+":"+String(a.getMinutes()).padStart(2,"0")+":"+String(a.getSeconds()).padStart(2,"0")}var Ni=15,Rt=class{db;getClientCount;services=null;interval=null;startTime=Date.now();logBuffer=[];originalConsoleLog=null;originalConsoleError=null;originalConsoleWarn=null;resizeHandler=null;disabled;constructor(e,t){this.db=e,this.getClientCount=t,this.disabled=!process.stdout.isTTY||process.env.IMPACTUS_DASHBOARD==="0"}setServices(e){this.services=e}interceptLogs(){if(this.disabled)return;this.originalConsoleLog=console.log,this.originalConsoleError=console.error,this.originalConsoleWarn=console.warn;let e=t=>(...r)=>{let s=r.map(n=>typeof n=="string"?n:JSON.stringify(n)).join(" ");this.pushLog(s,t)};console.log=e("log"),console.error=e("error"),console.warn=e("warn")}pushLog(e,t){this.logBuffer.push({time:Oi(),message:e,level:t}),this.logBuffer.length>Ni&&this.logBuffer.shift()}start(e=3e3){this.disabled||(process.stdout.write(Ai),this.render(),this.interval=setInterval(()=>this.render(),e),this.resizeHandler=()=>this.render(),process.on("SIGWINCH",this.resizeHandler))}stop(){this.interval&&(clearInterval(this.interval),this.interval=null),this.resizeHandler&&(process.removeListener("SIGWINCH",this.resizeHandler),this.resizeHandler=null),this.originalConsoleLog&&(console.log=this.originalConsoleLog,this.originalConsoleLog=null),this.originalConsoleError&&(console.error=this.originalConsoleError,this.originalConsoleError=null),this.originalConsoleWarn&&(console.warn=this.originalConsoleWarn,this.originalConsoleWarn=null),process.stdout.write(Ci)}render(){try{let e=Math.max(process.stdout.columns||80,60),t=e-2,r=[];r.push(this.boxTop(e)),r.push(this.boxLine(this.renderHeader(t),e)),r.push(this.boxSep(e));let s=this.renderSessions(t);for(let c of s)r.push(this.boxLine(c,e));r.push(this.boxSep(e));let n=this.renderStatus(t);for(let c of n)r.push(this.boxLine(c,e));r.push(this.boxSep(e)),r.push(this.boxLine(`${V}${kt} LOGS${S}`,e)),r.push(this.boxLine("",e));let i=this.renderLogs(t);for(let c of i)r.push(this.boxLine(c,e));r.push(this.boxBottom(e));let o=Li+r.join(`
614
+ `),n=a.prepare("INSERT OR IGNORE INTO area_state (areaId) VALUES (?)"),i=a.prepare("UPDATE terminal_configs SET areaId = ? WHERE workspaceId = ? AND (areaId IS NULL OR areaId = '')"),o=a.prepare("UPDATE saved_layouts SET areaId = ? WHERE workspaceId = ? AND (areaId IS NULL OR areaId = '')"),c=a.prepare("UPDATE swarms SET areaId = ? WHERE workspaceId = ? AND (areaId IS NULL OR areaId = '')");for(let l of t){let d=Si();s.run(d,l.id,"Principal",l.color,l.defaultCommand,l.terminalCount,l.layout,r,r),n.run(d),i.run(d,l.id),o.run(d,l.id),c.run(d,l.id)}}import ae from"ws";var Xs={debug:0,info:1,warn:2,error:3},bi=process.env.LOG_LEVEL?.toLowerCase()??"info";function ki(a){return!a||Object.keys(a).length===0?"":` | ${Object.entries(a).map(([t,r])=>`${t}=${r}`).join(" ")}`}var ar=class{constructor(e){this.module=e}log(e,t,r){if(Xs[e]<Xs[bi])return;let s=new Date().toISOString(),n=e.toUpperCase().padEnd(5),i=`[${s}] [${n}] [${this.module}] ${t}${ki(r)}`;switch(e){case"error":console.error(i);break;case"warn":console.warn(i);break;default:console.log(i);break}}debug(e,t){this.log("debug",e,t)}info(e,t){this.log("info",e,t)}warn(e,t){this.log("warn",e,t)}error(e,t){this.log("error",e,t)}};function js(a){return new ar(a)}var x=js("relay"),Ii=15e3,Ri=15e3,Ai=480*60*1e3,bt=class a{ws=null;_code=null;relayUrl;allowedIps;reconnectDelay=1e3;maxReconnectDelay=3e4;shouldReconnect=!0;pingTimer=null;pongTimer=null;sessionTimer=null;connectedAt=null;lastCode=null;reconnectToken=null;lastStableConnectTime=0;rapidDisconnectCount=0;static STABILITY_THRESHOLD_MS=3e4;static MAX_RAPID_FAILURES=10;static REGISTRATION_TIMEOUT_MS=15e3;onMessage;onCodeChange;constructor(e,t=[]){this.relayUrl=e,this.allowedIps=t}get code(){return this._code}get connected(){return this.ws?.readyState===ae.OPEN}getStatus(){return{code:this._code,connected:this.connected,connectedAt:this.connectedAt,relayUrl:this.relayUrl}}connect(){return new Promise((e,t)=>{let r=`${this.relayUrl.replace(/^http/,"ws")}/ws/server`;this.ws=new ae(r);let s=!1,n=null,i=()=>{n&&(clearTimeout(n),n=null)};n=setTimeout(()=>{if(!s){s=!0,i(),x.error("Registration timeout \u2014 no response from relay server");try{this.ws?.terminate()}catch{}t(new Error("Registration timeout"))}},a.REGISTRATION_TIMEOUT_MS),this.ws.on("open",()=>{this.lastStableConnectTime=Date.now(),this.connectedAt=new Date().toISOString(),x.info("WebSocket opened",{attemptingReclaim:!!(this.lastCode&&this.reconnectToken),lastCode:this.lastCode}),this.lastCode&&this.reconnectToken?this.ws.send(JSON.stringify({type:"reconnect",code:this.lastCode,reconnect_token:this.reconnectToken,allowed_ips:this.allowedIps})):this.ws.send(JSON.stringify({type:"register",allowed_ips:this.allowedIps})),this.startPing(),this.startSessionTimer()}),this.ws.on("message",o=>{let c=o.toString();try{let l=JSON.parse(c);if(l.type==="registered"&&l.code){i(),this._code=l.code,this.lastCode=l.code,l.reconnect_token&&(this.reconnectToken=l.reconnect_token),x.info("Registered with relay",{code:l.code,reclaimed:!!l.reclaimed}),s||(s=!0,e(l.code)),this.onCodeChange?.(l.code);return}if(l.type==="pong"){this.pongTimer&&(clearTimeout(this.pongTimer),this.pongTimer=null);return}if(l.type==="ping"){try{this.ws.send(JSON.stringify({type:"pong"}))}catch{}return}}catch{}if(this.onMessage&&this.ws){let l=this.createVirtualWs();this.onMessage(c,l)}}),this.ws.on("pong",()=>{this.pongTimer&&(clearTimeout(this.pongTimer),this.pongTimer=null)}),this.ws.on("close",(o,c)=>{i(),x.warn("Connection closed",{closeCode:o,reason:c.toString()||"none",connectionDuration:`${Date.now()-this.lastStableConnectTime}ms`,lastCode:this.lastCode}),s||(s=!0,t(new Error("Connection closed before registration"))),this.handleDisconnect()}),this.ws.on("error",o=>{x.error("Connection error",{error:o.message})})})}async reconnect(){if(this.stopPing(),this.stopSessionTimer(),this.ws){this.ws.removeAllListeners();try{this.ws.close()}catch{}this.ws=null}return this._code=null,this.lastCode=null,this.reconnectToken=null,this.rapidDisconnectCount=0,this.reconnectDelay=1e3,this.connect()}createVirtualWs(){let e=this;return{readyState:ae.OPEN,send(t){e.ws?.readyState===ae.OPEN&&e.ws.send(t)}}}send(e){this.ws?.readyState===ae.OPEN&&this.ws.send(e)}close(){this.shouldReconnect=!1,this.stopPing(),this.stopSessionTimer(),this.ws?.close()}startPing(){this.stopPing(),this.pingTimer=setInterval(()=>{if(this.ws?.readyState===ae.OPEN){try{this.ws.send(JSON.stringify({type:"ping"}))}catch{}try{this.ws.ping()}catch{}this.pongTimer&&clearTimeout(this.pongTimer),this.pongTimer=setTimeout(()=>{this.ws?.readyState===ae.OPEN&&(x.warn("Pong timeout \u2014 forcing reconnect"),this.ws.terminate()),this.pongTimer=null},Ri)}},Ii)}stopPing(){this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=null),this.pongTimer&&(clearTimeout(this.pongTimer),this.pongTimer=null)}startSessionTimer(){this.stopSessionTimer(),this.sessionTimer=setTimeout(()=>{x.info("Session expired (8h) \u2014 reconnecting"),this.reconnect().then(e=>x.info("Session refreshed with new code",{code:e})).catch(()=>x.error("Session refresh failed"))},Ai)}stopSessionTimer(){this.sessionTimer&&(clearTimeout(this.sessionTimer),this.sessionTimer=null)}handleDisconnect(){let e=this.lastStableConnectTime>0?Date.now()-this.lastStableConnectTime:0;if(this._code=null,this.connectedAt=null,this.stopPing(),this.stopSessionTimer(),!this.shouldReconnect)return;if(e<a.STABILITY_THRESHOLD_MS?this.rapidDisconnectCount++:(this.rapidDisconnectCount=0,this.reconnectDelay=1e3),this.rapidDisconnectCount>=a.MAX_RAPID_FAILURES){x.error("Max rapid disconnects reached \u2014 stopping reconnection",{maxFailures:a.MAX_RAPID_FAILURES});return}let t=this.reconnectDelay*(.75+Math.random()*.5),r=Math.round(t);this.rapidDisconnectCount<=1?x.info("Disconnected, reconnecting",{delay:`${r}ms`,rapidDisconnects:this.rapidDisconnectCount}):this.rapidDisconnectCount%5===0&&x.warn("Rapid disconnect",{count:this.rapidDisconnectCount,delay:`${r}ms`}),setTimeout(async()=>{try{let s=await this.connect();this.rapidDisconnectCount>1?x.info("Reconnected",{code:s,attempts:this.rapidDisconnectCount}):x.info("Reconnected",{code:s})}catch(s){x.error("Reconnection failed",{error:s?.message})}},r),this.reconnectDelay=Math.min(this.reconnectDelay*2,this.maxReconnectDelay)}};function Gs(){return process.env.PORT?parseInt(process.env.PORT):process.env.ELECTRON_RUN_AS_NODE?process.platform==="win32"?"\\\\.\\pipe\\impactus-swarm":"/tmp/impactus-swarm.sock":7773}var $="\x1B[",S=`${$}0m`,kt=`${$}1m`,A=`${$}2m`,Ks=`${$}31m`,fe=`${$}32m`,ir=`${$}33m`,V=`${$}36m`,It=`${$}37m`,bp=`${$}41m`,Ci="\x1B[?25l",Li="\x1B[?25h",Mi=`${$}2J${$}H`,B={tl:"\u2554",tr:"\u2557",bl:"\u255A",br:"\u255D",h:"\u2550",v:"\u2551",ml:"\u2560",mr:"\u2563",dash:"\u2500"};function te(a,e,t="left"){let r=Re(a),s=Math.max(0,e-r.length);return t==="right"?" ".repeat(s)+a:a+" ".repeat(s)}function Re(a){return a.replace(/\x1b\[[0-9;]*m/g,"")}function or(a,e){return a.length>e?a.slice(0,e-1)+"\u2026":a}function Ys(a){let e=Math.floor(a/1e3),t=Math.floor(e/3600),r=Math.floor(e%3600/60),s=e%60;return t>0?`${t}h ${r}m`:`${r}m ${s}s`}function Oi(a){return a<1024*1024?`${(a/1024).toFixed(0)} KB`:`${(a/(1024*1024)).toFixed(1)} MB`}function Ni(){let a=new Date;return String(a.getHours()).padStart(2,"0")+":"+String(a.getMinutes()).padStart(2,"0")+":"+String(a.getSeconds()).padStart(2,"0")}var Di=15,Rt=class{db;getClientCount;services=null;interval=null;startTime=Date.now();logBuffer=[];originalConsoleLog=null;originalConsoleError=null;originalConsoleWarn=null;resizeHandler=null;disabled;constructor(e,t){this.db=e,this.getClientCount=t,this.disabled=!process.stdout.isTTY||process.env.IMPACTUS_DASHBOARD==="0"}setServices(e){this.services=e}interceptLogs(){if(this.disabled)return;this.originalConsoleLog=console.log,this.originalConsoleError=console.error,this.originalConsoleWarn=console.warn;let e=t=>(...r)=>{let s=r.map(n=>typeof n=="string"?n:JSON.stringify(n)).join(" ");this.pushLog(s,t)};console.log=e("log"),console.error=e("error"),console.warn=e("warn")}pushLog(e,t){this.logBuffer.push({time:Ni(),message:e,level:t}),this.logBuffer.length>Di&&this.logBuffer.shift()}start(e=3e3){this.disabled||(process.stdout.write(Ci),this.render(),this.interval=setInterval(()=>this.render(),e),this.resizeHandler=()=>this.render(),process.on("SIGWINCH",this.resizeHandler))}stop(){this.interval&&(clearInterval(this.interval),this.interval=null),this.resizeHandler&&(process.removeListener("SIGWINCH",this.resizeHandler),this.resizeHandler=null),this.originalConsoleLog&&(console.log=this.originalConsoleLog,this.originalConsoleLog=null),this.originalConsoleError&&(console.error=this.originalConsoleError,this.originalConsoleError=null),this.originalConsoleWarn&&(console.warn=this.originalConsoleWarn,this.originalConsoleWarn=null),process.stdout.write(Li)}render(){try{let e=Math.max(process.stdout.columns||80,60),t=e-2,r=[];r.push(this.boxTop(e)),r.push(this.boxLine(this.renderHeader(t),e)),r.push(this.boxSep(e));let s=this.renderSessions(t);for(let c of s)r.push(this.boxLine(c,e));r.push(this.boxSep(e));let n=this.renderStatus(t);for(let c of n)r.push(this.boxLine(c,e));r.push(this.boxSep(e)),r.push(this.boxLine(`${V}${kt} LOGS${S}`,e)),r.push(this.boxLine("",e));let i=this.renderLogs(t);for(let c of i)r.push(this.boxLine(c,e));r.push(this.boxBottom(e));let o=Mi+r.join(`
615
615
  `)+`
616
- `;process.stdout.write(o)}catch{}}renderHeader(e){let t=Ys(Date.now()-this.startTime),r=Mi(process.memoryUsage().rss),s=`${V}${kt} IMPACTUS SWARM${S}`,n=`${A}uptime ${It}${t}${S} ${A}rss ${It}${r}${S}`,i=Re(s).length,o=Re(n).length,c=Math.max(1,e-i-o);return s+" ".repeat(c)+n}renderSessions(e){let t=[];t.push(`${V}${kt} SESSIONS${S}`),t.push("");let r=[];try{let c=R.listSessions();for(let l of c){let d=R.getTerminalId(l);if(!d)continue;let u=d.slice(0,8),p=R.getCreatedAt(l),m=p?Ys(Date.now()-p):"?",h="-";try{let g=this.db.prepare("SELECT w.name FROM terminal_configs tc JOIN workspaces w ON w.id = tc.workspaceId WHERE tc.id = ?").get(d);g&&(h=g.name)}catch{}let f=`${A}idle${S}`;if(this.services){let g=this.services.terminalManager.getProcessInfo(d);g?.foregroundProcess&&(f=`${fe}${g.foregroundProcess}${S}`)}r.push({id:u,workspace:or(h,20),uptime:m,process:f})}}catch{}if(r.length===0)return t.push(` ${A}No active sessions${S}`),t;let s=10,n=22,i=12,o=Math.max(10,e-s-n-i-6);t.push(` ${A}${te("ID",s)}${te("WORKSPACE",n)}${te("UPTIME",i)}${te("PROCESS",o)}${S}`);for(let c of r)t.push(` ${It}${te(c.id,s)}${S}${te(c.workspace,n)}${A}${te(c.uptime,i)}${S}${te(c.process,o)}`);return t}renderStatus(e){let t=[];t.push(`${V}${kt} STATUS${S}`),t.push("");let r=[],s=this.getClientCount();r.push(`${A}clients${S} ${s>0?`${fe}${s}${S}`:`${A}0${S}`}`);let n=this.services?.terminalManager.size??0;r.push(`${A}terminals${S} ${It}${n}${S}`);let i=this.services?.relayClient;if(i){let p=i.connected,m=i.code;p&&m?r.push(`${A}relay${S} ${fe}${m}${S}`):p?r.push(`${A}relay${S} ${fe}connected${S}`):r.push(`${A}relay${S} ${Ks}disconnected${S}`)}try{let p=this.db.prepare("SELECT id, name, status FROM swarms WHERE status IN ('active', 'draft')").all();if(p.length>0){let m=p.map(h=>`${h.status==="active"?fe:ir}${or(h.name,16)}${S}`);r.push(`${A}swarms${S} ${m.join(", ")}`)}else r.push(`${A}swarms${S} ${A}none${S}`)}catch{r.push(`${A}swarms${S} ${A}?${S}`)}let o=this.services?.healthCheckService.getLastResult();if(o){let p=o.providers.map(m=>m.state==="connected"?`${fe}${m.cli}${S}`:m.installed?`${ir}${m.cli}${S}`:`${A}${m.cli}${S}`);r.push(`${A}health${S} ${p.join(" ")}`)}let c=" ",l=2,d=` ${A}${B.dash}${S} `,u=5;for(let p=0;p<r.length;p++){let m=Re(r[p]).length,h=p===0?m:u+m;l+h>e&&l>2?(t.push(c),c=" "+r[p],l=2+m):(p>0&&(c+=d,l+=u),c+=r[p],l+=m)}return l>2&&t.push(c),t}renderLogs(e){if(this.logBuffer.length===0)return[` ${A}No log output yet${S}`];let t=e-14;return this.logBuffer.map(r=>{let s=A;r.level==="error"?s=Ks:r.level==="warn"&&(s=ir);let n=or(r.message,t);return` ${A}[${r.time}]${S} ${s}${n}${S}`})}boxTop(e){return`${V}${B.tl}${B.h.repeat(e-2)}${B.tr}${S}`}boxBottom(e){return`${V}${B.bl}${B.h.repeat(e-2)}${B.br}${S}`}boxSep(e){return`${V}${B.ml}${B.h.repeat(e-2)}${B.mr}${S}`}boxLine(e,t){let r=Re(e).length,s=Math.max(0,t-2-r);return`${V}${B.v}${S}${e}${" ".repeat(s)}${V}${B.v}${S}`}};var xi={".html":"text/html",".js":"application/javascript",".css":"text/css",".json":"application/json",".png":"image/png",".svg":"image/svg+xml",".ico":"image/x-icon"},Ae=Gs(),Js=process.env.IMPACTUS_WEB_DIR||cr(import.meta.dirname,"../../web/dist"),lr=Di((a,e)=>{let t=a.url||"/",r=cr(Js,t==="/"?"index.html":t);if(zs(r)||(r=cr(Js,"index.html")),!zs(r)){e.writeHead(404),e.end("Not found");return}if(r.endsWith("index.html")){try{let i=Vs(r,"utf-8"),o=JSON.stringify({relayUrl:process.env.RELAY_URL||null}),c=i.replace("</head>",`<script>window.__IMPACTUS_CONFIG__=${o}</script>
617
- </head>`);e.writeHead(200,{"Content-Type":"text/html"}),e.end(c)}catch{e.writeHead(500),e.end("Internal server error")}return}let s=Pi(r),n=xi[s]||"application/octet-stream";try{let i=Vs(r);e.writeHead(200,{"Content-Type":n}),e.end(i)}catch{e.writeHead(500),e.end("Internal server error")}}),ur=qs(),we=new Rt(ur,()=>0);we.interceptLogs();var{terminalManager:_i,broadcast:Ui,externalSenders:Fi,services:dr,routes:Bi,getClientCount:Wi}=$s(lr,ur);we.setServices(dr);we.getClientCount=Wi;var Qs=process.env.RELAY_URL,$i=process.env.RELAY_ALLOWED_IPS?process.env.RELAY_ALLOWED_IPS.split(",").map(a=>a.trim()):[],ie=null;Qs&&(ie=new bt(Qs,$i),dr.relayClient=ie,Fi.push(a=>ie.send(a)),ie.onMessage=(a,e)=>{let t;try{t=JSON.parse(a)}catch{return}sr(t,e,dr,Bi)},ie.onCodeChange=a=>{Ui("relay.codeChange",{code:a})},ie.connect().then(a=>console.log(`[relay] Code: ${a}`)).catch(a=>console.error("[relay] Failed to connect:",a)));function Zs(){we.stop(),ie?.close(),_i.detachAll(),ur.close(),process.exit(0)}process.on("SIGINT",Zs);process.on("SIGTERM",Zs);var Hi=process.argv.includes("--open");typeof Ae=="number"?lr.listen(Ae,async()=>{let a=`http://localhost:${Ae}`;console.log(`Impactus Swarm server running on ${a}`),we.start(),Hi&&(await import("open")).default(a)}):lr.listen(Ae,()=>{console.log(`Impactus Swarm server running on ${Ae}`),we.start()});
616
+ `;process.stdout.write(o)}catch{}}renderHeader(e){let t=Ys(Date.now()-this.startTime),r=Oi(process.memoryUsage().rss),s=`${V}${kt} IMPACTUS SWARM${S}`,n=`${A}uptime ${It}${t}${S} ${A}rss ${It}${r}${S}`,i=Re(s).length,o=Re(n).length,c=Math.max(1,e-i-o);return s+" ".repeat(c)+n}renderSessions(e){let t=[];t.push(`${V}${kt} SESSIONS${S}`),t.push("");let r=[];try{let c=R.listSessions();for(let l of c){let d=R.getTerminalId(l);if(!d)continue;let u=d.slice(0,8),p=R.getCreatedAt(l),m=p?Ys(Date.now()-p):"?",h="-";try{let g=this.db.prepare("SELECT w.name FROM terminal_configs tc JOIN workspaces w ON w.id = tc.workspaceId WHERE tc.id = ?").get(d);g&&(h=g.name)}catch{}let f=`${A}idle${S}`;if(this.services){let g=this.services.terminalManager.getProcessInfo(d);g?.foregroundProcess&&(f=`${fe}${g.foregroundProcess}${S}`)}r.push({id:u,workspace:or(h,20),uptime:m,process:f})}}catch{}if(r.length===0)return t.push(` ${A}No active sessions${S}`),t;let s=10,n=22,i=12,o=Math.max(10,e-s-n-i-6);t.push(` ${A}${te("ID",s)}${te("WORKSPACE",n)}${te("UPTIME",i)}${te("PROCESS",o)}${S}`);for(let c of r)t.push(` ${It}${te(c.id,s)}${S}${te(c.workspace,n)}${A}${te(c.uptime,i)}${S}${te(c.process,o)}`);return t}renderStatus(e){let t=[];t.push(`${V}${kt} STATUS${S}`),t.push("");let r=[],s=this.getClientCount();r.push(`${A}clients${S} ${s>0?`${fe}${s}${S}`:`${A}0${S}`}`);let n=this.services?.terminalManager.size??0;r.push(`${A}terminals${S} ${It}${n}${S}`);let i=this.services?.relayClient;if(i){let p=i.connected,m=i.code;p&&m?r.push(`${A}relay${S} ${fe}${m}${S}`):p?r.push(`${A}relay${S} ${fe}connected${S}`):r.push(`${A}relay${S} ${Ks}disconnected${S}`)}try{let p=this.db.prepare("SELECT id, name, status FROM swarms WHERE status IN ('active', 'draft')").all();if(p.length>0){let m=p.map(h=>`${h.status==="active"?fe:ir}${or(h.name,16)}${S}`);r.push(`${A}swarms${S} ${m.join(", ")}`)}else r.push(`${A}swarms${S} ${A}none${S}`)}catch{r.push(`${A}swarms${S} ${A}?${S}`)}let o=this.services?.healthCheckService.getLastResult();if(o){let p=o.providers.map(m=>m.state==="connected"?`${fe}${m.cli}${S}`:m.installed?`${ir}${m.cli}${S}`:`${A}${m.cli}${S}`);r.push(`${A}health${S} ${p.join(" ")}`)}let c=" ",l=2,d=` ${A}${B.dash}${S} `,u=5;for(let p=0;p<r.length;p++){let m=Re(r[p]).length,h=p===0?m:u+m;l+h>e&&l>2?(t.push(c),c=" "+r[p],l=2+m):(p>0&&(c+=d,l+=u),c+=r[p],l+=m)}return l>2&&t.push(c),t}renderLogs(e){if(this.logBuffer.length===0)return[` ${A}No log output yet${S}`];let t=e-14;return this.logBuffer.map(r=>{let s=A;r.level==="error"?s=Ks:r.level==="warn"&&(s=ir);let n=or(r.message,t);return` ${A}[${r.time}]${S} ${s}${n}${S}`})}boxTop(e){return`${V}${B.tl}${B.h.repeat(e-2)}${B.tr}${S}`}boxBottom(e){return`${V}${B.bl}${B.h.repeat(e-2)}${B.br}${S}`}boxSep(e){return`${V}${B.ml}${B.h.repeat(e-2)}${B.mr}${S}`}boxLine(e,t){let r=Re(e).length,s=Math.max(0,t-2-r);return`${V}${B.v}${S}${e}${" ".repeat(s)}${V}${B.v}${S}`}};var _i={".html":"text/html",".js":"application/javascript",".css":"text/css",".json":"application/json",".png":"image/png",".svg":"image/svg+xml",".ico":"image/x-icon"},Ae=Gs(),Js=process.env.IMPACTUS_WEB_DIR||cr(import.meta.dirname,"../../web/dist"),lr=Pi((a,e)=>{let t=a.url||"/",r=cr(Js,t==="/"?"index.html":t);if(zs(r)||(r=cr(Js,"index.html")),!zs(r)){e.writeHead(404),e.end("Not found");return}if(r.endsWith("index.html")){try{let i=Vs(r,"utf-8"),o=JSON.stringify({relayUrl:process.env.RELAY_URL||null}),c=i.replace("</head>",`<script>window.__IMPACTUS_CONFIG__=${o}</script>
617
+ </head>`);e.writeHead(200,{"Content-Type":"text/html"}),e.end(c)}catch{e.writeHead(500),e.end("Internal server error")}return}let s=xi(r),n=_i[s]||"application/octet-stream";try{let i=Vs(r);e.writeHead(200,{"Content-Type":n}),e.end(i)}catch{e.writeHead(500),e.end("Internal server error")}}),ur=qs(),we=new Rt(ur,()=>0);we.interceptLogs();var{terminalManager:Ui,broadcast:Fi,externalSenders:Bi,services:dr,routes:Wi,getClientCount:$i}=$s(lr,ur);we.setServices(dr);we.getClientCount=$i;var Qs=process.env.RELAY_URL,Hi=process.env.RELAY_ALLOWED_IPS?process.env.RELAY_ALLOWED_IPS.split(",").map(a=>a.trim()):[],ie=null;Qs&&(ie=new bt(Qs,Hi),dr.relayClient=ie,Bi.push(a=>ie.send(a)),ie.onMessage=(a,e)=>{let t;try{t=JSON.parse(a)}catch{return}sr(t,e,dr,Wi)},ie.onCodeChange=a=>{Fi("relay.codeChange",{code:a})},ie.connect().then(a=>console.log(`[relay] Code: ${a}`)).catch(a=>console.error("[relay] Failed to connect:",a)));function Zs(){we.stop(),ie?.close(),Ui.detachAll(),ur.close(),process.exit(0)}process.on("SIGINT",Zs);process.on("SIGTERM",Zs);var qi=process.argv.includes("--open");typeof Ae=="number"?lr.listen(Ae,async()=>{let a=`http://localhost:${Ae}`;console.log(`Impactus Swarm server running on ${a}`),we.start(),qi&&(await import("open")).default(a)}):lr.listen(Ae,()=>{console.log(`Impactus Swarm server running on ${Ae}`),we.start()});