impactus-swarm 0.0.20 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server/main.js +52 -52
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 ho}from"node:http";import{readFileSync as fn,existsSync as wn}from"node:fs";import{join as yr,extname as fo}from"node:path";import{WebSocketServer as ji,WebSocket as Ki}from"ws";import{homedir as Jr}from"node:os";import{execSync as Be}from"node:child_process";import{readlinkSync as Ea}from"node:fs";import{join as Sa}from"node:path";import{createRequire as Ln}from"node:module";import{homedir as Mn}from"node:os";import{chmod as An,mkdir as $t,writeFile as Bt}from"node:fs/promises";import{join as pe}from"node:path";import{tmpdir as Cn}from"node:os";var Ie=class a{static getInitScript(e){switch(e){case"zsh":return`
2
+ import{createServer as fo}from"node:http";import{readFileSync as wn,existsSync as Tn}from"node:fs";import{join as vr,extname as wo}from"node:path";import{WebSocketServer as Ki,WebSocket as Gi}from"ws";import{homedir as Qr}from"node:os";import{execSync as Be}from"node:child_process";import{readlinkSync as Sa}from"node:fs";import{join as ya}from"node:path";import{createRequire as Mn}from"node:module";import{homedir as On}from"node:os";import{chmod as Cn,mkdir as $t,writeFile as Bt}from"node:fs/promises";import{join as pe}from"node:path";import{tmpdir as Ln}from"node:os";var Ie=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=$?
@@ -30,38 +30,38 @@ fi
30
30
  # Fish 3.1.2+ has native OSC 133 support
31
31
  # Just set TERM_PROGRAM for detection
32
32
  set -gx TERM_PROGRAM impactus-swarm
33
- `.trim();default:return""}}static detectShell(e){return e.includes("zsh")?"zsh":e.includes("bash")?"bash":e.includes("fish")?"fish":"unknown"}static getEnvVars(e){return{TERM_PROGRAM:"impactus-swarm",__IMPACTUS_SHELL_INTEGRATION:"1"}}static async createInjectionEnv(e){if(e==="unknown"||e==="fish")return a.getEnvVars(e);try{let t=pe(Cn(),"impactus-shell-integration");if(await $t(t,{recursive:!0}),process.platform!=="win32"&&await An(t,448),e==="zsh"){let r=pe(t,"zsh");await $t(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(`
33
+ `.trim();default:return""}}static detectShell(e){return e.includes("zsh")?"zsh":e.includes("bash")?"bash":e.includes("fish")?"fish":"unknown"}static getEnvVars(e){return{TERM_PROGRAM:"impactus-swarm",__IMPACTUS_SHELL_INTEGRATION:"1"}}static async createInjectionEnv(e){if(e==="unknown"||e==="fish")return a.getEnvVars(e);try{let t=pe(Ln(),"impactus-shell-integration");if(await $t(t,{recursive:!0}),process.platform!=="win32"&&await Cn(t,448),e==="zsh"){let r=pe(t,"zsh");await $t(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 Bt(pe(r,".zshrc"),s,"utf-8");let n=["# Source original zshenv",'if [[ -f "$HOME/.zshenv" ]]; then',' ZDOTDIR="$HOME" source "$HOME/.zshenv"',"fi"].join(`
35
35
  `);return await Bt(pe(r,".zshenv"),n,"utf-8"),{...a.getEnvVars("zsh"),ZDOTDIR:r}}if(e==="bash"){let r=pe(t,"bash");await $t(r,{recursive:!0});let s=["# IMPACTUS Swarm Shell Integration","# Source original bashrc",'if [[ -f "$HOME/.bashrc" ]]; then',' source "$HOME/.bashrc"',"fi","",a.getInitScript("bash")].join(`
36
- `),n=pe(r,".bashrc_impactus");return await Bt(n,s,"utf-8"),{...a.getEnvVars("bash"),BASH_ENV:n}}}catch{}return a.getEnvVars(e)}};var On=Ln(import.meta.url),Or=On("node-pty");function Nr(){return process.platform==="win32"?process.env.COMSPEC||"cmd.exe":process.env.SHELL||"/bin/zsh"}async function Wt(){let a=Nr(),e=Ie.detectShell(a);return Ie.createInjectionEnv(e)}async function qt(a){let e=Nr(),t=[],r=await Wt(),{PORT:s,IMPACTUS_WEB_DIR:n,RELAY_URL:i,RELAY_ALLOWED_IPS:o,CLAUDECODE:c,...l}=process.env;return Or.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 Ht(a,e,t){return Or.spawn("tmux",a,{name:"xterm-256color",cols:e,rows:t,cwd:Mn()})}import{execFileSync as O}from"node:child_process";import{existsSync as Nn,writeFileSync as Dn,mkdirSync as Pn}from"node:fs";import{join as Dr}from"node:path";import{homedir as xn}from"node:os";var N="impactus",xe="impactus-",b=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=Dr(xn(),".impactus-swarm");Nn(e)||Pn(e,{recursive:!0});let t=Dr(e,"tmux.conf");return Dn(t,["# IMPACTUS Swarm tmux config \u2014 auto-generated, do not edit","set -g status off","set -g history-limit 50000",'set -g default-terminal "xterm-256color"',"set -g escape-time 10","set -g focus-events on","set -g mouse off","# Suppress DA queries \u2014 tell tmux the outer terminal capabilities","# Disable smcup/rmcup so tmux does NOT enter alternate screen in","# xterm.js \u2014 this allows xterm.js scrollback to accumulate normally.","# TUI apps inside tmux still use tmux's internal alternate screen.",'set -as terminal-overrides ",xterm*:Tc:smcup@:rmcup@"'].join(`
36
+ `),n=pe(r,".bashrc_impactus");return await Bt(n,s,"utf-8"),{...a.getEnvVars("bash"),BASH_ENV:n}}}catch{}return a.getEnvVars(e)}};var Nn=Mn(import.meta.url),Nr=Nn("node-pty");function Dr(){return process.platform==="win32"?process.env.COMSPEC||"cmd.exe":process.env.SHELL||"/bin/zsh"}async function Wt(){let a=Dr(),e=Ie.detectShell(a);return Ie.createInjectionEnv(e)}async function qt(a){let e=Dr(),t=[],r=await Wt(),{PORT:s,IMPACTUS_WEB_DIR:n,RELAY_URL:i,RELAY_ALLOWED_IPS:o,CLAUDECODE:c,...l}=process.env;return Nr.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 Ht(a,e,t){return Nr.spawn("tmux",a,{name:"xterm-256color",cols:e,rows:t,cwd:On()})}import{execFileSync as O}from"node:child_process";import{existsSync as Dn,writeFileSync as Pn,mkdirSync as xn}from"node:fs";import{join as Pr}from"node:path";import{homedir as _n}from"node:os";var N="impactus",xe="impactus-",b=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=Pr(_n(),".impactus-swarm");Dn(e)||xn(e,{recursive:!0});let t=Pr(e,"tmux.conf");return Pn(t,["# IMPACTUS Swarm tmux config \u2014 auto-generated, do not edit","set -g status off","set -g history-limit 50000",'set -g default-terminal "xterm-256color"',"set -g escape-time 10","set -g focus-events on","set -g mouse off","# Suppress DA queries \u2014 tell tmux the outer terminal capabilities","# Disable smcup/rmcup so tmux does NOT enter alternate screen in","# xterm.js \u2014 this allows xterm.js scrollback to accumulate normally.","# TUI apps inside tmux still use tmux's internal alternate screen.",'set -as terminal-overrides ",xterm*:Tc:smcup@:rmcup@"'].join(`
37
37
  `)+`
38
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 xe+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,h]of Object.entries(n))h!==void 0&&h!==""&&l.push("-e",`${f}=${h}`);if(i)for(let[f,h]of Object.entries(i))h!==void 0&&l.push("-e",`${f}=${h}`);let{PORT:d,IMPACTUS_WEB_DIR:u,RELAY_URL:p,RELAY_ALLOWED_IPS:m,...g}=process.env;O("tmux",l,{stdio:"pipe",env:g});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(xe)):[]}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(xe)?e.slice(xe.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:10485760}).toString().replace(/\n+$/,`
40
40
  `)}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(`
41
- `)[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 getCursorPosition(e){try{let r=O("tmux",["-L",N,"display-message","-t",e,"-p","#{cursor_x} #{cursor_y}"],{stdio:"pipe"}).toString().trim().split(" "),s=parseInt(r[0],10),n=parseInt(r[1],10);if(!isNaN(s)&&!isNaN(n))return{x:s,y:n}}catch{}return null}static getSessionSize(e){try{let r=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 _n}from"node:crypto";var Re=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:_n(),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 Un=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function Ur(a){return a.replace(Un,"")}var Pr=new Set(["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F","\u28FE","\u28FD","\u28FB","\u28BF","\u287F","\u28DF","\u28EF","\u28F7"]),xr=new Set(["\u273B","\u2722","\u26A1","\u25CF","\u25C9","\u25CE","\u25CB","\u25CC","\u23F5"]),Fn=/^[\s|/\\\-.*]+$/,$n=/^[\s─━═╌╍┄┅┈┉╴╶╸╺│┃║├┤┬┴┼╋]+$/,Bn=["\u23F5\u23F5","\u273B ","\u26A1 "];function _r(a){let e=Ur(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=>Pr.has(s)||xr.has(s))||e.length<=10&&Fn.test(e)||$n.test(e))return!0;for(let r of Bn)if(e.startsWith(r))return!0;if(t.length>=1&&t.length<=30){let r=t[0];if(Pr.has(r)||xr.has(r))return!0}return!1}function Fr(a){if(a.length===0)return!1;if(a.includes("\r")&&!a.includes(`
42
- `))return a.split("\r").filter(s=>s.length>0).every(s=>_r(s));let t=a.split(`
43
- `).filter(r=>Ur(r).trim().length>0);return t.length===0?!0:t.every(r=>_r(r))}var Wn=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function $r(a){return a.replace(Wn,"")}var Br=/\/\/|\/\*|^\s*#\s/,Wr=/^[+-][^+-]/,qn=/\?\s*:|:\s*\?|\?\./,Hn=/\w\)\?\s*$|\w\?\s*;?\s*$/,Xn=/\?[a-zA-Z_]+=\S/,jn=/^\s+at\s+/,Kn=/->|=>|::|!=|==/,Gn=/^#{1,6}\s/,qr=/^\s*\d+\s*[|:]\s/,Yn=/\b(?:function|def|fn|func|sub|proc)\s+\w/,Hr=/^(?:\s{4,}|\t)/,Xr=/\b(?:import|require|from|use|include)\b.*['"`]/,Vn=/\([^)]*\)\s*\?\s*$/,zn=/[+\-*/%]=|<<=|>>=/,Jn=/:\s*\w+\?\s*[;,)=]/;function jr(a){let e=$r(a).trim();return!(!e.endsWith("?")||e.length<5||Br.test(e)||Wr.test(e)||qn.test(e)||Hn.test(e)||Xn.test(e)||jn.test(e)||Kn.test(e)||Gn.test(e)||qr.test(e)||Yn.test(e)||Hr.test(e)||Xr.test(e)||Vn.test(e)||zn.test(e)||Jn.test(e))}function Kr(a){let e=$r(a).trim();return Wr.test(e)||qr.test(e)||Hr.test(e)||Br.test(e)||Xr.test(e)}var _e=class{grid;cursorRow=0;cursorCol=0;rows;cols;savedCursor=null;alternateGrid=null;isAlternate=!1;parseState=0;csiParams="";constructor(e=24,t=80){this.rows=e,this.cols=t,this.grid=this.createGrid(e,t)}createGrid(e,t){let r=[];for(let s=0;s<e;s++)r.push(new Array(t).fill(" "));return r}write(e){for(let t=0;t<e.length;t++){let r=e[t],s=e.charCodeAt(t);switch(this.parseState){case 0:this.handleNormal(r,s);break;case 1:this.handleEscStart(r,s);break;case 2:this.handleCsiParam(r,s);break;case 3:s===7?this.parseState=0:s===27&&t+1<e.length&&e.charCodeAt(t+1)===92&&(t++,this.parseState=0);break}}}handleNormal(e,t){if(t===27){this.parseState=1,this.csiParams="";return}if(t===13){this.cursorCol=0;return}if(t===10){this.lineFeed();return}if(t===8){this.cursorCol>0&&this.cursorCol--;return}if(t===9){this.cursorCol=Math.min(this.cols-1,(Math.floor(this.cursorCol/8)+1)*8);return}t<32||(this.cursorRow>=0&&this.cursorRow<this.rows&&this.cursorCol>=0&&this.cursorCol<this.cols&&(this.grid[this.cursorRow][this.cursorCol]=e),this.cursorCol++,this.cursorCol>=this.cols&&(this.cursorCol=0,this.lineFeed()))}handleEscStart(e,t){if(t===91){this.parseState=2,this.csiParams="";return}if(t===93){this.parseState=3;return}if(t===55){this.savedCursor={row:this.cursorRow,col:this.cursorCol},this.parseState=0;return}if(t===56){this.savedCursor&&(this.cursorRow=this.savedCursor.row,this.cursorCol=this.savedCursor.col),this.parseState=0;return}this.parseState=0}handleCsiParam(e,t){if(t>=48&&t<=63){this.csiParams+=e;return}if(t>=32&&t<=47){this.csiParams+=e;return}if(t>=64&&t<=126){this.executeCsi(e,this.csiParams),this.parseState=0;return}this.parseState=0}executeCsi(e,t){let r=t.replace(/^\?/,"").split(";").map(i=>parseInt(i,10)||0),s=t.startsWith("?"),n=r[0]||1;switch(e){case"A":this.cursorRow=Math.max(0,this.cursorRow-n);break;case"B":this.cursorRow=Math.min(this.rows-1,this.cursorRow+n);break;case"C":this.cursorCol=Math.min(this.cols-1,this.cursorCol+n);break;case"D":this.cursorCol=Math.max(0,this.cursorCol-n);break;case"H":case"f":this.cursorRow=Math.min(this.rows-1,Math.max(0,(r[0]||1)-1)),this.cursorCol=Math.min(this.cols-1,Math.max(0,(r[1]||1)-1));break;case"J":this.eraseDisplay(r[0]||0);break;case"K":this.eraseLine(r[0]||0);break;case"m":break;case"s":this.savedCursor={row:this.cursorRow,col:this.cursorCol};break;case"u":this.savedCursor&&(this.cursorRow=this.savedCursor.row,this.cursorCol=this.savedCursor.col);break;case"h":s&&(r[0]===1049||r[0]===47)&&this.enterAlternateScreen();break;case"l":s&&(r[0]===1049||r[0]===47)&&this.leaveAlternateScreen();break;case"r":break;case"G":this.cursorCol=Math.min(this.cols-1,Math.max(0,n-1));break;case"d":this.cursorRow=Math.min(this.rows-1,Math.max(0,n-1));break;case"E":this.cursorRow=Math.min(this.rows-1,this.cursorRow+n),this.cursorCol=0;break;case"F":this.cursorRow=Math.max(0,this.cursorRow-n),this.cursorCol=0;break;default:break}}lineFeed(){this.cursorRow<this.rows-1?this.cursorRow++:(this.grid.shift(),this.grid.push(new Array(this.cols).fill(" ")))}eraseDisplay(e){switch(e){case 0:this.eraseLine(0);for(let t=this.cursorRow+1;t<this.rows;t++)this.grid[t].fill(" ");break;case 1:this.eraseLine(1);for(let t=0;t<this.cursorRow;t++)this.grid[t].fill(" ");break;case 2:case 3:for(let t=0;t<this.rows;t++)this.grid[t].fill(" ");this.cursorRow=0,this.cursorCol=0;break}}eraseLine(e){if(this.cursorRow<0||this.cursorRow>=this.rows)return;let t=this.grid[this.cursorRow];switch(e){case 0:for(let r=this.cursorCol;r<this.cols;r++)t[r]=" ";break;case 1:for(let r=0;r<=this.cursorCol&&r<this.cols;r++)t[r]=" ";break;case 2:t.fill(" ");break}}enterAlternateScreen(){this.isAlternate||(this.alternateGrid=this.grid,this.grid=this.createGrid(this.rows,this.cols),this.isAlternate=!0,this.savedCursor={row:this.cursorRow,col:this.cursorCol},this.cursorRow=0,this.cursorCol=0)}leaveAlternateScreen(){this.isAlternate&&this.alternateGrid&&(this.grid=this.alternateGrid,this.alternateGrid=null,this.isAlternate=!1,this.savedCursor&&(this.cursorRow=this.savedCursor.row,this.cursorCol=this.savedCursor.col,this.savedCursor=null))}getBottomRows(e){let t=[];for(let r=this.rows-1;r>=0&&t.length<e;r--){let s=this.grid[r].join("").trimEnd();s.length>0&&t.unshift(s)}return t}getScreen(){return this.grid.map(e=>e.join("").trimEnd())}resize(e,t){let r=this.createGrid(e,t),s=Math.min(this.rows,e),n=Math.min(this.cols,t);for(let i=0;i<s;i++)for(let o=0;o<n;o++)r[i][o]=this.grid[i][o];this.grid=r,this.rows=e,this.cols=t,this.cursorRow=Math.min(this.cursorRow,e-1),this.cursorCol=Math.min(this.cursorCol,t-1)}containsInBottom(e,t){return this.getBottomRows(t).join(`
44
- `).includes(e)}};var Ue=class a{constructor(e,t){this.terminalId=e;this.onStateChange=t;this.startedAt=Date.now()}state="idle";lastRealOutputAt=0;idleCheckHandle=null;debouncedIdleHandle=null;startedAt;static IDLE_THRESHOLD_MS=500;static DEBOUNCE_MS=2e3;static STARTUP_GRACE_MS=1e4;inStartupGrace(){return Date.now()-this.startedAt<a.STARTUP_GRACE_MS}onRealOutput(){this.lastRealOutputAt=Date.now(),this.debouncedIdleHandle!==null&&(clearTimeout(this.debouncedIdleHandle),this.debouncedIdleHandle=null),this.state==="idle"&&(this.state="busy",this.inStartupGrace()||this.onStateChange({terminalId:this.terminalId,state:"busy"})),this.idleCheckHandle!==null&&clearTimeout(this.idleCheckHandle),this.idleCheckHandle=setTimeout(()=>this.checkIdle(),a.IDLE_THRESHOLD_MS)}onChromeOutput(){this.state==="busy"&&(this.debouncedIdleHandle!==null&&(clearTimeout(this.debouncedIdleHandle),this.debouncedIdleHandle=null),this.idleCheckHandle!==null&&clearTimeout(this.idleCheckHandle),this.idleCheckHandle=setTimeout(()=>this.checkIdle(),a.IDLE_THRESHOLD_MS))}getState(){return this.state}dispose(){this.idleCheckHandle!==null&&(clearTimeout(this.idleCheckHandle),this.idleCheckHandle=null),this.debouncedIdleHandle!==null&&(clearTimeout(this.debouncedIdleHandle),this.debouncedIdleHandle=null)}checkIdle(){this.idleCheckHandle=null,Date.now()-this.lastRealOutputAt>=a.IDLE_THRESHOLD_MS&&this.state==="busy"&&(this.debouncedIdleHandle=setTimeout(()=>{this.debouncedIdleHandle=null,Date.now()-this.lastRealOutputAt>=a.IDLE_THRESHOLD_MS&&(this.state="idle",this.inStartupGrace()||this.onStateChange({terminalId:this.terminalId,state:"idle"}))},a.DEBOUNCE_MS))}};var Fe=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 Qn=[/(?: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],Zn=/(?:retry.?after|wait|try again in)\s*[:=]?\s*(\d+)\s*(s(?:ec)?|m(?:in)?|h(?:our)?)?/i;function Xt(a){for(let e of Qn)if(e.test(a)){let t=Zn.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 ea=[/(?: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)/],ta=/(?:HTTP\s+)?([45]\d{2})/;function jt(a){for(let e of ea)if(e.test(a)){let t=ta.exec(a);return{type:"api-error",data:{message:a.trim().slice(0,300),statusCode:t?parseInt(t[1],10):void 0}}}return null}var ra=/https?:\/\/(?:github\.com|gitlab\.com|bitbucket\.org)\/[^\s]+\/pull\/(\d+)/gi,sa=/https?:\/\/gitlab\.com\/[^\s]+\/merge_requests\/(\d+)/gi;function Kt(a){let e=[];for(let t of[ra,sa]){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 na=/(\d{1,3}(?:\.\d+)?)\s*%/,aa=/(\d+)\s*\/\s*(\d+)/,ia=/\[([█▓▒░=\->#\s]{4,})\]/;function Gt(a){let e=na.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=aa.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 ia.test(a)?{type:"progress",data:{raw:a.trim().slice(0,100)}}:null}var oa=/(\d+)\s+(?:tool|sub.?(?:task|agent))s?\s+running/i,Gr=/teammate\s+\w+\s+\((?:working|running|busy)\)/gi,ca=/(?:task|step|agent)\s+(\d+)\s*(?:\/|of)\s*(\d+)/i;function Yt(a){let e=oa.exec(a);if(e)return{type:"subtask-count",data:{active:parseInt(e[1],10)}};Gr.lastIndex=0;let t=[],r;for(;(r=Gr.exec(a))!==null;)t.push(r[0]);if(t.length>0)return{type:"subtask-count",data:{active:t.length,teammates:t}};let s=ca.exec(a);return s?{type:"subtask-count",data:{current:parseInt(s[1],10),total:parseInt(s[2],10)}}:null}var la=[Xt,jt,Kt,Gt,Yt];function Yr(a){let e=[];for(let t of la){let r=t(a);r&&e.push(r)}return e}var da=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function ua(a){return a.replace(da,"")}var pa=[/\[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],ma=1e3,ga=1e4,ha=10,fa=500,wa=1e3,Vr=5e3,zr=5,Ta=2e3,$e=class{terminals=new Map;pushHandler;constructor(e){this.pushHandler=e}initTerminal(e,t=24,r=80){this.cleanupTerminal(e);let s={vtBuffer:new _e(t,r),shellState:new Ue(e,n=>{this.pushHandler("terminal.shell-state",n)}),bufferAssembler:new Fe,silenceTimerHandle:setInterval(()=>this.checkSilence(e),ma),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),Fr(s)?r.shellState.onChromeOutput():(r.lastRealOutputAt=Date.now(),r.shellState.onRealOutput(),r.pendingQuestionLine!==null&&(r.chunksAfterQuestion++,r.chunksAfterQuestion>=ha&&(r.pendingQuestionLine=null,r.chunksAfterQuestion=0)),r.questionEmitted&&Date.now()-r.questionEmittedAt>=Ta&&(r.questionEmitted=!1,r.questionEmittedAt=0,this.pushHandler("terminal.awaiting-input-cleared",{terminalId:e})));let i=ua(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<Vr))for(let s of t.split(`
45
- `)){let n=s.trim();if(n.length!==0&&!Kr(s)){for(let i of pa)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(`
46
- `);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<Vr||r-t.lastResizeAt<wa||r-t.lastUserInputAt<fa||t.questionEmitted||t.pendingQuestionLine===null||r-t.lastRealOutputAt<ga||t.lastRealOutputAt===0)return;let n=t.pendingQuestionLine;if(!jr(n)){t.pendingQuestionLine=null;return}if(!t.vtBuffer.containsInBottom(n,zr)){let o=t.vtBuffer.getBottomRows(zr).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(`
47
- `);for(let s of r){let n=s.trim();if(n.length===0)continue;let i=Yr(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 ya=process.platform==="win32",Vt=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"]),We=class a{terminals=new Map;pushHandler;commandBlockParser=new Re;outputEventParser;processDetectionInterval;useTmux;constructor(e){this.pushHandler=e,this.outputEventParser=new $e(e),this.useTmux=b.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=b.getShellPid(e.tmuxSession);if(t)return t}return e.pty.pid}detectProcessForTerminal(e){let t=this.getEffectivePid(e),r;try{if(ya){let n=Be(`wmic process where (ParentProcessId=${t}) get Name /format:list`,{stdio:"pipe",timeout:2e3}).toString().trim().split(`
41
+ `)[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 getCursorPosition(e){try{let r=O("tmux",["-L",N,"display-message","-t",e,"-p","#{cursor_x} #{cursor_y}"],{stdio:"pipe"}).toString().trim().split(" "),s=parseInt(r[0],10),n=parseInt(r[1],10);if(!isNaN(s)&&!isNaN(n))return{x:s,y:n}}catch{}return null}static getSessionSize(e){try{let r=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 Un}from"node:crypto";var Re=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:Un(),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 Fn=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function Fr(a){return a.replace(Fn,"")}var xr=new Set(["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F","\u28FE","\u28FD","\u28FB","\u28BF","\u287F","\u28DF","\u28EF","\u28F7"]),_r=new Set(["\u273B","\u2722","\u26A1","\u25CF","\u25C9","\u25CE","\u25CB","\u25CC","\u23F5"]),$n=/^[\s|/\\\-.*]+$/,Bn=/^[\s─━═╌╍┄┅┈┉╴╶╸╺│┃║├┤┬┴┼╋]+$/,Wn=["\u23F5\u23F5","\u273B ","\u26A1 "];function Ur(a){let e=Fr(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=>xr.has(s)||_r.has(s))||e.length<=10&&$n.test(e)||Bn.test(e))return!0;for(let r of Wn)if(e.startsWith(r))return!0;if(t.length>=1&&t.length<=30){let r=t[0];if(xr.has(r)||_r.has(r))return!0}return!1}function $r(a){if(a.length===0)return!1;if(a.includes("\r")&&!a.includes(`
42
+ `))return a.split("\r").filter(s=>s.length>0).every(s=>Ur(s));let t=a.split(`
43
+ `).filter(r=>Fr(r).trim().length>0);return t.length===0?!0:t.every(r=>Ur(r))}var qn=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function Br(a){return a.replace(qn,"")}var Wr=/\/\/|\/\*|^\s*#\s/,qr=/^[+-][^+-]/,Hn=/\?\s*:|:\s*\?|\?\./,Xn=/\w\)\?\s*$|\w\?\s*;?\s*$/,jn=/\?[a-zA-Z_]+=\S/,Kn=/^\s+at\s+/,Gn=/->|=>|::|!=|==/,Yn=/^#{1,6}\s/,Hr=/^\s*\d+\s*[|:]\s/,Vn=/\b(?:function|def|fn|func|sub|proc)\s+\w/,Xr=/^(?:\s{4,}|\t)/,jr=/\b(?:import|require|from|use|include)\b.*['"`]/,zn=/\([^)]*\)\s*\?\s*$/,Jn=/[+\-*/%]=|<<=|>>=/,Qn=/:\s*\w+\?\s*[;,)=]/;function Kr(a){let e=Br(a).trim();return!(!e.endsWith("?")||e.length<5||Wr.test(e)||qr.test(e)||Hn.test(e)||Xn.test(e)||jn.test(e)||Kn.test(e)||Gn.test(e)||Yn.test(e)||Hr.test(e)||Vn.test(e)||Xr.test(e)||jr.test(e)||zn.test(e)||Jn.test(e)||Qn.test(e))}function Gr(a){let e=Br(a).trim();return qr.test(e)||Hr.test(e)||Xr.test(e)||Wr.test(e)||jr.test(e)}var _e=class{grid;cursorRow=0;cursorCol=0;rows;cols;savedCursor=null;alternateGrid=null;isAlternate=!1;parseState=0;csiParams="";constructor(e=24,t=80){this.rows=e,this.cols=t,this.grid=this.createGrid(e,t)}createGrid(e,t){let r=[];for(let s=0;s<e;s++)r.push(new Array(t).fill(" "));return r}write(e){for(let t=0;t<e.length;t++){let r=e[t],s=e.charCodeAt(t);switch(this.parseState){case 0:this.handleNormal(r,s);break;case 1:this.handleEscStart(r,s);break;case 2:this.handleCsiParam(r,s);break;case 3:s===7?this.parseState=0:s===27&&t+1<e.length&&e.charCodeAt(t+1)===92&&(t++,this.parseState=0);break}}}handleNormal(e,t){if(t===27){this.parseState=1,this.csiParams="";return}if(t===13){this.cursorCol=0;return}if(t===10){this.lineFeed();return}if(t===8){this.cursorCol>0&&this.cursorCol--;return}if(t===9){this.cursorCol=Math.min(this.cols-1,(Math.floor(this.cursorCol/8)+1)*8);return}t<32||(this.cursorRow>=0&&this.cursorRow<this.rows&&this.cursorCol>=0&&this.cursorCol<this.cols&&(this.grid[this.cursorRow][this.cursorCol]=e),this.cursorCol++,this.cursorCol>=this.cols&&(this.cursorCol=0,this.lineFeed()))}handleEscStart(e,t){if(t===91){this.parseState=2,this.csiParams="";return}if(t===93){this.parseState=3;return}if(t===55){this.savedCursor={row:this.cursorRow,col:this.cursorCol},this.parseState=0;return}if(t===56){this.savedCursor&&(this.cursorRow=this.savedCursor.row,this.cursorCol=this.savedCursor.col),this.parseState=0;return}this.parseState=0}handleCsiParam(e,t){if(t>=48&&t<=63){this.csiParams+=e;return}if(t>=32&&t<=47){this.csiParams+=e;return}if(t>=64&&t<=126){this.executeCsi(e,this.csiParams),this.parseState=0;return}this.parseState=0}executeCsi(e,t){let r=t.replace(/^\?/,"").split(";").map(i=>parseInt(i,10)||0),s=t.startsWith("?"),n=r[0]||1;switch(e){case"A":this.cursorRow=Math.max(0,this.cursorRow-n);break;case"B":this.cursorRow=Math.min(this.rows-1,this.cursorRow+n);break;case"C":this.cursorCol=Math.min(this.cols-1,this.cursorCol+n);break;case"D":this.cursorCol=Math.max(0,this.cursorCol-n);break;case"H":case"f":this.cursorRow=Math.min(this.rows-1,Math.max(0,(r[0]||1)-1)),this.cursorCol=Math.min(this.cols-1,Math.max(0,(r[1]||1)-1));break;case"J":this.eraseDisplay(r[0]||0);break;case"K":this.eraseLine(r[0]||0);break;case"m":break;case"s":this.savedCursor={row:this.cursorRow,col:this.cursorCol};break;case"u":this.savedCursor&&(this.cursorRow=this.savedCursor.row,this.cursorCol=this.savedCursor.col);break;case"h":s&&(r[0]===1049||r[0]===47)&&this.enterAlternateScreen();break;case"l":s&&(r[0]===1049||r[0]===47)&&this.leaveAlternateScreen();break;case"r":break;case"G":this.cursorCol=Math.min(this.cols-1,Math.max(0,n-1));break;case"d":this.cursorRow=Math.min(this.rows-1,Math.max(0,n-1));break;case"E":this.cursorRow=Math.min(this.rows-1,this.cursorRow+n),this.cursorCol=0;break;case"F":this.cursorRow=Math.max(0,this.cursorRow-n),this.cursorCol=0;break;default:break}}lineFeed(){this.cursorRow<this.rows-1?this.cursorRow++:(this.grid.shift(),this.grid.push(new Array(this.cols).fill(" ")))}eraseDisplay(e){switch(e){case 0:this.eraseLine(0);for(let t=this.cursorRow+1;t<this.rows;t++)this.grid[t].fill(" ");break;case 1:this.eraseLine(1);for(let t=0;t<this.cursorRow;t++)this.grid[t].fill(" ");break;case 2:case 3:for(let t=0;t<this.rows;t++)this.grid[t].fill(" ");this.cursorRow=0,this.cursorCol=0;break}}eraseLine(e){if(this.cursorRow<0||this.cursorRow>=this.rows)return;let t=this.grid[this.cursorRow];switch(e){case 0:for(let r=this.cursorCol;r<this.cols;r++)t[r]=" ";break;case 1:for(let r=0;r<=this.cursorCol&&r<this.cols;r++)t[r]=" ";break;case 2:t.fill(" ");break}}enterAlternateScreen(){this.isAlternate||(this.alternateGrid=this.grid,this.grid=this.createGrid(this.rows,this.cols),this.isAlternate=!0,this.savedCursor={row:this.cursorRow,col:this.cursorCol},this.cursorRow=0,this.cursorCol=0)}leaveAlternateScreen(){this.isAlternate&&this.alternateGrid&&(this.grid=this.alternateGrid,this.alternateGrid=null,this.isAlternate=!1,this.savedCursor&&(this.cursorRow=this.savedCursor.row,this.cursorCol=this.savedCursor.col,this.savedCursor=null))}getBottomRows(e){let t=[];for(let r=this.rows-1;r>=0&&t.length<e;r--){let s=this.grid[r].join("").trimEnd();s.length>0&&t.unshift(s)}return t}getScreen(){return this.grid.map(e=>e.join("").trimEnd())}resize(e,t){let r=this.createGrid(e,t),s=Math.min(this.rows,e),n=Math.min(this.cols,t);for(let i=0;i<s;i++)for(let o=0;o<n;o++)r[i][o]=this.grid[i][o];this.grid=r,this.rows=e,this.cols=t,this.cursorRow=Math.min(this.cursorRow,e-1),this.cursorCol=Math.min(this.cursorCol,t-1)}containsInBottom(e,t){return this.getBottomRows(t).join(`
44
+ `).includes(e)}};var Ue=class a{constructor(e,t){this.terminalId=e;this.onStateChange=t;this.startedAt=Date.now()}state="idle";lastRealOutputAt=0;idleCheckHandle=null;debouncedIdleHandle=null;startedAt;static IDLE_THRESHOLD_MS=500;static DEBOUNCE_MS=2e3;static STARTUP_GRACE_MS=1e4;inStartupGrace(){return Date.now()-this.startedAt<a.STARTUP_GRACE_MS}onRealOutput(){this.lastRealOutputAt=Date.now(),this.debouncedIdleHandle!==null&&(clearTimeout(this.debouncedIdleHandle),this.debouncedIdleHandle=null),this.state==="idle"&&(this.state="busy",this.inStartupGrace()||this.onStateChange({terminalId:this.terminalId,state:"busy"})),this.idleCheckHandle!==null&&clearTimeout(this.idleCheckHandle),this.idleCheckHandle=setTimeout(()=>this.checkIdle(),a.IDLE_THRESHOLD_MS)}onChromeOutput(){this.state==="busy"&&(this.debouncedIdleHandle!==null&&(clearTimeout(this.debouncedIdleHandle),this.debouncedIdleHandle=null),this.idleCheckHandle!==null&&clearTimeout(this.idleCheckHandle),this.idleCheckHandle=setTimeout(()=>this.checkIdle(),a.IDLE_THRESHOLD_MS))}getState(){return this.state}dispose(){this.idleCheckHandle!==null&&(clearTimeout(this.idleCheckHandle),this.idleCheckHandle=null),this.debouncedIdleHandle!==null&&(clearTimeout(this.debouncedIdleHandle),this.debouncedIdleHandle=null)}checkIdle(){this.idleCheckHandle=null,Date.now()-this.lastRealOutputAt>=a.IDLE_THRESHOLD_MS&&this.state==="busy"&&(this.debouncedIdleHandle=setTimeout(()=>{this.debouncedIdleHandle=null,Date.now()-this.lastRealOutputAt>=a.IDLE_THRESHOLD_MS&&(this.state="idle",this.inStartupGrace()||this.onStateChange({terminalId:this.terminalId,state:"idle"}))},a.DEBOUNCE_MS))}};var Fe=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 Zn=[/(?: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],ea=/(?:retry.?after|wait|try again in)\s*[:=]?\s*(\d+)\s*(s(?:ec)?|m(?:in)?|h(?:our)?)?/i;function Xt(a){for(let e of Zn)if(e.test(a)){let t=ea.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 ta=[/(?: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)/],ra=/(?:HTTP\s+)?([45]\d{2})/;function jt(a){for(let e of ta)if(e.test(a)){let t=ra.exec(a);return{type:"api-error",data:{message:a.trim().slice(0,300),statusCode:t?parseInt(t[1],10):void 0}}}return null}var sa=/https?:\/\/(?:github\.com|gitlab\.com|bitbucket\.org)\/[^\s]+\/pull\/(\d+)/gi,na=/https?:\/\/gitlab\.com\/[^\s]+\/merge_requests\/(\d+)/gi;function Kt(a){let e=[];for(let t of[sa,na]){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 aa=/(\d{1,3}(?:\.\d+)?)\s*%/,ia=/(\d+)\s*\/\s*(\d+)/,oa=/\[([█▓▒░=\->#\s]{4,})\]/;function Gt(a){let e=aa.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=ia.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 oa.test(a)?{type:"progress",data:{raw:a.trim().slice(0,100)}}:null}var ca=/(\d+)\s+(?:tool|sub.?(?:task|agent))s?\s+running/i,Yr=/teammate\s+\w+\s+\((?:working|running|busy)\)/gi,la=/(?:task|step|agent)\s+(\d+)\s*(?:\/|of)\s*(\d+)/i;function Yt(a){let e=ca.exec(a);if(e)return{type:"subtask-count",data:{active:parseInt(e[1],10)}};Yr.lastIndex=0;let t=[],r;for(;(r=Yr.exec(a))!==null;)t.push(r[0]);if(t.length>0)return{type:"subtask-count",data:{active:t.length,teammates:t}};let s=la.exec(a);return s?{type:"subtask-count",data:{current:parseInt(s[1],10),total:parseInt(s[2],10)}}:null}var da=[Xt,jt,Kt,Gt,Yt];function Vr(a){let e=[];for(let t of da){let r=t(a);r&&e.push(r)}return e}var ua=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b\][^\x07]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[>=]|\x1b\[[\d;]*m/g;function pa(a){return a.replace(ua,"")}var ma=[/\[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],ga=1e3,ha=1e4,fa=10,wa=500,Ta=1e3,zr=5e3,Jr=5,Ea=2e3,$e=class{terminals=new Map;pushHandler;constructor(e){this.pushHandler=e}initTerminal(e,t=24,r=80){this.cleanupTerminal(e);let s={vtBuffer:new _e(t,r),shellState:new Ue(e,n=>{this.pushHandler("terminal.shell-state",n)}),bufferAssembler:new Fe,silenceTimerHandle:setInterval(()=>this.checkSilence(e),ga),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),$r(s)?r.shellState.onChromeOutput():(r.lastRealOutputAt=Date.now(),r.shellState.onRealOutput(),r.pendingQuestionLine!==null&&(r.chunksAfterQuestion++,r.chunksAfterQuestion>=fa&&(r.pendingQuestionLine=null,r.chunksAfterQuestion=0)),r.questionEmitted&&Date.now()-r.questionEmittedAt>=Ea&&(r.questionEmitted=!1,r.questionEmittedAt=0,this.pushHandler("terminal.awaiting-input-cleared",{terminalId:e})));let i=pa(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<zr))for(let s of t.split(`
45
+ `)){let n=s.trim();if(n.length!==0&&!Gr(s)){for(let i of ma)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(`
46
+ `);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<zr||r-t.lastResizeAt<Ta||r-t.lastUserInputAt<wa||t.questionEmitted||t.pendingQuestionLine===null||r-t.lastRealOutputAt<ha||t.lastRealOutputAt===0)return;let n=t.pendingQuestionLine;if(!Kr(n)){t.pendingQuestionLine=null;return}if(!t.vtBuffer.containsInBottom(n,Jr)){let o=t.vtBuffer.getBottomRows(Jr).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(`
47
+ `);for(let s of r){let n=s.trim();if(n.length===0)continue;let i=Vr(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 va=process.platform==="win32",Vt=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"]),We=class a{terminals=new Map;pushHandler;commandBlockParser=new Re;outputEventParser;processDetectionInterval;useTmux;constructor(e){this.pushHandler=e,this.outputEventParser=new $e(e),this.useTmux=b.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=b.getShellPid(e.tmuxSession);if(t)return t}return e.pty.pid}detectProcessForTerminal(e){let t=this.getEffectivePid(e),r;try{if(va){let n=Be(`wmic process where (ParentProcessId=${t}) get Name /format:list`,{stdio:"pipe",timeout:2e3}).toString().trim().split(`
48
48
  `).map(i=>i.replace(/^Name=/,"").trim()).filter(i=>i&&!Vt.has(i)&&!Vt.has(i.replace(/\.exe$/i,"")));n.length>0&&(r=n[0].replace(/\.exe$/i,""))}else{let s=Be(`ps -p ${t} -o tty= 2>/dev/null`,{stdio:"pipe",timeout:2e3}).toString().trim();if(s&&s!=="?"){let i=Be(`ps -o comm= -t ${s} 2>/dev/null`,{stdio:"pipe",timeout:2e3}).toString().trim().split(`
49
- `).map(o=>{let c=o.trim();return c.split("/").pop()||c}).filter(o=>o&&!Vt.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==="~"?Jr():e.cwd.startsWith("~/")?Sa(Jr(),e.cwd.slice(2)):e.cwd,s,n;try{if(this.useTmux){let u=await Wt();n=b.createSession(e.id,e.cols,e.rows,r,u,e.env),s=Ht(b.getAttachArgs(n),e.cols,e.rows)}else s=await qt({cols:e.cols,rows:e.rows,cwd:r,env:e.env})}catch(u){if(n){console.warn("[terminal] tmux session creation failed, falling back to direct PTY:",u),b.killSession(n),n=void 0;try{s=await qt({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=b.listSessions();if(r.length===0)return[];let s=Date.now(),n=[],i=0,o=0;for(let c of r){let l=b.getTerminalId(c);if(!l){b.killSession(c),i++;continue}if(e&&!e.has(l)){console.log(`[terminal] Killing orphaned session ${c} (terminal ${l} not in DB)`),b.killSession(c),i++;continue}let d=b.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)`),b.killSession(c),o++;continue}if(!this.terminals.has(l))try{let u=b.getSessionSize(c)||{cols:80,rows:24},p=Ht(b.getAttachArgs(c),u.cols,u.rows),m=b.capturePane(c),g={pty:p,id:l,tmuxSession:c,outputBuffer:m};this.terminals.set(l,g),this.setupHandlers(g),this.outputEventParser.initTerminal(l,u.rows,u.cols),n.push(l)}catch(u){console.error(`[terminal] Failed to recover session ${c}:`,u),b.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?Re.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&&b.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&&b.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);if(!t)return null;if(t.tmuxSession){let r=b.capturePane(t.tmuxSession);if(r){let s=b.getCursorPosition(t.tmuxSession);return s?r+`\x1B[${s.y+1};${s.x+1}H`:r}}return t.outputBuffer?t.outputBuffer:""}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=Be(`lsof -a -p ${r} -d cwd -Fn 2>/dev/null`,{stdio:"pipe",timeout:3e3}).toString().trim().split(`
50
- `);for(let i of n)if(i.startsWith("n"))return i.slice(1)}else if(process.platform==="linux")return Ea(`/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 va}from"node:crypto";var qe=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=va(),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
+ `).map(o=>{let c=o.trim();return c.split("/").pop()||c}).filter(o=>o&&!Vt.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==="~"?Qr():e.cwd.startsWith("~/")?ya(Qr(),e.cwd.slice(2)):e.cwd,s,n;try{if(this.useTmux){let u=await Wt();n=b.createSession(e.id,e.cols,e.rows,r,u,e.env),s=Ht(b.getAttachArgs(n),e.cols,e.rows)}else s=await qt({cols:e.cols,rows:e.rows,cwd:r,env:e.env})}catch(u){if(n){console.warn("[terminal] tmux session creation failed, falling back to direct PTY:",u),b.killSession(n),n=void 0;try{s=await qt({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=b.listSessions();if(r.length===0)return[];let s=Date.now(),n=[],i=0,o=0;for(let c of r){let l=b.getTerminalId(c);if(!l){b.killSession(c),i++;continue}if(e&&!e.has(l)){console.log(`[terminal] Killing orphaned session ${c} (terminal ${l} not in DB)`),b.killSession(c),i++;continue}let d=b.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)`),b.killSession(c),o++;continue}if(!this.terminals.has(l))try{let u=b.getSessionSize(c)||{cols:80,rows:24},p=Ht(b.getAttachArgs(c),u.cols,u.rows),m=b.capturePane(c),g={pty:p,id:l,tmuxSession:c,outputBuffer:m};this.terminals.set(l,g),this.setupHandlers(g),this.outputEventParser.initTerminal(l,u.rows,u.cols),n.push(l)}catch(u){console.error(`[terminal] Failed to recover session ${c}:`,u),b.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?Re.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&&b.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&&b.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);if(!t)return null;if(t.tmuxSession){let r=b.capturePane(t.tmuxSession);if(r){let s=b.getCursorPosition(t.tmuxSession);return s?r+`\x1B[${s.y+1};${s.x+1}H`:r}}return t.outputBuffer?t.outputBuffer:""}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=Be(`lsof -a -p ${r} -d cwd -Fn 2>/dev/null`,{stdio:"pipe",timeout:3e3}).toString().trim().split(`
50
+ `);for(let i of n)if(i.startsWith("n"))return i.slice(1)}else if(process.platform==="linux")return Sa(`/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 ka}from"node:crypto";var qe=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=ka(),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)
51
51
  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
52
52
  name = ?, icon = ?, imageUrl = ?, color = ?, rootDirectory = ?, initGit = ?,
53
53
  defaultCommand = ?, terminalCount = ?, layout = ?, updatedAt = ?
54
54
  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 = ?
55
- 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 zt}from"node:crypto";import{join as ka}from"node:path";var He=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=zt(),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
+ 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 zt}from"node:crypto";import{join as ba}from"node:path";var He=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=zt(),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)
56
56
  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)
57
57
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);for(let u=0;u<o;u++){let p=e.terminals?.[u],m=zt();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
58
58
  name = ?, color = ?, directory = ?, useWorktree = ?,
59
59
  worktreeBranch = ?, defaultCommand = ?, terminalCount = ?,
60
60
  layout = ?, ignoreOnLaunchAll = ?, trigger = ?, updatedAt = ?
61
61
  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)
62
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),c=e.terminalCount??t.terminalCount;for(let l=0;l<c;l++){let d=e.terminals[l],u=d?.id||zt();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:ka(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,g=p?void 0:n.commandSequence;return{id:n.id,label:n.label||`Terminal ${i+1}`,cwd:c,command:m,commandSequence:g,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 = ?
63
- 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 er}from"node:crypto";import{mkdirSync as me,writeFileSync as _a}from"node:fs";import{join as V}from"node:path";import{randomUUID as ba}from"node:crypto";import{mkdirSync as Ia,writeFileSync as Qr}from"node:fs";import{join as Jt}from"node:path";var Xe=class{registry;constructor(e){this.registry=e}async boot(e,t,r,s,n){let i=`swarm-${t.id}-agent-${e.id}-${ba().slice(0,8)}`,o=this.getCommandForCli(e.cli,t.mission,e.autoApprove||t.autoApprove),c=e.name.toLowerCase().replace(/\s+/g,"-"),l=Jt(t.directory,".swarm","agents",c);Ia(l,{recursive:!0});let d=this.generateClaudeMd(t,e);if(Qr(Jt(l,"CLAUDE.md"),d),e.mcps&&e.mcps.length>0){let g={mcpServers:Object.fromEntries(e.mcps.map(f=>[f,{command:f}]))};Qr(Jt(l,".mcp.json"),JSON.stringify(g,null,2))}let u,p,m=t.directory;if(t.useWorktrees&&n&&n.isGitRepo(t.directory))try{let g=n.createForAgent(t.directory,t.id,e.name);u=g.path,p=g.branch,m=g.path}catch(g){console.warn(`[WorktreeManager] Failed to create worktree for agent ${e.name}:`,g)}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(`
64
- `)}getCommandForCli(e,t,r){let s=this.registry.get(e);return s?s.buildCommand({mission:t,cwd:"",autoApprove:r}):e}};import{randomUUID as Ma}from"node:crypto";import{query as Oa}from"@anthropic-ai/claude-agent-sdk";import{randomUUID as Ra}from"node:crypto";import{resolve as Qt,sep as Aa}from"node:path";import{spawn as Ca}from"node:child_process";import{query as La}from"@anthropic-ai/claude-agent-sdk";var Zr=1024*1024,es=5e4,ts=50,rs=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"]),je=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>=ts)throw new Error(`Global CLI session limit (${ts}) 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>es)throw new Error(`Prompt too long (max ${es} chars)`);if(e.prompt.includes("\0"))throw new Error("Prompt contains invalid characters");if(e.workDir){let t=Qt(e.workDir);if(!this.allowedBasePaths.some(s=>t===Qt(s)||t.startsWith(Qt(s)+Aa)))throw new Error(`Working directory "${e.workDir}" is outside allowed paths`)}if(e.env){for(let t of Object.keys(e.env))if(rs.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))rs.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=La({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>Zr&&(e.outputBuffer=e.outputBuffer.slice(-Zr/2))}spawnCLIProcess(e){let t=e.config,{cmd:r,args:s}=this.buildCLICommand(t),n;try{let i=Ca(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 Ke=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 je({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?`
62
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),c=e.terminalCount??t.terminalCount;for(let l=0;l<c;l++){let d=e.terminals[l],u=d?.id||zt();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:ba(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,g=p?void 0:n.commandSequence;return{id:n.id,label:n.label||`Terminal ${i+1}`,cwd:c,command:m,commandSequence:g,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 = ?
63
+ 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 er}from"node:crypto";import{mkdirSync as me,writeFileSync as Ua}from"node:fs";import{join as V}from"node:path";import{randomUUID as Ia}from"node:crypto";import{mkdirSync as Ra,writeFileSync as Zr}from"node:fs";import{join as Jt}from"node:path";var Xe=class{registry;constructor(e){this.registry=e}async boot(e,t,r,s,n){let i=`swarm-${t.id}-agent-${e.id}-${Ia().slice(0,8)}`,o=this.getCommandForCli(e.cli,t.mission,e.autoApprove||t.autoApprove),c=e.name.toLowerCase().replace(/\s+/g,"-"),l=Jt(t.directory,".swarm","agents",c);Ra(l,{recursive:!0});let d=this.generateClaudeMd(t,e);if(Zr(Jt(l,"CLAUDE.md"),d),e.mcps&&e.mcps.length>0){let g={mcpServers:Object.fromEntries(e.mcps.map(f=>[f,{command:f}]))};Zr(Jt(l,".mcp.json"),JSON.stringify(g,null,2))}let u,p,m=t.directory;if(t.useWorktrees&&n&&n.isGitRepo(t.directory))try{let g=n.createForAgent(t.directory,t.id,e.name);u=g.path,p=g.branch,m=g.path}catch(g){console.warn(`[WorktreeManager] Failed to create worktree for agent ${e.name}:`,g)}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(`
64
+ `)}getCommandForCli(e,t,r){let s=this.registry.get(e);return s?s.buildCommand({mission:t,cwd:"",autoApprove:r}):e}};import{randomUUID as Oa}from"node:crypto";import{query as Na}from"@anthropic-ai/claude-agent-sdk";import{randomUUID as Aa}from"node:crypto";import{resolve as Qt,sep as Ca}from"node:path";import{spawn as La}from"node:child_process";import{query as Ma}from"@anthropic-ai/claude-agent-sdk";var es=1024*1024,ts=5e4,rs=50,ss=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"]),je=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>=rs)throw new Error(`Global CLI session limit (${rs}) reached`);let n=Aa(),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>ts)throw new Error(`Prompt too long (max ${ts} chars)`);if(e.prompt.includes("\0"))throw new Error("Prompt contains invalid characters");if(e.workDir){let t=Qt(e.workDir);if(!this.allowedBasePaths.some(s=>t===Qt(s)||t.startsWith(Qt(s)+Ca)))throw new Error(`Working directory "${e.workDir}" is outside allowed paths`)}if(e.env){for(let t of Object.keys(e.env))if(ss.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))ss.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=Ma({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>es&&(e.outputBuffer=e.outputBuffer.slice(-es/2))}spawnCLIProcess(e){let t=e.config,{cmd:r,args:s}=this.buildCLICommand(t),n;try{let i=La(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 Ke=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 je({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?`
65
65
 
66
66
  Context from previous agent:
67
67
  ${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 h=this.instances.get(f.from);if(h?.result){let w=r.get(f.from);p.push(`Result from ${w?.name??f.from}:
@@ -72,26 +72,26 @@ ${p.join(`
72
72
 
73
73
  `)}`:"",g=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,g)}};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=`
74
74
 
75
- 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
+ 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=Na({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(`
76
76
  `),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(`
77
77
  `)});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:
78
78
  `);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(`
79
79
  You can document your own discoveries for teammates to benefit from.`),s.push("")}}catch{}return s.join(`
80
- `)}async escalate(e,t,r,s,n){let i={id:Ma(),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 Ge=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(`
81
- `)||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 Na}from"node:crypto";var Ye=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}addMessage(e){let t=Na(),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)
80
+ `)}async escalate(e,t,r,s,n){let i={id:Oa(),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 Ge=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(`
81
+ `)||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 Da}from"node:crypto";var Ye=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}addMessage(e){let t=Da(),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)
82
82
  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
83
- 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 K}from"node:child_process";import{existsSync as Da}from"node:fs";import{join as Zt}from"node:path";var Ve=class{isGitRepo(e){try{return K("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=Zt(e,".swarm","worktrees",s);try{K(`git branch "${i}" HEAD`,{cwd:e,stdio:"pipe"})}catch{}return K(`git worktree add -B "${i}" "${o}" HEAD`,{cwd:e,stdio:"pipe"}),{path:o,branch:i}}remove(e,t){try{K(`git worktree remove --force "${t}"`,{cwd:e,stdio:"pipe"})}catch{}}removeAllForSwarm(e,t){let r=t.slice(0,8),s=Zt(e,".swarm","worktrees");if(Da(s))try{let n=K("git worktree list --porcelain",{cwd:e,stdio:"pipe"}).toString(),i=[],o={};for(let c of n.split(`
83
+ 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 K}from"node:child_process";import{existsSync as Pa}from"node:fs";import{join as Zt}from"node:path";var Ve=class{isGitRepo(e){try{return K("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=Zt(e,".swarm","worktrees",s);try{K(`git branch "${i}" HEAD`,{cwd:e,stdio:"pipe"})}catch{}return K(`git worktree add -B "${i}" "${o}" HEAD`,{cwd:e,stdio:"pipe"}),{path:o,branch:i}}remove(e,t){try{K(`git worktree remove --force "${t}"`,{cwd:e,stdio:"pipe"})}catch{}}removeAllForSwarm(e,t){let r=t.slice(0,8),s=Zt(e,".swarm","worktrees");if(Pa(s))try{let n=K("git worktree list --porcelain",{cwd:e,stdio:"pipe"}).toString(),i=[],o={};for(let c of n.split(`
84
84
  `))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=Zt(e,".areas","worktrees",n);try{K(`git branch "${o}" HEAD`,{cwd:e,stdio:"pipe"})}catch{}return K(`git worktree add -B "${o}" "${c}" HEAD`,{cwd:e,stdio:"pipe"}),{path:c,branch:o}}removeForArea(e,t){try{K(`git worktree remove --force "${t}"`,{cwd:e,stdio:"pipe"})}catch{}}initGitRepo(e){if(this.isGitRepo(e))return!1;try{return K("git init",{cwd:e,stdio:"pipe"}),!0}catch{return!1}}list(e){try{let t=K("git worktree list --porcelain",{cwd:e,stdio:"pipe"}).toString(),r=[],s={};for(let n of t.split(`
85
- `))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 Pa}from"node:crypto";var ze=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}addEntry(e){let t=Pa(),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)
86
- 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 xa}from"node:crypto";var Je=class{constructor(e,t){this.db=e;this.broadcast=t}post(e){let t=xa(),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)
85
+ `))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 xa}from"node:crypto";var ze=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}addEntry(e){let t=xa(),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)
86
+ 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 _a}from"node:crypto";var Je=class{constructor(e,t){this.db=e;this.broadcast=t}post(e){let t=_a(),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)
87
87
  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 Qe=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 Ye(e,r),this.knowledgeManager=new ze(e,r),this.mailboxManager=new Je(e,r),this.agentSession=new Xe(s),this.worktreeManager=new Ve}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=er(),r=new Date().toISOString(),s=e.knowledge.map(i=>({...i,id:er()}));this.db.prepare(`INSERT INTO swarms (id, workspaceId, name, mission, directory, knowledge, status, presetSize, cliForAll, autoApprove, useWorktrees, createdAt)
88
88
  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=er();return this.db.prepare(`INSERT INTO swarm_agents (id, swarmId, "index", name, role, cli, status, autoApprove, systemPrompt, skills, mcps, workScope, createdAt)
89
- 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=V(t.directory,".swarm");me(V(s,"agents"),{recursive:!0}),me(V(s,"registry"),{recursive:!0}),me(V(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,g=this.agentTerminals.get(c.id)??[];g.push(u),this.agentTerminals.set(c.id,g),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 h=new Ge;h.start(c.id,e,this,this.terminalManager,this.broadcast,this.taskManager??void 0),this.coordinatorLoops.set(e,h);for(let w of t.agents){let T=this.agentTerminals.get(w.id)??[];for(let E of T)h.registerAgentTerminal(w.id,E,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(_a(V(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=V(t.directory,".swarm");me(V(s,"agents"),{recursive:!0}),me(V(s,"registry"),{recursive:!0}),me(V(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 Ke({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 ss}from"node:crypto";import z from"node:fs";import Z from"node:path";import ns from"node:os";var as={"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"}},is=[{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"}],Ze=class{projectSkillsDir(e){return Z.join(e,".swarm","registry","skills")}projectMcpsDir(e){return Z.join(e,".swarm","registry","mcps")}globalSkillsDir(){return Z.join(ns.homedir(),".swarm","registry","skills")}globalMcpsDir(){return Z.join(ns.homedir(),".swarm","registry","mcps")}readJsonFiles(e){return z.existsSync(e)?z.readdirSync(e).filter(r=>r.endsWith(".json")).map(r=>JSON.parse(z.readFileSync(Z.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(as).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);z.mkdirSync(r,{recursive:!0});let s=as[e],n={id:ss(),name:e,description:s?.description??`Custom skill: ${e}`,source:s?"skills.sh":"custom",installedAt:new Date().toISOString()};return z.writeFileSync(Z.join(r,`${e}.json`),JSON.stringify(n,null,2)),n}removeSkill(e,t){let r=Z.join(this.projectSkillsDir(t),`${e}.json`);return z.existsSync(r)?(z.unlinkSync(r),!0):!1}listBundles(){return is}installBundle(e,t){let r=is.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);z.mkdirSync(t,{recursive:!0});let r={id:ss(),name:e.name,command:e.command,args:e.args,env:e.env,enabled:!0};return z.writeFileSync(Z.join(t,`${e.name}.json`),JSON.stringify(r,null,2)),r}};import{randomUUID as os}from"node:crypto";import{execSync as cs}from"node:child_process";var et=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}create(e){let t=os(),r=new Date().toISOString();if(this.db.prepare(`INSERT INTO tasks (id, swarmId, workspaceId, title, description, assignedAgentId, useWorktree, status, approvalMode, createdAt, updatedAt)
89
+ 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=V(t.directory,".swarm");me(V(s,"agents"),{recursive:!0}),me(V(s,"registry"),{recursive:!0}),me(V(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,g=this.agentTerminals.get(c.id)??[];g.push(u),this.agentTerminals.set(c.id,g),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 h=new Ge;h.start(c.id,e,this,this.terminalManager,this.broadcast,this.taskManager??void 0),this.coordinatorLoops.set(e,h);for(let w of t.agents){let T=this.agentTerminals.get(w.id)??[];for(let E of T)h.registerAgentTerminal(w.id,E,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(V(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=V(t.directory,".swarm");me(V(s,"agents"),{recursive:!0}),me(V(s,"registry"),{recursive:!0}),me(V(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 Ke({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 ns}from"node:crypto";import z from"node:fs";import Z from"node:path";import as from"node:os";var is={"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"}},os=[{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"}],Ze=class{projectSkillsDir(e){return Z.join(e,".swarm","registry","skills")}projectMcpsDir(e){return Z.join(e,".swarm","registry","mcps")}globalSkillsDir(){return Z.join(as.homedir(),".swarm","registry","skills")}globalMcpsDir(){return Z.join(as.homedir(),".swarm","registry","mcps")}readJsonFiles(e){return z.existsSync(e)?z.readdirSync(e).filter(r=>r.endsWith(".json")).map(r=>JSON.parse(z.readFileSync(Z.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(is).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);z.mkdirSync(r,{recursive:!0});let s=is[e],n={id:ns(),name:e,description:s?.description??`Custom skill: ${e}`,source:s?"skills.sh":"custom",installedAt:new Date().toISOString()};return z.writeFileSync(Z.join(r,`${e}.json`),JSON.stringify(n,null,2)),n}removeSkill(e,t){let r=Z.join(this.projectSkillsDir(t),`${e}.json`);return z.existsSync(r)?(z.unlinkSync(r),!0):!1}listBundles(){return os}installBundle(e,t){let r=os.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);z.mkdirSync(t,{recursive:!0});let r={id:ns(),name:e.name,command:e.command,args:e.args,env:e.env,enabled:!0};return z.writeFileSync(Z.join(t,`${e.name}.json`),JSON.stringify(r,null,2)),r}};import{randomUUID as cs}from"node:crypto";import{execSync as ls}from"node:child_process";var et=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}create(e){let t=cs(),r=new Date().toISOString();if(this.db.prepare(`INSERT INTO tasks (id, swarmId, workspaceId, title, description, assignedAgentId, useWorktree, status, approvalMode, createdAt, updatedAt)
90
90
  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)
91
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let i of e.attachments)n.run(os(),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{cs(`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{cs(`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)
92
- 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 $a}from"node:child_process";import{execSync as Ua}from"node:child_process";var Fa=process.platform==="win32",Tl=process.platform==="darwin",El=process.platform==="linux";function tr(a){try{let e=Fa?`where ${a}`:`which ${a}`;return Ua(e,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim().split(`
93
- `)[0]}catch{return null}}var ls={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 ds={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 us={id:"gemini",name:"Gemini",command:"gemini",buildCommand({mission:a}){return`gemini '${a.replace(/'/g,"'\\''")}'`}};var ps={id:"opencode",name:"OpenCode",command:"opencode",buildCommand(){return"opencode"}};var ms={id:"cursor",name:"Cursor",command:"cursor",buildCommand(){return"cursor"}};var tt=class{providers=new Map;constructor(){this.register(ls),this.register(ds),this.register(us),this.register(ps),this.register(ms)}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=tr(r.command),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=$a(`${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){return e&&e!=="claude"?e:tr("claude")??"claude"}};import{randomUUID as Ts}from"node:crypto";import{mkdirSync as Wa,writeFileSync as nt}from"node:fs";import{join as Ce}from"node:path";var rt=[{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 Ae=[{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"}],gs=[{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 hs=[{name:"Claude Code",category:"ai_coding",command:"claude",healthCommand:"claude --version",healthSuccessKeywords:["claude"],versionCommand:"claude --version",authCommand:"claude auth status",authSuccessKeywords:["logged in","authenticated",'"loggedin": true'],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},{name:"GitHub CLI",category:"devops",command:"gh",healthCommand:"gh --version",healthSuccessKeywords:["gh version"],versionCommand:"gh --version",authCommand:"gh auth status",authSuccessKeywords:["Logged in"],docsUrl:"https://cli.github.com/manual/",enabled:!0,isBuiltIn:!0},{name:"Vercel CLI",category:"devops",command:"vercel",healthCommand:"vercel --version",healthSuccessKeywords:["Vercel CLI"],versionCommand:"vercel --version",authCommand:"vercel whoami",authSuccessKeywords:[],docsUrl:"https://vercel.com/docs/cli",enabled:!0,isBuiltIn:!0},{name:"Modal",category:"cloud",command:"modal",healthCommand:"modal --version",healthSuccessKeywords:["modal client version"],versionCommand:"modal --version",authCommand:"modal profile current",authSuccessKeywords:[],docsUrl:"https://modal.com/docs/reference/cli",enabled:!0,isBuiltIn:!0},{name:"Tinybird CLI",category:"database",command:"tb",healthCommand:"tb --version",healthSuccessKeywords:["tb, version"],versionCommand:"tb --version",authCommand:"cat ~/.tinyb 2>/dev/null",authSuccessKeywords:["user_email","token"],docsUrl:"https://www.tinybird.co/docs/forward/get-started/install-tinybird-cli",enabled:!0,isBuiltIn:!0}];function rr(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 sr(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 nr(a){let e=rr(a);return["image","pdf","audio","video","archive","font"].includes(e)}var ar=[{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 fs={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 he(a,e){return a==="review"&&e?Ba(e):fs[a]}function st(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 Ba(a){let e=ge(a,"overview"),t=ge(a,"features"),r=ge(a,"screens"),s=a.stack.map(n=>rt.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(`
94
- `)}function ge(a,e){let r=["engine","overview","features","stack","screens","review","done"].indexOf(e),s=fs[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 ws(a){let e=ge(a,"overview")??"",t=ge(a,"features")??"",r=ge(a,"screens")??"",s=a.stack.map(h=>rt.find(w=>w.id===h)?.name??h),n=a.stack.map(h=>rt.find(w=>w.id===h)).filter(Boolean),i=["# PRD - Product Requirements Document","","## Visao Geral","",e,"","## Funcionalidades","",...t.split(`
91
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(let i of e.attachments)n.run(cs(),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{ls(`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{ls(`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)
92
+ 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 Ba}from"node:child_process";var tr=[{id:"claude",label:"Claude",command:"claude"},{id:"codex",label:"Codex",command:"codex"},{id:"gemini",label:"Gemini",command:"gemini"},{id:"opencode",label:"OpenCode",command:"opencode"},{id:"cursor",label:"Cursor",command:"cursor"}];var tt=[{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 Ae=[{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"}],ds=[{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 us=[{name:"Claude Code",category:"ai_coding",command:"claude",healthCommand:"claude --version",healthSuccessKeywords:["claude"],versionCommand:"claude --version",authCommand:"claude auth status",authSuccessKeywords:["logged in","authenticated",'"loggedin": true'],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},{name:"GitHub CLI",category:"devops",command:"gh",healthCommand:"gh --version",healthSuccessKeywords:["gh version"],versionCommand:"gh --version",authCommand:"gh auth status",authSuccessKeywords:["Logged in"],docsUrl:"https://cli.github.com/manual/",enabled:!0,isBuiltIn:!0},{name:"Vercel CLI",category:"devops",command:"vercel",healthCommand:"vercel --version",healthSuccessKeywords:["Vercel CLI"],versionCommand:"vercel --version",authCommand:"vercel whoami",authSuccessKeywords:[],docsUrl:"https://vercel.com/docs/cli",enabled:!0,isBuiltIn:!0},{name:"Modal",category:"cloud",command:"modal",healthCommand:"modal --version",healthSuccessKeywords:["modal client version"],versionCommand:"modal --version",authCommand:"modal profile current",authSuccessKeywords:[],docsUrl:"https://modal.com/docs/reference/cli",enabled:!0,isBuiltIn:!0},{name:"Tinybird CLI",category:"database",command:"tb",healthCommand:"tb --version",healthSuccessKeywords:["tb, version"],versionCommand:"tb --version",authCommand:"cat ~/.tinyb 2>/dev/null",authSuccessKeywords:["user_email","token"],docsUrl:"https://www.tinybird.co/docs/forward/get-started/install-tinybird-cli",enabled:!0,isBuiltIn:!0}];function rr(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 sr(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 nr(a){let e=rr(a);return["image","pdf","audio","video","archive","font"].includes(e)}var ar=[{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}];import{execSync as Fa}from"node:child_process";var $a=process.platform==="win32",rd=process.platform==="darwin",sd=process.platform==="linux";function ir(a){try{let e=$a?`where ${a}`:`which ${a}`;return Fa(e,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim().split(`
93
+ `)[0]}catch{return null}}var ps={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 ms={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 gs={id:"gemini",name:"Gemini",command:"gemini",buildCommand({mission:a}){return`gemini '${a.replace(/'/g,"'\\''")}'`}};var hs={id:"opencode",name:"OpenCode",command:"opencode",buildCommand(){return"opencode"}};var fs={id:"cursor",name:"Cursor",command:"cursor",buildCommand(){return"cursor"}};var rt=class{providers=new Map;customConfigs=new Map;constructor(){this.register(ps),this.register(ms),this.register(gs),this.register(hs),this.register(fs)}register(e){this.providers.set(e.id,e)}get(e){return this.providers.get(e)}listRegistered(){return Array.from(this.providers.keys())}setCustomConfigs(e){this.customConfigs=e}async detectInstalled(){let e=[];for(let[t,r]of this.providers){let s=this.customConfigs.get(t);try{let n=s?.path||ir(r.command);if(!n)throw new Error("not found");let i=tr.find(c=>c.id===t),o={cli:t,installed:!0,path:n,startupCommand:s?.startupCommand??i?.startupCommand??r.command,customPath:s?.path};t==="claude"&&(o.authenticated=this.checkClaudeAuth(n)),e.push(o)}catch{let n=tr.find(i=>i.id===t);e.push({cli:t,installed:!1,startupCommand:s?.startupCommand??n?.startupCommand??r.command,customPath:s?.path})}}return e}checkClaudeAuth(e="claude"){try{let r=Ba(`${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){return e&&e!=="claude"?e:ir("claude")??"claude"}};import{randomUUID as Es}from"node:crypto";import{mkdirSync as qa,writeFileSync as nt}from"node:fs";import{join as Ce}from"node:path";var ws={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 he(a,e){return a==="review"&&e?Wa(e):ws[a]}function st(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 Wa(a){let e=ge(a,"overview"),t=ge(a,"features"),r=ge(a,"screens"),s=a.stack.map(n=>tt.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(`
94
+ `)}function ge(a,e){let r=["engine","overview","features","stack","screens","review","done"].indexOf(e),s=ws[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 Ts(a){let e=ge(a,"overview")??"",t=ge(a,"features")??"",r=ge(a,"screens")??"",s=a.stack.map(h=>tt.find(w=>w.id===h)?.name??h),n=a.stack.map(h=>tt.find(w=>w.id===h)).filter(Boolean),i=["# PRD - Product Requirements Document","","## Visao Geral","",e,"","## Funcionalidades","",...t.split(`
95
95
  `).map(h=>{let w=h.trim();return w?w.startsWith("-")?w:`- ${w}`:""}),"","## Stack Tecnologica","",...s.map(h=>`- ${h}`),"","## Telas","",r,"","---",`Gerado em ${new Date().toISOString()}`].join(`
96
96
  `),o=n.filter(h=>h.category==="frontend").map(h=>h.name),c=n.filter(h=>h.category==="backend").map(h=>h.name),l=n.filter(h=>h.category==="database").map(h=>h.name),d=n.filter(h=>h.category==="auth").map(h=>h.name),u=n.filter(h=>h.category==="deployment").map(h=>h.name),p=["# Arquitetura","","## Frontend",o.length>0?o.map(h=>`- ${h}`).join(`
97
97
  `):"- A definir","","## Backend",c.length>0?c.map(h=>`- ${h}`).join(`
@@ -101,10 +101,10 @@ You can document your own discoveries for teammates to benefit from.`),s.push(""
101
101
  `):"- A definir","","## Variaveis de Ambiente Necessarias","",...n.filter(h=>h.requiredEnvVars&&h.requiredEnvVars.length>0).flatMap(h=>[`### ${h.name}`,...h.requiredEnvVars.map(w=>`- \`${w}\``),""])].join(`
102
102
  `),m=["# Telas","",r].join(`
103
103
  `),g=t.split(`
104
- `).map(h=>h.trim().replace(/^[-*]\s*/,"")).filter(Boolean),f=g.map((h,w)=>({title:`Implementar: ${h}`,description:`Implementar a funcionalidade "${h}" conforme descrito no PRD.`,dependencies:w>0?[g[w-1]]:[]}));return{prdMd:i,architectureMd:p,screensMd:m,tasksJson:f}}var at=class{sessions=new Map;broadcast;constructor(e){this.broadcast=e}startSession(e){let t=Ts(),r=new Date().toISOString(),s="engine",n=this.createMessage("system",he(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",he("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=st(r.step);r.step=n;let i=this.createMessage("system",he(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=st(r.step);r.step=n;let i=this.createMessage("system",he(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=st(r.step);r.step=n;let i=this.createMessage("system",he(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=ws(t),s=Ce(t.projectDir,".swarm","prd");return Wa(s,{recursive:!0}),nt(Ce(s,"prd.md"),r.prdMd,"utf-8"),nt(Ce(s,"architecture.md"),r.architectureMd,"utf-8"),nt(Ce(s,"screens.md"),r.screensMd,"utf-8"),nt(Ce(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:Ts(),role:e,content:t,timestamp:new Date().toISOString()}}};import{createCipheriv as qa,createDecipheriv as Ha,randomBytes as Es}from"node:crypto";var fe=class{masterKey;constructor(e){this.masterKey=e}encrypt(e){let t=Es(12),r=qa("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 Es(32)}};import{execSync as we}from"node:child_process";import{pbkdf2Sync as Xa}from"node:crypto";import{hostname as ja,userInfo as Ka}from"node:os";var it=class{static SERVICE="impactus-swarm";static ACCOUNT="master-key";static _backend;static detectBackend(){if(this._backend!==void 0)return this._backend;try{process.platform==="darwin"?(we("which security",{stdio:"pipe"}),this._backend="macos"):process.platform==="linux"?(we("which secret-tool",{stdio:"pipe"}),this._backend="linux"):this._backend="none"}catch{this._backend="none"}return this._backend}static isAvailable(){return this.detectBackend()!=="none"}static getMasterKey(){let e=this.detectBackend();if(e==="none")return this.deriveFallbackKey();try{if(e==="macos"){let r=we(`security find-generic-password -s "${this.SERVICE}" -a "${this.ACCOUNT}" -w`,{stdio:"pipe",encoding:"utf8"}).trim();return Buffer.from(r,"base64")}let t=we(`secret-tool lookup service "${this.SERVICE}" account "${this.ACCOUNT}"`,{stdio:"pipe",encoding:"utf8"}).trim();return t?Buffer.from(t,"base64"):null}catch{return null}}static setMasterKey(e){let t=this.detectBackend();if(t==="none")return;let r=e.toString("base64");try{t==="macos"?we(`security add-generic-password -s "${this.SERVICE}" -a "${this.ACCOUNT}" -w "${r}" -U`,{stdio:"pipe"}):we(`echo -n "${r}" | secret-tool store --label="IMPACTUS Swarm Master Key" service "${this.SERVICE}" account "${this.ACCOUNT}"`,{stdio:"pipe"})}catch{}}static getOrCreateMasterKey(){let e=this.getMasterKey();return e||(e=fe.generateMasterKey(),this.setMasterKey(e)),e}static deriveFallbackKey(){let e=`${ja()}-${Ka().username}-impactus-swarm-vault`;return Xa(e,"impactus-swarm-salt",1e5,32,"sha256")}};var ot=class{db;vault;constructor(e){this.db=e;let t=it.getOrCreateMasterKey();this.vault=new fe(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)
104
+ `).map(h=>h.trim().replace(/^[-*]\s*/,"")).filter(Boolean),f=g.map((h,w)=>({title:`Implementar: ${h}`,description:`Implementar a funcionalidade "${h}" conforme descrito no PRD.`,dependencies:w>0?[g[w-1]]:[]}));return{prdMd:i,architectureMd:p,screensMd:m,tasksJson:f}}var at=class{sessions=new Map;broadcast;constructor(e){this.broadcast=e}startSession(e){let t=Es(),r=new Date().toISOString(),s="engine",n=this.createMessage("system",he(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",he("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=st(r.step);r.step=n;let i=this.createMessage("system",he(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=st(r.step);r.step=n;let i=this.createMessage("system",he(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=st(r.step);r.step=n;let i=this.createMessage("system",he(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=Ts(t),s=Ce(t.projectDir,".swarm","prd");return qa(s,{recursive:!0}),nt(Ce(s,"prd.md"),r.prdMd,"utf-8"),nt(Ce(s,"architecture.md"),r.architectureMd,"utf-8"),nt(Ce(s,"screens.md"),r.screensMd,"utf-8"),nt(Ce(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:Es(),role:e,content:t,timestamp:new Date().toISOString()}}};import{createCipheriv as Ha,createDecipheriv as Xa,randomBytes as Ss}from"node:crypto";var fe=class{masterKey;constructor(e){this.masterKey=e}encrypt(e){let t=Ss(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=Xa("aes-256-gcm",this.masterKey,n);return c.setAuthTag(o),c.update(i).toString("utf8")+c.final("utf8")}static generateMasterKey(){return Ss(32)}};import{execSync as we}from"node:child_process";import{pbkdf2Sync as ja}from"node:crypto";import{hostname as Ka,userInfo as Ga}from"node:os";var it=class{static SERVICE="impactus-swarm";static ACCOUNT="master-key";static _backend;static detectBackend(){if(this._backend!==void 0)return this._backend;try{process.platform==="darwin"?(we("which security",{stdio:"pipe"}),this._backend="macos"):process.platform==="linux"?(we("which secret-tool",{stdio:"pipe"}),this._backend="linux"):this._backend="none"}catch{this._backend="none"}return this._backend}static isAvailable(){return this.detectBackend()!=="none"}static getMasterKey(){let e=this.detectBackend();if(e==="none")return this.deriveFallbackKey();try{if(e==="macos"){let r=we(`security find-generic-password -s "${this.SERVICE}" -a "${this.ACCOUNT}" -w`,{stdio:"pipe",encoding:"utf8"}).trim();return Buffer.from(r,"base64")}let t=we(`secret-tool lookup service "${this.SERVICE}" account "${this.ACCOUNT}"`,{stdio:"pipe",encoding:"utf8"}).trim();return t?Buffer.from(t,"base64"):null}catch{return null}}static setMasterKey(e){let t=this.detectBackend();if(t==="none")return;let r=e.toString("base64");try{t==="macos"?we(`security add-generic-password -s "${this.SERVICE}" -a "${this.ACCOUNT}" -w "${r}" -U`,{stdio:"pipe"}):we(`echo -n "${r}" | secret-tool store --label="IMPACTUS Swarm Master Key" service "${this.SERVICE}" account "${this.ACCOUNT}"`,{stdio:"pipe"})}catch{}}static getOrCreateMasterKey(){let e=this.getMasterKey();return e||(e=fe.generateMasterKey(),this.setMasterKey(e)),e}static deriveFallbackKey(){let e=`${Ka()}-${Ga().username}-impactus-swarm-vault`;return ja(e,"impactus-swarm-salt",1e5,32,"sha256")}};var ot=class{db;vault;constructor(e){this.db=e;let t=it.getOrCreateMasterKey();this.vault=new fe(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)
105
105
  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 Ae){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 Ae){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)
106
106
  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 Ae.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 Ae){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)
107
- VALUES (?, ?, 0, ?, ?, ?, ?)`),t=new Date().toISOString();for(let r of gs)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 Ga}from"node:crypto";import{exec as Ya}from"node:child_process";import{promisify as Va}from"node:util";var ir=Va(Ya),ct=class{db;constructor(e){this.db=e,this.initializeDefaults()}initializeDefaults(){let e=new Date().toISOString(),t=this.db.prepare(`
107
+ VALUES (?, ?, 0, ?, ?, ?, ?)`),t=new Date().toISOString();for(let r of ds)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 Ya}from"node:crypto";import{exec as Va}from"node:child_process";import{promisify as za}from"node:util";var or=za(Va),ct=class{db;constructor(e){this.db=e,this.initializeDefaults()}initializeDefaults(){let e=new Date().toISOString(),t=this.db.prepare(`
108
108
  INSERT OR IGNORE INTO cli_tools
109
109
  (id, name, logo, category, command, healthCommand, healthSuccessKeywords,
110
110
  versionCommand, authCommand, authSuccessKeywords, docsUrl, envVars, notes,
@@ -115,16 +115,16 @@ You can document your own discoveries for teammates to benefit from.`),s.push(""
115
115
  authCommand = ?, authSuccessKeywords = ?, healthCommand = ?,
116
116
  healthSuccessKeywords = ?, updatedAt = ?
117
117
  WHERE id = ? AND isBuiltIn = 1
118
- `);for(let s of hs){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=Ga();return this.db.prepare(`INSERT INTO cli_tools
118
+ `);for(let s of us){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=Ya();return this.db.prepare(`INSERT INTO cli_tools
119
119
  (id, name, logo, category, command, healthCommand, healthSuccessKeywords,
120
120
  versionCommand, authCommand, authSuccessKeywords, docsUrl, envVars, notes,
121
121
  enabled, isBuiltIn, createdAt, updatedAt)
122
- 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{stdout:n,stderr:i}=await ir(t.healthCommand,{timeout:1e4,encoding:"utf-8",shell:"/bin/sh"}),o=(n+" "+i).toLowerCase();s.installed=!0,t.healthSuccessKeywords.length>0?s.healthy=t.healthSuccessKeywords.some(c=>o.includes(c.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{stdout:n}=await ir(t.versionCommand,{timeout:5e3,encoding:"utf-8"});s.version=n.trim()}catch{}if(t.authCommand){let n="",i=!1;try{let{stdout:o,stderr:c}=await ir(t.authCommand,{timeout:15e3,encoding:"utf-8",shell:"/bin/sh"});n=(o+" "+c).toLowerCase()}catch(o){if(i=!0,o&&typeof o=="object"){let c=o;n=((c.stdout??"")+" "+(c.stderr??"")).toLowerCase()}}t.authSuccessKeywords&&t.authSuccessKeywords.length>0?s.authenticated=t.authSuccessKeywords.some(o=>n.includes(o.toLowerCase())):s.authenticated=n.length>0,s.authenticated||(s.authError=i?`Auth check failed: ${t.authCommand}`:`Not authenticated: ${t.authCommand}`)}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 lt}from"node:crypto";var dt=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=lt(),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=lt(),n=lt(),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=lt(),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,h,w,T)=>h==="class"&&T[w+1]?T[w+1]:f,""),g=(p.attributes||[]).reduce((f,h,w,T)=>h==="id"&&T[w+1]?T[w+1]:f,"");return{found:!0,boundingBox:u,tagName:p.localName||p.nodeName?.toLowerCase(),className:m,id:g,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 za}from"node:child_process";import{promisify as Ja}from"node:util";var Te=Ja(za),ut=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{if(process.kill(t,0),process.platform==="win32"){let{execSync:r}=await import("node:child_process");r(`taskkill /pid ${t} /T /F`,{stdio:"ignore"})}else 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 n=new Map;if(process.platform==="win32"){let{stdout:i}=await Te("wmic process get ParentProcessId,ProcessId /format:csv",{timeout:5e3});for(let o of i.trim().split(`
122
+ 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{stdout:n,stderr:i}=await or(t.healthCommand,{timeout:1e4,encoding:"utf-8",shell:"/bin/sh"}),o=(n+" "+i).toLowerCase();s.installed=!0,t.healthSuccessKeywords.length>0?s.healthy=t.healthSuccessKeywords.some(c=>o.includes(c.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{stdout:n}=await or(t.versionCommand,{timeout:5e3,encoding:"utf-8"});s.version=n.trim()}catch{}if(t.authCommand){let n="",i=!1;try{let{stdout:o,stderr:c}=await or(t.authCommand,{timeout:15e3,encoding:"utf-8",shell:"/bin/sh"});n=(o+" "+c).toLowerCase()}catch(o){if(i=!0,o&&typeof o=="object"){let c=o;n=((c.stdout??"")+" "+(c.stderr??"")).toLowerCase()}}t.authSuccessKeywords&&t.authSuccessKeywords.length>0?s.authenticated=t.authSuccessKeywords.some(o=>n.includes(o.toLowerCase())):s.authenticated=n.length>0,s.authenticated||(s.authError=i?`Auth check failed: ${t.authCommand}`:`Not authenticated: ${t.authCommand}`)}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 lt}from"node:crypto";var dt=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=lt(),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=lt(),n=lt(),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=lt(),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,h,w,T)=>h==="class"&&T[w+1]?T[w+1]:f,""),g=(p.attributes||[]).reduce((f,h,w,T)=>h==="id"&&T[w+1]?T[w+1]:f,"");return{found:!0,boundingBox:u,tagName:p.localName||p.nodeName?.toLowerCase(),className:m,id:g,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 Ja}from"node:child_process";import{promisify as Qa}from"node:util";var Te=Qa(Ja),ut=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{if(process.kill(t,0),process.platform==="win32"){let{execSync:r}=await import("node:child_process");r(`taskkill /pid ${t} /T /F`,{stdio:"ignore"})}else 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 n=new Map;if(process.platform==="win32"){let{stdout:i}=await Te("wmic process get ParentProcessId,ProcessId /format:csv",{timeout:5e3});for(let o of i.trim().split(`
123
123
  `)){let c=o.trim().split(",");if(c.length<3)continue;let l=parseInt(c[1],10),d=parseInt(c[2],10);if(isNaN(l)||isNaN(d))continue;let u=n.get(l);u||(u=[],n.set(l,u)),u.push(d)}}else{let{stdout:i}=await Te("ps -eo ppid=,pid= 2>/dev/null || true",{timeout:3e3});for(let o of i.trim().split(`
124
124
  `)){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=n.get(l);u||(u=[],n.set(l,u)),u.push(d)}}for(let i of t){let o=this.resolvePid(i);if(!o||o<=0)continue;let c=[o];for(s.set(o,i);c.length>0;){let l=c.pop(),d=n.get(l);if(d)for(let u of d)r.has(u)||(r.add(u),s.set(u,i),c.push(u))}}}catch{}return{allDescendantPids:r,pidToTerminal:s}}async detectListeningPorts(){let e=process.platform;try{if(e==="darwin"){let{stdout:t}=await Te("lsof -i -P -n -sTCP:LISTEN 2>/dev/null || true",{timeout:5e3});return this.parseLsofOutput(t)}return e==="linux"?await this.detectLinuxPorts():e==="win32"?await this.detectWindowsPorts():[]}catch{return[]}}async detectLinuxPorts(){try{let{stdout:e}=await Te("ss -tlnp 2>/dev/null || true",{timeout:5e3});return this.parseSsOutput(e)}catch{try{let{stdout:e}=await Te("lsof -i -P -n -sTCP:LISTEN 2>/dev/null || true",{timeout:5e3});return this.parseLsofOutput(e)}catch{return[]}}}async detectWindowsPorts(){try{let{stdout:e}=await Te("netstat -ano",{timeout:5e3});return this.parseNetstatOutput(e)}catch{return[]}}parseSsOutput(e){let t=e.trim().split(`
125
125
  `);if(t.length<2)return[];let r=[],s=new Set;for(let n=1;n<t.length;n++){let i=t[n].trim();if(!i)continue;let o=i.split(/\s+/);if(o.length<5)continue;let c=o[3],l=c.lastIndexOf(":");if(l===-1)continue;let d=c.substring(0,l),u=parseInt(c.substring(l+1),10);if(isNaN(u)||u<=0)continue;let p=0,m="unknown",g=o.slice(5).join(" "),f=g.match(/pid=(\d+)/),h=g.match(/\("([^"]+)"/);if(f&&(p=parseInt(f[1],10)),h&&(m=h[1]),p<=0)continue;let w=`${u}:${p}`;if(s.has(w))continue;s.add(w);let T=d==="*"?"0.0.0.0":d;r.push({port:u,protocol:"tcp",pid:p,process:m,localAddress:T,detectedAt:Date.now()})}return r.sort((n,i)=>n.port-i.port),r}parseNetstatOutput(e){let t=e.trim().split(`
126
126
  `),r=[],s=new Set;for(let n of t){let i=n.trim();if(!i.startsWith("TCP")||!i.includes("LISTENING"))continue;let o=i.split(/\s+/);if(o.length<5)continue;let c=o[1],l=parseInt(o[4],10),d=c.lastIndexOf(":");if(d===-1)continue;let u=c.substring(0,d),p=parseInt(c.substring(d+1),10);if(isNaN(p)||p<=0||isNaN(l)||l<=0)continue;let m=`${p}:${l}`;s.has(m)||(s.add(m),r.push({port:p,protocol:"tcp",pid:l,process:"unknown",localAddress:u,detectedAt:Date.now()}))}return r.sort((n,i)=>n.port-i.port),r}parseLsofOutput(e){let t=e.trim().split(`
127
- `);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 g=u==="*"?"0.0.0.0":u;r.push({port:p,protocol:"tcp",pid:c,process:o,localAddress:g,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 Qa}from"node:child_process";import{exec as Za}from"node:child_process";import{promisify as ei}from"node:util";import{randomBytes as ti}from"node:crypto";var ri=ei(Za),si=/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/,pt=class{process=null;url=null;active=!1;startedAt=null;lastError=null;authToken=null;broadcast;constructor(e){this.broadcast=e}async isCloudflaredInstalled(){try{let e=process.platform==="win32"?"where cloudflared":"which cloudflared";return await ri(e),!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=Qa("cloudflared",s,{stdio:["ignore","pipe","pipe"]}),this.active=!0,this.startedAt=new Date().toISOString(),this.lastError=null,this.authToken=ti(32).toString("hex");let n=i=>{let c=i.toString().match(si);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 ni}from"node:child_process";import{exec as ai}from"node:child_process";import{promisify as ii}from"node:util";var Ss=ii(ai),oi=/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/,ys=10,mt=class{tunnels=new Map;broadcast;constructor(e){this.broadcast=e}async startTunnel(e,t){if(this.tunnels.has(e))return;if(this.tunnels.size>=ys)throw new Error(`Maximum of ${ys} port tunnels reached`);try{let o=process.platform==="win32"?"where cloudflared":"which cloudflared";await Ss(o)}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=ni("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(oi);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{let e=process.platform==="win32"?"where cloudflared":"which cloudflared";return await Ss(e),!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 ci,writeFileSync as vs,readdirSync as li,unlinkSync as di,mkdirSync as ui,existsSync as ks,statSync as pi}from"node:fs";import{join as Ee,basename as mi}from"node:path";function gi(a){return a.toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9\-_]/g,"")}function gt(a){return Ee(a,".swarm","prd","wireframes")}function ht(a,e){let t=ci(a,"utf-8"),r=pi(a),s=e.replace(/-/g," ").replace(/\b\w/g,n=>n.toUpperCase());return{id:e,name:s,content:t,updatedAt:r.mtime.toISOString()}}function hi(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
127
+ `);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 g=u==="*"?"0.0.0.0":u;r.push({port:p,protocol:"tcp",pid:c,process:o,localAddress:g,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 Za}from"node:child_process";import{exec as ei}from"node:child_process";import{promisify as ti}from"node:util";import{randomBytes as ri}from"node:crypto";var si=ti(ei),ni=/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/,pt=class{process=null;url=null;active=!1;startedAt=null;lastError=null;authToken=null;broadcast;constructor(e){this.broadcast=e}async isCloudflaredInstalled(){try{let e=process.platform==="win32"?"where cloudflared":"which cloudflared";return await si(e),!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=Za("cloudflared",s,{stdio:["ignore","pipe","pipe"]}),this.active=!0,this.startedAt=new Date().toISOString(),this.lastError=null,this.authToken=ri(32).toString("hex");let n=i=>{let c=i.toString().match(ni);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 ai}from"node:child_process";import{exec as ii}from"node:child_process";import{promisify as oi}from"node:util";var ys=oi(ii),ci=/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/,vs=10,mt=class{tunnels=new Map;broadcast;constructor(e){this.broadcast=e}async startTunnel(e,t){if(this.tunnels.has(e))return;if(this.tunnels.size>=vs)throw new Error(`Maximum of ${vs} port tunnels reached`);try{let o=process.platform==="win32"?"where cloudflared":"which cloudflared";await ys(o)}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=ai("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(ci);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{let e=process.platform==="win32"?"where cloudflared":"which cloudflared";return await ys(e),!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 li,writeFileSync as ks,readdirSync as di,unlinkSync as ui,mkdirSync as pi,existsSync as bs,statSync as mi}from"node:fs";import{join as Ee,basename as gi}from"node:path";function hi(a){return a.toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9\-_]/g,"")}function gt(a){return Ee(a,".swarm","prd","wireframes")}function ht(a,e){let t=li(a,"utf-8"),r=mi(a),s=e.replace(/-/g," ").replace(/\b\w/g,n=>n.toUpperCase());return{id:e,name:s,content:t,updatedAt:r.mtime.toISOString()}}function fi(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
128
128
  \u2502 LOGIN \u2502
129
129
  \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
130
130
  \u2502 \u2502
@@ -257,24 +257,24 @@ You can document your own discoveries for teammates to benefit from.`),s.push(""
257
257
  \u2502 \u2502
258
258
  \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
259
259
  \u2502 FOOTER \u2502
260
- \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 ft=class{broadcast;constructor(e){this.broadcast=e}ensureDir(e){let t=gt(e);return ui(t,{recursive:!0}),t}list(e){let t=this.ensureDir(e);return li(t).filter(s=>s.endsWith(".txt")).map(s=>{let n=mi(s,".txt");return ht(Ee(t,s),n)})}get(e,t){let r=gt(e),s=Ee(r,`${t}.txt`);return ks(s)?ht(s,t):null}create(e,t){let r=this.ensureDir(e),s=gi(t.name),n=Ee(r,`${s}.txt`),i;t.content?i=t.content:t.description?i=`# ${t.name}
260
+ \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 ft=class{broadcast;constructor(e){this.broadcast=e}ensureDir(e){let t=gt(e);return pi(t,{recursive:!0}),t}list(e){let t=this.ensureDir(e);return di(t).filter(s=>s.endsWith(".txt")).map(s=>{let n=gi(s,".txt");return ht(Ee(t,s),n)})}get(e,t){let r=gt(e),s=Ee(r,`${t}.txt`);return bs(s)?ht(s,t):null}create(e,t){let r=this.ensureDir(e),s=hi(t.name),n=Ee(r,`${s}.txt`),i;t.content?i=t.content:t.description?i=`# ${t.name}
261
261
  # ${t.description}
262
262
 
263
263
  `:i=`# ${t.name}
264
264
 
265
- `,vs(n,i,"utf-8");let o=ht(n,s);return this.broadcast("wireframe.created",{wireframe:o}),o}update(e,t,r){let s=gt(e),n=Ee(s,`${t}.txt`);vs(n,r,"utf-8");let i=ht(n,t);return this.broadcast("wireframe.updated",{wireframe:i}),i}delete(e,t){let r=gt(e),s=Ee(r,`${t}.txt`);ks(s)&&di(s),this.broadcast("wireframe.deleted",{id:t})}generate(e,t,r){let s=hi(r);return this.update(e,t,s)}};import{randomUUID as fi}from"node:crypto";var wt=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=fi(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO command_templates (id, name, description, command, steps, createdAt, updatedAt)
266
- 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 wi}from"node:crypto";var Tt=class{db;constructor(e){this.db=e}list(){return this.db.prepare("SELECT * FROM prompt_templates ORDER BY name ASC").all().map(r=>this.hydrate(r))}get(e){let r=this.db.prepare("SELECT * FROM prompt_templates WHERE id = ?").get(e);return r?this.hydrate(r):null}create(e){let t=wi(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO prompt_templates (id, name, description, content, createdAt, updatedAt)
267
- VALUES (?, ?, ?, ?, ?, ?)`).run(t,e.name,e.description||"",e.content,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 prompt_templates SET name = ?, description = ?, content = ?, updatedAt = ? WHERE id = ?").run(e.name??t.name,e.description??t.description,e.content??t.content,r,e.id),this.get(e.id)}delete(e){return this.db.prepare("DELETE FROM prompt_templates WHERE id = ?").run(e).changes>0}hydrate(e){return{id:e.id,name:e.name,description:e.description,content:e.content,createdAt:e.createdAt,updatedAt:e.updatedAt}}};import{randomUUID as bs}from"node:crypto";var As=process.platform==="win32",Is=As?".venv\\Scripts\\activate":"source .venv/bin/activate",Rs=As?"python":"python3",Ti=[{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:`${Rs} -m venv .venv`,commandSequence:[{command:Is,delay:1e3},{command:"pip install -r requirements.txt",delay:500},{command:`${Rs} main.py`,delay:5e3}]},{label:"Tests",directory:".",command:Is,commandSequence:[{command:"pytest --watch",delay:1e3}]}]},{name:"Simple",description:"Terminal unico",color:"#EA580C",logo:"\u{1F4BB}",defaultCommand:"",terminals:[{label:"Terminal 1",directory:".",command:""}]}],Et=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=bs(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO workspace_templates (id, name, description, color, logo, version, defaultCommand, terminals, isBuiltIn, createdAt, updatedAt)
265
+ `,ks(n,i,"utf-8");let o=ht(n,s);return this.broadcast("wireframe.created",{wireframe:o}),o}update(e,t,r){let s=gt(e),n=Ee(s,`${t}.txt`);ks(n,r,"utf-8");let i=ht(n,t);return this.broadcast("wireframe.updated",{wireframe:i}),i}delete(e,t){let r=gt(e),s=Ee(r,`${t}.txt`);bs(s)&&ui(s),this.broadcast("wireframe.deleted",{id:t})}generate(e,t,r){let s=fi(r);return this.update(e,t,s)}};import{randomUUID as wi}from"node:crypto";var wt=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=wi(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO command_templates (id, name, description, command, steps, createdAt, updatedAt)
266
+ 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 Ti}from"node:crypto";var Tt=class{db;constructor(e){this.db=e}list(){return this.db.prepare("SELECT * FROM prompt_templates ORDER BY name ASC").all().map(r=>this.hydrate(r))}get(e){let r=this.db.prepare("SELECT * FROM prompt_templates WHERE id = ?").get(e);return r?this.hydrate(r):null}create(e){let t=Ti(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO prompt_templates (id, name, description, content, createdAt, updatedAt)
267
+ VALUES (?, ?, ?, ?, ?, ?)`).run(t,e.name,e.description||"",e.content,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 prompt_templates SET name = ?, description = ?, content = ?, updatedAt = ? WHERE id = ?").run(e.name??t.name,e.description??t.description,e.content??t.content,r,e.id),this.get(e.id)}delete(e){return this.db.prepare("DELETE FROM prompt_templates WHERE id = ?").run(e).changes>0}hydrate(e){return{id:e.id,name:e.name,description:e.description,content:e.content,createdAt:e.createdAt,updatedAt:e.updatedAt}}};import{randomUUID as Is}from"node:crypto";var Cs=process.platform==="win32",Rs=Cs?".venv\\Scripts\\activate":"source .venv/bin/activate",As=Cs?"python":"python3",Ei=[{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:`${As} -m venv .venv`,commandSequence:[{command:Rs,delay:1e3},{command:"pip install -r requirements.txt",delay:500},{command:`${As} main.py`,delay:5e3}]},{label:"Tests",directory:".",command:Rs,commandSequence:[{command:"pytest --watch",delay:1e3}]}]},{name:"Simple",description:"Terminal unico",color:"#EA580C",logo:"\u{1F4BB}",defaultCommand:"",terminals:[{label:"Terminal 1",directory:".",command:""}]}],Et=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=Is(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO workspace_templates (id, name, description, color, logo, version, defaultCommand, terminals, isBuiltIn, createdAt, updatedAt)
268
268
  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)
269
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`);for(let n of Ti)s.run(bs(),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 Ei}from"node:crypto";var St=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=Ei(),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)
269
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`);for(let n of Ei)s.run(Is(),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 Si}from"node:crypto";var St=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=Si(),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)
270
270
  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 yt=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)
271
271
  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=g=>s.find(f=>f.name===g),i=new Date().toISOString(),o=this.db.prepare(`INSERT INTO stacks (id, name, description, color, logo, version, steps, isBuiltIn, createdAt, updatedAt)
272
- VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`),c=n("Next.js"),l=n("Docker"),d=n("Simple");if(c&&l&&d){let g=W(),f=W(),h=W(),w=[{id:g,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:g,dependsOnTerminalLabel:"App",waitForText:"Ready",timeoutMs:12e4}},{id:h,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 g=W(),f=W(),h=[{id:g,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:g,dependsOnTerminalLabel:"Docker Up",timeoutMs:6e4}}];o.run(W(),"Python API + DB","Docker DB + Python backend","#CA8A04","\u{1F40D}","1.00",JSON.stringify(h),i,i)}let p=n("Monorepo"),m=n("Multi-Agent");if(p&&m){let g=W(),f=W(),h=[{id:g,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(h),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 Si}from"ws";function Se(a,e){a.readyState===Si.OPEN&&a.send(JSON.stringify(e))}function Ls(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 Le(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 ae(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 Le(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 yi=300*1e3,vt=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,h)=>f.order-h.order),d=new Map,u=new Map,p=new Map;for(let f of l){let h,w=new Promise(T=>{h=T});d.set(f.id,w),u.set(f.id,h)}let m=new Promise((f,h)=>setTimeout(()=>h(new Error("Stack orchestration timed out")),yi)),g=async()=>{let f=l.map(h=>this.runStep({step:h,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([g(),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 g;if(t.targetArea==="new"){let T=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(E=>({label:E.label,directory:E.directory,command:E.command,commandSequence:E.commandSequence,runOnce:!1,commandRunOnce:!1,startDelay:E.startDelay??0,startWaitFor:E.startWaitFor??"",startRunOnce:!1,closeAfterCommand:!1,closeDelay:1e3,closeWaitFor:""})),layout:"auto",templateId:m.id});g=T.id,d("area.updated",{workspaceId:s,area:T})}else{let T=this.areaManager.get(n);if(!T){console.warn(`[StackOrchestrator] Default area not found: ${n}`),c.get(t.id)?.();return}let E=T.terminals.map(R=>({id:R.id,label:R.label,directory:R.directory,command:R.command,commandSequence:R.commandSequence,runOnce:R.runOnce,commandRunOnce:R.commandRunOnce,startDelay:R.startDelay,startWaitFor:R.startWaitFor,startRunOnce:R.startRunOnce,closeAfterCommand:R.closeAfterCommand,closeDelay:R.closeDelay,closeWaitFor:R.closeWaitFor})),U=m.terminals.map(R=>({label:R.label,directory:R.directory,command:R.command,commandSequence:R.commandSequence,runOnce:!1,commandRunOnce:!1,startDelay:0,startWaitFor:"",startRunOnce:!1,closeAfterCommand:!1,closeDelay:1e3,closeWaitFor:""})),de=[...E,...U];this.areaManager.update({id:n,terminalCount:de.length,terminals:de}),g=n;let x=this.areaManager.get(n);d("area.updated",{workspaceId:s,area:x})}c.get(t.id)?.(),d("stack.step.started",{stackId:r.id,stepId:t.id,areaId:g});let f=this.areaManager.get(g);if(!f)return;let h=this.areaManager.resolveForLaunch(f,i),w=t.targetArea==="current"?h.slice(h.length-m.terminals.length):h;l.set(t.id,w.map(T=>T.id));try{await ae(w,u,g)}catch(T){console.error(`[StackOrchestrator] Error launching terminals for step ${t.id}:`,T)}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 Le(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 or}from"node:child_process";var vi=300*1e3,ki=2e3,cr=5e3,Ms=[{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)}}],kt=class{interval=null;startupTimer=null;lastResult=null;previousStates=new Map;broadcast;constructor(e){this.broadcast=e,this.startupTimer=setTimeout(()=>{this.checkAll(),this.startupTimer=null},ki),this.interval=setInterval(()=>{this.checkAll()},vi)}async checkAll(){let e=[];for(let r of Ms){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=Ms.find(c=>c.cli===e);if(!t)return{cli:e,state:"not_installed",installed:!1,authenticated:!1,lastCheckedAt:new Date().toISOString()};let r;try{let c=process.platform==="win32"?"where":"which";r=or(`${c} ${t.command}`,{encoding:"utf8",timeout:cr,stdio:["pipe","pipe","pipe"]}).trim()}catch{return{cli:e,state:"not_installed",installed:!1,authenticated:!1,lastCheckedAt:new Date().toISOString()}}let s;try{s=or(t.versionCommand,{encoding:"utf8",timeout:cr,stdio:["pipe","pipe","pipe"]}).trim()}catch{}let n=!1,i="disconnected",o;try{let c=or(t.authCommand,{encoding:"utf8",timeout:cr,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 bi}from"node:crypto";var Os=100,bt=class{notifications=[];broadcast;constructor(e){this.broadcast=e}add(e,t,r,s){let n={id:bi(),type:e,title:t,message:r,source:s,read:!1,createdAt:new Date().toISOString()};return this.notifications.unshift(n),this.notifications.length>Os&&(this.notifications=this.notifications.slice(0,Os)),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 Ii}from"node:child_process";import{stat as Ri,open as Ai}from"node:fs/promises";import{join as Ns}from"node:path";import{promisify as Ci}from"node:util";var Li=Ci(Ii),It=class{async exec(e,t){return Li("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(`
272
+ VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`),c=n("Next.js"),l=n("Docker"),d=n("Simple");if(c&&l&&d){let g=W(),f=W(),h=W(),w=[{id:g,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:g,dependsOnTerminalLabel:"App",waitForText:"Ready",timeoutMs:12e4}},{id:h,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 g=W(),f=W(),h=[{id:g,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:g,dependsOnTerminalLabel:"Docker Up",timeoutMs:6e4}}];o.run(W(),"Python API + DB","Docker DB + Python backend","#CA8A04","\u{1F40D}","1.00",JSON.stringify(h),i,i)}let p=n("Monorepo"),m=n("Multi-Agent");if(p&&m){let g=W(),f=W(),h=[{id:g,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(h),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 yi}from"ws";function Se(a,e){a.readyState===yi.OPEN&&a.send(JSON.stringify(e))}function Ms(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 Le(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 ae(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 Le(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 vi=300*1e3,vt=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,h)=>f.order-h.order),d=new Map,u=new Map,p=new Map;for(let f of l){let h,w=new Promise(T=>{h=T});d.set(f.id,w),u.set(f.id,h)}let m=new Promise((f,h)=>setTimeout(()=>h(new Error("Stack orchestration timed out")),vi)),g=async()=>{let f=l.map(h=>this.runStep({step:h,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([g(),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 g;if(t.targetArea==="new"){let T=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(E=>({label:E.label,directory:E.directory,command:E.command,commandSequence:E.commandSequence,runOnce:!1,commandRunOnce:!1,startDelay:E.startDelay??0,startWaitFor:E.startWaitFor??"",startRunOnce:!1,closeAfterCommand:!1,closeDelay:1e3,closeWaitFor:""})),layout:"auto",templateId:m.id});g=T.id,d("area.updated",{workspaceId:s,area:T})}else{let T=this.areaManager.get(n);if(!T){console.warn(`[StackOrchestrator] Default area not found: ${n}`),c.get(t.id)?.();return}let E=T.terminals.map(R=>({id:R.id,label:R.label,directory:R.directory,command:R.command,commandSequence:R.commandSequence,runOnce:R.runOnce,commandRunOnce:R.commandRunOnce,startDelay:R.startDelay,startWaitFor:R.startWaitFor,startRunOnce:R.startRunOnce,closeAfterCommand:R.closeAfterCommand,closeDelay:R.closeDelay,closeWaitFor:R.closeWaitFor})),U=m.terminals.map(R=>({label:R.label,directory:R.directory,command:R.command,commandSequence:R.commandSequence,runOnce:!1,commandRunOnce:!1,startDelay:0,startWaitFor:"",startRunOnce:!1,closeAfterCommand:!1,closeDelay:1e3,closeWaitFor:""})),de=[...E,...U];this.areaManager.update({id:n,terminalCount:de.length,terminals:de}),g=n;let x=this.areaManager.get(n);d("area.updated",{workspaceId:s,area:x})}c.get(t.id)?.(),d("stack.step.started",{stackId:r.id,stepId:t.id,areaId:g});let f=this.areaManager.get(g);if(!f)return;let h=this.areaManager.resolveForLaunch(f,i),w=t.targetArea==="current"?h.slice(h.length-m.terminals.length):h;l.set(t.id,w.map(T=>T.id));try{await ae(w,u,g)}catch(T){console.error(`[StackOrchestrator] Error launching terminals for step ${t.id}:`,T)}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 Le(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 cr}from"node:child_process";var ki=300*1e3,bi=2e3,lr=5e3,Os=[{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)}}],kt=class{interval=null;startupTimer=null;lastResult=null;previousStates=new Map;broadcast;constructor(e){this.broadcast=e,this.startupTimer=setTimeout(()=>{this.checkAll(),this.startupTimer=null},bi),this.interval=setInterval(()=>{this.checkAll()},ki)}async checkAll(){let e=[];for(let r of Os){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=Os.find(c=>c.cli===e);if(!t)return{cli:e,state:"not_installed",installed:!1,authenticated:!1,lastCheckedAt:new Date().toISOString()};let r;try{let c=process.platform==="win32"?"where":"which";r=cr(`${c} ${t.command}`,{encoding:"utf8",timeout:lr,stdio:["pipe","pipe","pipe"]}).trim()}catch{return{cli:e,state:"not_installed",installed:!1,authenticated:!1,lastCheckedAt:new Date().toISOString()}}let s;try{s=cr(t.versionCommand,{encoding:"utf8",timeout:lr,stdio:["pipe","pipe","pipe"]}).trim()}catch{}let n=!1,i="disconnected",o;try{let c=cr(t.authCommand,{encoding:"utf8",timeout:lr,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 Ii}from"node:crypto";var Ns=100,bt=class{notifications=[];broadcast;constructor(e){this.broadcast=e}add(e,t,r,s){let n={id:Ii(),type:e,title:t,message:r,source:s,read:!1,createdAt:new Date().toISOString()};return this.notifications.unshift(n),this.notifications.length>Ns&&(this.notifications=this.notifications.slice(0,Ns)),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 Ri}from"node:child_process";import{stat as Ai,open as Ci}from"node:fs/promises";import{join as Ds}from"node:path";import{promisify as Li}from"node:util";var Mi=Li(Ri),It=class{async exec(e,t){return Mi("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(`
273
273
  `))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],g=p[0],f=p[1];g!=="."&&o.push({path:m,status:this.mapStatus(g,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:g}=await this.exec(m,e);return{...this.parseDiff(g),rawPatch:g}}let r="";try{let{stdout:m}=await this.exec(["diff","HEAD"],e);r=m}catch{let[m,g]=await Promise.all([this.exec(["diff"],e).then(f=>f.stdout).catch(()=>""),this.exec(["diff","--cached"],e).then(f=>f.stdout).catch(()=>"")]);r=[m,g].filter(Boolean).join(`
274
274
  `)}let s=await this.exec(["ls-files","--others","--exclude-standard"],e).then(m=>m.stdout.trim().split(`
275
275
  `).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})
276
276
  `);for(let m of c){if(d.length>=o){d+=`# untracked diff truncated at ${o} bytes
277
- `;break}let g=!1,f=!1;try{let h=await Ri(Ns(e,m));if(h.size>i&&(f=!0),!f&&h.size>0){let w=await Ai(Ns(e,m),"r");try{let T=Buffer.alloc(Math.min(8192,h.size));await w.read(T,0,T.length,0),T.includes(0)&&(g=!0)}finally{await w.close()}}}catch{f=!0}if(f||g){d+=`diff --git a/${m} b/${m}
277
+ `;break}let g=!1,f=!1;try{let h=await Ai(Ds(e,m));if(h.size>i&&(f=!0),!f&&h.size>0){let w=await Ci(Ds(e,m),"r");try{let T=Buffer.alloc(Math.min(8192,h.size));await w.read(T,0,T.length,0),T.includes(0)&&(g=!0)}finally{await w.close()}}}catch{f=!0}if(f||g){d+=`diff --git a/${m} b/${m}
278
278
  new file mode 100644
279
279
  --- /dev/null
280
280
  +++ b/${m}
@@ -284,11 +284,11 @@ ${g?"Binary file":"File too large to preview"} (untracked)
284
284
  `)){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(`
285
285
  `)){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(`
286
286
  `)){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(`
287
- `),c,l="",d="modified",u=0;for(let w=0;w<o.length;w++){let T=o[w];if(T.startsWith("--- ")){let E=T.slice(4);E==="/dev/null"?d="added":c=E.replace(/^a\//,"")}else if(T.startsWith("+++ ")){let E=T.slice(4);E==="/dev/null"?(d="deleted",l=c||""):l=E.replace(/^b\//,"")}else if(T.startsWith("@@ ")){u=w;break}else T.startsWith("rename from ")?(c=T.slice(12),d="renamed"):T.startsWith("rename to ")&&(l=T.slice(10),d="renamed")}if(!l&&!c)continue;l||(l=c||"");let p=[],m=null,g=0,f=0;for(let w=u;w<o.length;w++){let T=o[w];if(T.startsWith("@@ ")){let E=T.match(/@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);E&&(g=parseInt(E[1],10),f=parseInt(E[2],10),m={header:T,lines:[]},p.push(m))}else if(m){if(T.startsWith("+")){let E={type:"add",content:T.slice(1),newLineNumber:f};m.lines.push(E),f++,r++}else if(T.startsWith("-")){let E={type:"delete",content:T.slice(1),oldLineNumber:g};m.lines.push(E),g++,s++}else if(T.startsWith(" ")){let E={type:"context",content:T.slice(1),oldLineNumber:g,newLineNumber:f};m.lines.push(E),g++,f++}}}let h={path:l,status:d,hunks:p};c&&c!==l&&(h.oldPath=c),t.push(h)}return{files:t,stats:{filesChanged:t.length,insertions:r,deletions:s}}}};import{execFile as Mi}from"node:child_process";import{promisify as Oi}from"node:util";var Ni=Oi(Mi),Rt=class{constructor(e){this.db=e}async exec(e,t){let r={maxBuffer:10485760};return t&&(r.cwd=t),Ni("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(`
287
+ `),c,l="",d="modified",u=0;for(let w=0;w<o.length;w++){let T=o[w];if(T.startsWith("--- ")){let E=T.slice(4);E==="/dev/null"?d="added":c=E.replace(/^a\//,"")}else if(T.startsWith("+++ ")){let E=T.slice(4);E==="/dev/null"?(d="deleted",l=c||""):l=E.replace(/^b\//,"")}else if(T.startsWith("@@ ")){u=w;break}else T.startsWith("rename from ")?(c=T.slice(12),d="renamed"):T.startsWith("rename to ")&&(l=T.slice(10),d="renamed")}if(!l&&!c)continue;l||(l=c||"");let p=[],m=null,g=0,f=0;for(let w=u;w<o.length;w++){let T=o[w];if(T.startsWith("@@ ")){let E=T.match(/@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);E&&(g=parseInt(E[1],10),f=parseInt(E[2],10),m={header:T,lines:[]},p.push(m))}else if(m){if(T.startsWith("+")){let E={type:"add",content:T.slice(1),newLineNumber:f};m.lines.push(E),f++,r++}else if(T.startsWith("-")){let E={type:"delete",content:T.slice(1),oldLineNumber:g};m.lines.push(E),g++,s++}else if(T.startsWith(" ")){let E={type:"context",content:T.slice(1),oldLineNumber:g,newLineNumber:f};m.lines.push(E),g++,f++}}}let h={path:l,status:d,hunks:p};c&&c!==l&&(h.oldPath=c),t.push(h)}return{files:t,stats:{filesChanged:t.length,insertions:r,deletions:s}}}};import{execFile as Oi}from"node:child_process";import{promisify as Ni}from"node:util";var Di=Ni(Oi),Rt=class{constructor(e){this.db=e}async exec(e,t){let r={maxBuffer:10485760};return t&&(r.cwd=t),Di("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(`
288
288
  `).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)
289
- 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)}};import{randomUUID as lr}from"node:crypto";import{mkdirSync as ie,readFileSync as At,writeFileSync as Ct,unlinkSync as Ds,existsSync as oe,readdirSync as dr,cpSync as Di,rmSync as Ps,renameSync as Pi,statSync as xs}from"node:fs";import{join as D}from"node:path";import{homedir as xi}from"node:os";import{exec as ur}from"node:child_process";var ye=D(xi(),".impactus-swarm","skills"),_i="https://skills.sh/api/skills/all-time",_s="https://raw.githubusercontent.com",Lt=class{db;constructor(e){this.db=e,ie(ye,{recursive:!0}),this.migrateFlatFiles()}migrateFlatFiles(){try{let e=dr(ye,{withFileTypes:!0});for(let t of e)if(t.isFile()&&t.name.endsWith(".md")){let r=t.name.replace(/\.md$/,""),s=D(ye,t.name),n=D(ye,r),i=D(n,"SKILL.md");ie(n,{recursive:!0});let o=At(s,"utf-8");Ct(i,o,"utf-8"),Ds(s)}}catch{}}resolveSkillPath(e,t){let r=D(ye,e),s=D(r,t);if(!s.startsWith(r))throw new Error("Invalid path: path traversal detected");return s}getSkillDir(e){return D(ye,e)}list(){return this.db.prepare("SELECT * FROM saved_skills ORDER BY createdAt DESC").all().map(r=>this.hydrate(r))}get(e){let r=this.db.prepare("SELECT * FROM saved_skills WHERE id = ?").get(e);return r?this.hydrate(r):null}save(e){let t=lr(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO saved_skills (id, name, displayName, description, source, skillId, command, hasFile, tags, isCustom, parentSkillIds, createdAt, updatedAt)
290
- VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, 0, '[]', ?, ?)`).run(t,e.name,e.displayName,e.description,e.source,e.skillId,e.command,JSON.stringify(e.tags??[]),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 saved_skills SET displayName = ?, description = ?, command = ?, tags = ?, updatedAt = ? WHERE id = ?").run(e.displayName??t.displayName,e.description??t.description,e.command??t.command,e.tags?JSON.stringify(e.tags):JSON.stringify(t.tags),r,e.id),this.get(e.id)}delete(e){let t=this.get(e);if(t?.hasFile){let n=this.getSkillDir(t.name);try{Ps(n,{recursive:!0})}catch{}}return this.db.prepare("DELETE FROM saved_skills WHERE id = ?").run(e).changes>0}saveFile(e,t){let r=this.get(e);if(!r)throw new Error(`Skill not found: ${e}`);let s=this.getSkillDir(r.name);ie(s,{recursive:!0});let n=D(s,"SKILL.md");Ct(n,t,"utf-8");let i=new Date().toISOString();return this.db.prepare("UPDATE saved_skills SET hasFile = 1, isCustom = 1, updatedAt = ? WHERE id = ?").run(i,e),{filePath:n}}readFile(e){let t=this.get(e);if(!t)throw new Error(`Skill not found: ${e}`);let r=D(this.getSkillDir(t.name),"SKILL.md");if(!oe(r))throw new Error(`Skill file not found: ${r}`);return{content:At(r,"utf-8"),filePath:r}}openFolder(e){let t=this.get(e);if(!t)throw new Error(`Skill not found: ${e}`);let r=this.getSkillDir(t.name),s=D(r,"SKILL.md"),n=process.platform;return n==="darwin"?ur(`open "${r}"`):n==="win32"?ur(`explorer "${r.replace(/\//g,"\\")}"`):ur(`xdg-open "${r}"`),{filePath:s,dirPath:r}}duplicate(e,t){let r=this.get(e);if(!r)throw new Error(`Skill not found: ${e}`);let s=t||`${r.name}-copy`,n=lr(),i=new Date().toISOString();if(this.db.prepare(`INSERT INTO saved_skills (id, name, displayName, description, source, skillId, command, hasFile, tags, isCustom, parentSkillIds, createdAt, updatedAt)
291
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?)`).run(n,s,`${r.displayName} (Copy)`,r.description,r.source,r.skillId,r.command,r.hasFile?1:0,JSON.stringify(r.tags),JSON.stringify([r.id]),i,i),r.hasFile){let c=this.getSkillDir(r.name),l=this.getSkillDir(s);oe(c)&&Di(c,l,{recursive:!0})}return this.get(n)}merge(e,t,r,s){let n=e.map(m=>{let g=this.get(m);if(!g)throw new Error(`Skill not found: ${m}`);return g}),i=[];for(let m of n){let g=D(this.getSkillDir(m.name),"SKILL.md");if(oe(g)){let f=At(g,"utf-8");i.push(`# ${m.displayName}
289
+ 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)}};import{randomUUID as dr}from"node:crypto";import{mkdirSync as ie,readFileSync as At,writeFileSync as Ct,unlinkSync as Ps,existsSync as oe,readdirSync as ur,cpSync as Pi,rmSync as xs,renameSync as xi,statSync as _s}from"node:fs";import{join as D}from"node:path";import{homedir as _i}from"node:os";import{exec as pr}from"node:child_process";var ye=D(_i(),".impactus-swarm","skills"),Ui="https://skills.sh/api/skills/all-time",Us="https://raw.githubusercontent.com",Lt=class{db;constructor(e){this.db=e,ie(ye,{recursive:!0}),this.migrateFlatFiles()}migrateFlatFiles(){try{let e=ur(ye,{withFileTypes:!0});for(let t of e)if(t.isFile()&&t.name.endsWith(".md")){let r=t.name.replace(/\.md$/,""),s=D(ye,t.name),n=D(ye,r),i=D(n,"SKILL.md");ie(n,{recursive:!0});let o=At(s,"utf-8");Ct(i,o,"utf-8"),Ps(s)}}catch{}}resolveSkillPath(e,t){let r=D(ye,e),s=D(r,t);if(!s.startsWith(r))throw new Error("Invalid path: path traversal detected");return s}getSkillDir(e){return D(ye,e)}list(){return this.db.prepare("SELECT * FROM saved_skills ORDER BY createdAt DESC").all().map(r=>this.hydrate(r))}get(e){let r=this.db.prepare("SELECT * FROM saved_skills WHERE id = ?").get(e);return r?this.hydrate(r):null}save(e){let t=dr(),r=new Date().toISOString();return this.db.prepare(`INSERT INTO saved_skills (id, name, displayName, description, source, skillId, command, hasFile, tags, isCustom, parentSkillIds, createdAt, updatedAt)
290
+ VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, 0, '[]', ?, ?)`).run(t,e.name,e.displayName,e.description,e.source,e.skillId,e.command,JSON.stringify(e.tags??[]),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 saved_skills SET displayName = ?, description = ?, command = ?, tags = ?, updatedAt = ? WHERE id = ?").run(e.displayName??t.displayName,e.description??t.description,e.command??t.command,e.tags?JSON.stringify(e.tags):JSON.stringify(t.tags),r,e.id),this.get(e.id)}delete(e){let t=this.get(e);if(t?.hasFile){let n=this.getSkillDir(t.name);try{xs(n,{recursive:!0})}catch{}}return this.db.prepare("DELETE FROM saved_skills WHERE id = ?").run(e).changes>0}saveFile(e,t){let r=this.get(e);if(!r)throw new Error(`Skill not found: ${e}`);let s=this.getSkillDir(r.name);ie(s,{recursive:!0});let n=D(s,"SKILL.md");Ct(n,t,"utf-8");let i=new Date().toISOString();return this.db.prepare("UPDATE saved_skills SET hasFile = 1, isCustom = 1, updatedAt = ? WHERE id = ?").run(i,e),{filePath:n}}readFile(e){let t=this.get(e);if(!t)throw new Error(`Skill not found: ${e}`);let r=D(this.getSkillDir(t.name),"SKILL.md");if(!oe(r))throw new Error(`Skill file not found: ${r}`);return{content:At(r,"utf-8"),filePath:r}}openFolder(e){let t=this.get(e);if(!t)throw new Error(`Skill not found: ${e}`);let r=this.getSkillDir(t.name),s=D(r,"SKILL.md"),n=process.platform;return n==="darwin"?pr(`open "${r}"`):n==="win32"?pr(`explorer "${r.replace(/\//g,"\\")}"`):pr(`xdg-open "${r}"`),{filePath:s,dirPath:r}}duplicate(e,t){let r=this.get(e);if(!r)throw new Error(`Skill not found: ${e}`);let s=t||`${r.name}-copy`,n=dr(),i=new Date().toISOString();if(this.db.prepare(`INSERT INTO saved_skills (id, name, displayName, description, source, skillId, command, hasFile, tags, isCustom, parentSkillIds, createdAt, updatedAt)
291
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?)`).run(n,s,`${r.displayName} (Copy)`,r.description,r.source,r.skillId,r.command,r.hasFile?1:0,JSON.stringify(r.tags),JSON.stringify([r.id]),i,i),r.hasFile){let c=this.getSkillDir(r.name),l=this.getSkillDir(s);oe(c)&&Pi(c,l,{recursive:!0})}return this.get(n)}merge(e,t,r,s){let n=e.map(m=>{let g=this.get(m);if(!g)throw new Error(`Skill not found: ${m}`);return g}),i=[];for(let m of n){let g=D(this.getSkillDir(m.name),"SKILL.md");if(oe(g)){let f=At(g,"utf-8");i.push(`# ${m.displayName}
292
292
 
293
293
  ${f}`)}else i.push(`# ${m.displayName}
294
294
 
@@ -296,13 +296,13 @@ _No file content available._`)}let o=i.join(`
296
296
 
297
297
  ---
298
298
 
299
- `),c=lr(),l=new Date().toISOString(),d=[...new Set(n.flatMap(m=>m.tags))];this.db.prepare(`INSERT INTO saved_skills (id, name, displayName, description, source, skillId, command, hasFile, tags, isCustom, parentSkillIds, createdAt, updatedAt)
300
- VALUES (?, ?, ?, ?, 'local', ?, '', 1, ?, 1, ?, ?, ?)`).run(c,t,r,s||`Merged from: ${n.map(m=>m.displayName).join(", ")}`,c,JSON.stringify(d),JSON.stringify(e),l,l);let p=this.getSkillDir(t);return ie(p,{recursive:!0}),Ct(D(p,"SKILL.md"),o,"utf-8"),this.get(c)}listSkillFiles(e){let t=this.get(e);if(!t)throw new Error(`Skill not found: ${e}`);let r=this.getSkillDir(t.name);return oe(r)?this.readDirRecursive(r,""):[]}readDirRecursive(e,t){let r=t?D(e,t):e,s=dr(r,{withFileTypes:!0}),n=[];for(let i of s){let o=t?`${t}/${i.name}`:i.name;if(i.isDirectory()){let c=this.readDirRecursive(e,o);n.push({name:i.name,path:o,isDirectory:!0,children:c})}else{let c=D(r,i.name),l=xs(c);n.push({name:i.name,path:o,isDirectory:!1,size:l.size})}}return n}readSkillFile(e,t){let r=this.get(e);if(!r)throw new Error(`Skill not found: ${e}`);let s=this.resolveSkillPath(r.name,t);if(!oe(s))throw new Error(`File not found: ${t}`);return{content:At(s,"utf-8"),filePath:s}}writeSkillFile(e,t,r){let s=this.get(e);if(!s)throw new Error(`Skill not found: ${e}`);let n=this.resolveSkillPath(s.name,t),i=D(n,"..");return ie(i,{recursive:!0}),Ct(n,r,"utf-8"),{filePath:n}}deleteSkillFile(e,t){let r=this.get(e);if(!r)throw new Error(`Skill not found: ${e}`);let s=this.resolveSkillPath(r.name,t);if(!oe(s))return!1;if(xs(s).isDirectory()){if(dr(s).length>0)throw new Error("Cannot delete non-empty directory");Ps(s)}else Ds(s);return!0}createSkillFolder(e,t){let r=this.get(e);if(!r)throw new Error(`Skill not found: ${e}`);let s=this.resolveSkillPath(r.name,t);return ie(s,{recursive:!0}),!0}renameSkillFile(e,t,r){let s=this.get(e);if(!s)throw new Error(`Skill not found: ${e}`);let n=this.resolveSkillPath(s.name,t),i=this.resolveSkillPath(s.name,r);if(!oe(n))throw new Error(`Source not found: ${t}`);let o=D(i,"..");return ie(o,{recursive:!0}),Pi(n,i),!0}async browseRemote(e){let t=e.page??1,r=e.pageSize??20,s=`${_i}/${t}`,n=await fetch(s);if(!n.ok)throw new Error(`skills.sh API error: ${n.status} ${n.statusText}`);let i=await n.json(),o=i.skills.map(c=>{let l=c.source||"",[d="",u=""]=l.split("/"),p=c.name||c.skillId||"";return{source:l,skillId:c.skillId||p,name:p,installs:c.installs||0,owner:d,repo:u,githubUrl:`https://github.com/${l}`,displayName:c.displayName||p}});if(e.query){let c=e.query.toLowerCase();o=o.filter(l=>l.name.toLowerCase().includes(c)||l.displayName.toLowerCase().includes(c)||l.owner.toLowerCase().includes(c)||l.repo.toLowerCase().includes(c))}if(e.sortBy==="name"){let c=e.sortOrder==="desc"?-1:1;o.sort((l,d)=>l.name.localeCompare(d.name)*c)}else if(e.sortBy==="installs"){let c=e.sortOrder==="asc"?1:-1;o.sort((l,d)=>(d.installs-l.installs)*c)}return{skills:o.slice(0,r),total:i.total??o.length,page:t,pageSize:r}}async fetchRemoteContent(e,t,r){let s=[`${r}/SKILL.md`,`skills/${r}/SKILL.md`,`sdk/${r}/SKILL.md`,`guides/${r}/SKILL.md`];for(let n of["main","master"])for(let i of s){let o=`${_s}/${e}/${t}/${n}/${i}`;try{let c=await fetch(o);if(c.ok){let l=await c.text();return this.parseSkillMd(l)}}catch{}}try{let n=await fetch(`https://api.github.com/repos/${e}/${t}/git/trees/main?recursive=1`,{headers:{Accept:"application/vnd.github.v3+json","User-Agent":"impactus-swarm"}});if(n.ok){let i=await n.json(),o=`${r}/SKILL.md`,c=i.tree.find(l=>l.type==="blob"&&l.path.endsWith(o));if(c){let l=`${_s}/${e}/${t}/main/${c.path}`,d=await fetch(l);if(d.ok){let u=await d.text();return this.parseSkillMd(u)}}}}catch{}throw new Error(`Could not fetch SKILL.md for ${e}/${t}/${r}`)}parseSkillMd(e){let t={name:"",description:""},r=e,s=e.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);if(s){let n=s[1];r=s[2].trim();for(let i of n.split(`
301
- `)){let o=i.indexOf(":");if(o===-1)continue;let c=i.slice(0,o).trim(),l=i.slice(o+1).trim().replace(/^["']|["']$/g,"");c&&l&&(t[c]=l)}}return{raw:e,metadata:t,instructions:r}}hydrate(e){return{id:e.id,name:e.name,displayName:e.displayName,description:e.description,source:e.source,skillId:e.skillId,command:e.command,hasFile:e.hasFile===1,tags:JSON.parse(e.tags),isCustom:e.isCustom===1,parentSkillIds:JSON.parse(e.parentSkillIds),createdAt:e.createdAt,updatedAt:e.updatedAt}}};function Us(){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),g=1;for(;i.existsSync(l);)l=o.resolve(n,`${m} (${g})${p}`),g++}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 Fs(){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 ae(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 g of l){for(let f of g.terminals)n.close(f.id);s.setRunning(g.id,!1)}r.setRunning(t.id,!1),i.stopMonitoring(t.id);let u=l.filter(g=>!g.ignoreOnLaunchAll).map(g=>{s.resetAllTerminals(g.id);let f=s.resolveForLaunch(g,o.rootDirectory);return{area:g,resolved:f}});if(u.length===0){s.resetAllTerminals(c.id);let g=s.resolveForLaunch(c,o.rootDirectory);u.push({area:c,resolved:g})}let p=u.find(g=>g.area.id===c.id)??u[0],m=new Map(p.area.terminals.map(g=>[g.id,g.color||"default"]));return e.respond({ok:!0,terminals:p.resolved.map(g=>({id:g.id,label:g.label,cwd:g.cwd,position:g.position,color:m.get(g.id)||"default"}))}),(async()=>{let g=[];await Promise.all(u.map(async({area:f,resolved:h})=>{try{let w=f.trigger;if(w){let T=w.timeoutMs??12e4;w.type==="delay"?await new Promise(E=>setTimeout(E,w.delayMs??0)):w.type==="waitForOutput"&&w.dependsOnTerminalId&&w.waitForText?await Le(n,w.dependsOnTerminalId,w.waitForText,T):w.type==="waitForExit"&&w.dependsOnTerminalId&&await Ls(n,w.dependsOnTerminalId,T)}await ae(h,e.services,f.id,{ignoreRunOnce:!0,completedStepsProvider:T=>s.getCompletedSteps(T),onStepCompleted:(T,E)=>{s.markStepCompleted(T,E)}}),s.setRunning(f.id,!0),e.services.broadcast("area.status",{id:f.id,workspaceId:t.id,state:"running"});for(let T of h)g.push(T.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"}),g.length>0&&i.startMonitoring(t.id,g).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 $s(){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 ae(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 Bs(){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 pr,writeFile as Mt,cp as Ui}from"node:fs/promises";import{basename as Fi,join as ee,resolve as $i}from"node:path";var Me=class{async buildContext(e){let{task:t,agent:r,swarm:s,knowledgeEntries:n,dependencyTasks:i,workspaceDir:o}=e,c=ee(o,".swarm","tasks",t.id);await pr(c,{recursive:!0});let l=this.assemblePrompt(t,r,n,i),d=ee(c,"CLAUDE.md"),u=this.generateClaudeMd(t,r,s);await Mt(d,u,"utf-8");let p=this.generateTaskMd(t,i);if(await Mt(ee(c,"TASK.md"),p,"utf-8"),s?.knowledge&&s.knowledge.length>0){let m=ee(c,"knowledge");await pr(m,{recursive:!0});for(let g of s.knowledge)try{let f=Fi(g.name),h=$i(g.path),w=ee(m,f);await Ui(h,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(`
299
+ `),c=dr(),l=new Date().toISOString(),d=[...new Set(n.flatMap(m=>m.tags))];this.db.prepare(`INSERT INTO saved_skills (id, name, displayName, description, source, skillId, command, hasFile, tags, isCustom, parentSkillIds, createdAt, updatedAt)
300
+ VALUES (?, ?, ?, ?, 'local', ?, '', 1, ?, 1, ?, ?, ?)`).run(c,t,r,s||`Merged from: ${n.map(m=>m.displayName).join(", ")}`,c,JSON.stringify(d),JSON.stringify(e),l,l);let p=this.getSkillDir(t);return ie(p,{recursive:!0}),Ct(D(p,"SKILL.md"),o,"utf-8"),this.get(c)}listSkillFiles(e){let t=this.get(e);if(!t)throw new Error(`Skill not found: ${e}`);let r=this.getSkillDir(t.name);return oe(r)?this.readDirRecursive(r,""):[]}readDirRecursive(e,t){let r=t?D(e,t):e,s=ur(r,{withFileTypes:!0}),n=[];for(let i of s){let o=t?`${t}/${i.name}`:i.name;if(i.isDirectory()){let c=this.readDirRecursive(e,o);n.push({name:i.name,path:o,isDirectory:!0,children:c})}else{let c=D(r,i.name),l=_s(c);n.push({name:i.name,path:o,isDirectory:!1,size:l.size})}}return n}readSkillFile(e,t){let r=this.get(e);if(!r)throw new Error(`Skill not found: ${e}`);let s=this.resolveSkillPath(r.name,t);if(!oe(s))throw new Error(`File not found: ${t}`);return{content:At(s,"utf-8"),filePath:s}}writeSkillFile(e,t,r){let s=this.get(e);if(!s)throw new Error(`Skill not found: ${e}`);let n=this.resolveSkillPath(s.name,t),i=D(n,"..");return ie(i,{recursive:!0}),Ct(n,r,"utf-8"),{filePath:n}}deleteSkillFile(e,t){let r=this.get(e);if(!r)throw new Error(`Skill not found: ${e}`);let s=this.resolveSkillPath(r.name,t);if(!oe(s))return!1;if(_s(s).isDirectory()){if(ur(s).length>0)throw new Error("Cannot delete non-empty directory");xs(s)}else Ps(s);return!0}createSkillFolder(e,t){let r=this.get(e);if(!r)throw new Error(`Skill not found: ${e}`);let s=this.resolveSkillPath(r.name,t);return ie(s,{recursive:!0}),!0}renameSkillFile(e,t,r){let s=this.get(e);if(!s)throw new Error(`Skill not found: ${e}`);let n=this.resolveSkillPath(s.name,t),i=this.resolveSkillPath(s.name,r);if(!oe(n))throw new Error(`Source not found: ${t}`);let o=D(i,"..");return ie(o,{recursive:!0}),xi(n,i),!0}async browseRemote(e){let t=e.page??1,r=e.pageSize??20,s=`${Ui}/${t}`,n=await fetch(s);if(!n.ok)throw new Error(`skills.sh API error: ${n.status} ${n.statusText}`);let i=await n.json(),o=i.skills.map(c=>{let l=c.source||"",[d="",u=""]=l.split("/"),p=c.name||c.skillId||"";return{source:l,skillId:c.skillId||p,name:p,installs:c.installs||0,owner:d,repo:u,githubUrl:`https://github.com/${l}`,displayName:c.displayName||p}});if(e.query){let c=e.query.toLowerCase();o=o.filter(l=>l.name.toLowerCase().includes(c)||l.displayName.toLowerCase().includes(c)||l.owner.toLowerCase().includes(c)||l.repo.toLowerCase().includes(c))}if(e.sortBy==="name"){let c=e.sortOrder==="desc"?-1:1;o.sort((l,d)=>l.name.localeCompare(d.name)*c)}else if(e.sortBy==="installs"){let c=e.sortOrder==="asc"?1:-1;o.sort((l,d)=>(d.installs-l.installs)*c)}return{skills:o.slice(0,r),total:i.total??o.length,page:t,pageSize:r}}async fetchRemoteContent(e,t,r){let s=[`${r}/SKILL.md`,`skills/${r}/SKILL.md`,`sdk/${r}/SKILL.md`,`guides/${r}/SKILL.md`];for(let n of["main","master"])for(let i of s){let o=`${Us}/${e}/${t}/${n}/${i}`;try{let c=await fetch(o);if(c.ok){let l=await c.text();return this.parseSkillMd(l)}}catch{}}try{let n=await fetch(`https://api.github.com/repos/${e}/${t}/git/trees/main?recursive=1`,{headers:{Accept:"application/vnd.github.v3+json","User-Agent":"impactus-swarm"}});if(n.ok){let i=await n.json(),o=`${r}/SKILL.md`,c=i.tree.find(l=>l.type==="blob"&&l.path.endsWith(o));if(c){let l=`${Us}/${e}/${t}/main/${c.path}`,d=await fetch(l);if(d.ok){let u=await d.text();return this.parseSkillMd(u)}}}}catch{}throw new Error(`Could not fetch SKILL.md for ${e}/${t}/${r}`)}parseSkillMd(e){let t={name:"",description:""},r=e,s=e.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);if(s){let n=s[1];r=s[2].trim();for(let i of n.split(`
301
+ `)){let o=i.indexOf(":");if(o===-1)continue;let c=i.slice(0,o).trim(),l=i.slice(o+1).trim().replace(/^["']|["']$/g,"");c&&l&&(t[c]=l)}}return{raw:e,metadata:t,instructions:r}}hydrate(e){return{id:e.id,name:e.name,displayName:e.displayName,description:e.description,source:e.source,skillId:e.skillId,command:e.command,hasFile:e.hasFile===1,tags:JSON.parse(e.tags),isCustom:e.isCustom===1,parentSkillIds:JSON.parse(e.parentSkillIds),createdAt:e.createdAt,updatedAt:e.updatedAt}}};function Fs(){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),g=1;for(;i.existsSync(l);)l=o.resolve(n,`${m} (${g})${p}`),g++}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 $s(){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 ae(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 g of l){for(let f of g.terminals)n.close(f.id);s.setRunning(g.id,!1)}r.setRunning(t.id,!1),i.stopMonitoring(t.id);let u=l.filter(g=>!g.ignoreOnLaunchAll).map(g=>{s.resetAllTerminals(g.id);let f=s.resolveForLaunch(g,o.rootDirectory);return{area:g,resolved:f}});if(u.length===0){s.resetAllTerminals(c.id);let g=s.resolveForLaunch(c,o.rootDirectory);u.push({area:c,resolved:g})}let p=u.find(g=>g.area.id===c.id)??u[0],m=new Map(p.area.terminals.map(g=>[g.id,g.color||"default"]));return e.respond({ok:!0,terminals:p.resolved.map(g=>({id:g.id,label:g.label,cwd:g.cwd,position:g.position,color:m.get(g.id)||"default"}))}),(async()=>{let g=[];await Promise.all(u.map(async({area:f,resolved:h})=>{try{let w=f.trigger;if(w){let T=w.timeoutMs??12e4;w.type==="delay"?await new Promise(E=>setTimeout(E,w.delayMs??0)):w.type==="waitForOutput"&&w.dependsOnTerminalId&&w.waitForText?await Le(n,w.dependsOnTerminalId,w.waitForText,T):w.type==="waitForExit"&&w.dependsOnTerminalId&&await Ms(n,w.dependsOnTerminalId,T)}await ae(h,e.services,f.id,{ignoreRunOnce:!0,completedStepsProvider:T=>s.getCompletedSteps(T),onStepCompleted:(T,E)=>{s.markStepCompleted(T,E)}}),s.setRunning(f.id,!0),e.services.broadcast("area.status",{id:f.id,workspaceId:t.id,state:"running"});for(let T of h)g.push(T.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"}),g.length>0&&i.startMonitoring(t.id,g).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 Bs(){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 ae(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 Ws(){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 mr,writeFile as Mt,cp as Fi}from"node:fs/promises";import{basename as $i,join as ee,resolve as Bi}from"node:path";var Me=class{async buildContext(e){let{task:t,agent:r,swarm:s,knowledgeEntries:n,dependencyTasks:i,workspaceDir:o}=e,c=ee(o,".swarm","tasks",t.id);await mr(c,{recursive:!0});let l=this.assemblePrompt(t,r,n,i),d=ee(c,"CLAUDE.md"),u=this.generateClaudeMd(t,r,s);await Mt(d,u,"utf-8");let p=this.generateTaskMd(t,i);if(await Mt(ee(c,"TASK.md"),p,"utf-8"),s?.knowledge&&s.knowledge.length>0){let m=ee(c,"knowledge");await mr(m,{recursive:!0});for(let g of s.knowledge)try{let f=$i(g.name),h=Bi(g.path),w=ee(m,f);await Fi(h,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(`
302
302
  `)}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(`
303
- `)}async buildStandaloneContext(e){let{task:t,prompt:r,workspaceDir:s}=e,n=ee(s,".swarm","tasks",t.id);await pr(n,{recursive:!0});let i=this.generateTaskMd(t);await Mt(ee(n,"TASK.md"),i,"utf-8");let o=ee(n,"CLAUDE.md"),c=[`# Task: ${t.title}`,"","## Mission",r,"","## Current Task",`- **ID:** ${t.id}`,`- **Title:** ${t.title}`,`- **Approval Mode:** ${t.approvalMode}`,""].join(`
303
+ `)}async buildStandaloneContext(e){let{task:t,prompt:r,workspaceDir:s}=e,n=ee(s,".swarm","tasks",t.id);await mr(n,{recursive:!0});let i=this.generateTaskMd(t);await Mt(ee(n,"TASK.md"),i,"utf-8");let o=ee(n,"CLAUDE.md"),c=[`# Task: ${t.title}`,"","## Mission",r,"","## Current Task",`- **ID:** ${t.id}`,`- **Title:** ${t.title}`,`- **Approval Mode:** ${t.approvalMode}`,""].join(`
304
304
  `);return await Mt(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(`
305
- `)}};function Ws(){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 x=c.workspaceId?n.get(c.workspaceId):null,R=t.workspaceDir||x?.rootDirectory||process.cwd(),F=[];for(let ne=0;ne<t.terminals.length;ne++){let I=t.terminals[ne],H=`task-${c.id}-${ne}-${Date.now()}`,G;if(I.command)G=I.command;else if(I.cli){let X=await new Me().buildStandaloneContext({task:c,cli:I.cli,prompt:I.prompt,workspaceDir:R}),Q=o.get(I.cli);G=Q?Q.buildCommand({mission:X.prompt,cwd:"",autoApprove:I.autoApprove??!1}):I.cli,I.cli==="claude"&&G.startsWith("claude")&&(G=G.replace(/^claude/,"claude -p"))}else G="bash";if(await s.open({id:H,cwd:R,command:G,env:t.env,cols:120,rows:30}),I.command){let be=I.promptDelay??3e3;if(I.commandSequence&&I.commandSequence.length>0){let X=0;for(let Q of I.commandSequence)X+=Q.delay,setTimeout(()=>{s.write(H,Q.command+"\r")},X);I.prompt&&setTimeout(()=>{s.write(H,I.prompt+"\r")},X+be)}else I.prompt&&setTimeout(()=>{s.write(H,I.prompt+"\r")},be)}let Ft=I.cli||I.command||"shell";r.addTerminal(c.id,H,Ft,I.prompt,I.autoApprove??!1),F.push(H)}return r.move(c.id,"running"),{taskId:c.id,terminalIds:F,workDir:R}}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(x=>x.id===l);if(!u)return e.respondError(`Agent ${l} not found in swarm`),null;let m=t.includeKnowledge!==!1?d.knowledge:void 0,g;t.includeDependencies&&c.dependencies.length>0&&(g=c.dependencies.map(x=>r.get(x)).filter(x=>x!==null));let h=await new Me().buildContext({task:c,agent:u,swarm:d,knowledgeEntries:m,dependencyTasks:g,workspaceDir:d.directory}),w=o.get(u.cli),T=w?w.buildCommand({mission:h.prompt,cwd:"",autoApprove:u.autoApprove||d.autoApprove}):u.cli,E=`task-${c.id}-${l.slice(0,8)}`,U=u.worktreePath||d.directory;return await s.open({id:E,cwd:U,command:T,env:t.env,cols:120,rows:30}),r.update(c.id,{}),r.move(c.id,"running"),r.updateTerminalId(c.id,E),{terminalId:E,terminalIds:[E],taskId:c.id,agentId:l,workDir:d.directory,cwd:U}},"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 qs(){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 Hs(){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 Xs(){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 js(){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 Ks(){return{"browser.session.open":async(a,e)=>{let t=a;return await e.services.browserManager.openSession(t.url)},"browser.session.close":async(a,e)=>{let t=a;return await e.services.browserManager.closeSession(t.sessionId),{ok:!0}},"browser.tab.open":async(a,e)=>{let t=a;return await e.services.browserManager.openTab(t.sessionId,t.url)},"browser.tab.close":async(a,e)=>{let t=a;return await e.services.browserManager.closeTab(t.sessionId,t.tabId),{ok:!0}},"browser.tab.navigate":async(a,e)=>{let t=a;return await e.services.browserManager.navigateTab(t.sessionId,t.tabId,t.url),{ok:!0}},"browser.tab.activate":async(a,e)=>{let t=a;return await e.services.browserManager.activateTab(t.sessionId,t.tabId),{ok:!0}},"browser.tab.back":async(a,e)=>{let t=a;return await e.services.browserManager.goBack(t.sessionId,t.tabId),{ok:!0}},"browser.tab.forward":async(a,e)=>{let t=a;return await e.services.browserManager.goForward(t.sessionId,t.tabId),{ok:!0}},"browser.tab.refresh":async(a,e)=>{let t=a;return await e.services.browserManager.refresh(t.sessionId,t.tabId),{ok:!0}},"browser.input":async(a,e)=>{let t=a;return await e.services.browserManager.sendInput(t.sessionId,t.tabId,t.event),{ok:!0}},"browser.screencast.ack":async(a,e)=>{let t=a;return await e.services.browserManager.ackFrame(t.sessionId,t.tabId,t.frameNumber),{ok:!0}}}}import*as te from"node:fs";import*as Ot from"node:os";import*as P from"node:path";import Gs from"node:fs";import Ys from"node:path";import{spawn as Bi}from"node:child_process";var Wi={"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"},mr=class{detectInstalledEditors(){let e=new Set,t=(process.env.PATH||"").split(Ys.delimiter),r=process.platform==="darwin";for(let s of ar){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(Gs.existsSync(Ys.join(n,s.command))){e.add(s.id);break}}catch{}}if(r)try{let s=Gs.readdirSync("/Applications");for(let n of s){let i=Wi[n];i&&!e.has(i)&&e.add(i)}}catch{}return Array.from(e)}openInEditor(e,t){try{let r=ar.find(o=>o.id===e);if(!r)return{ok:!1,error:`Unknown editor: ${e}`};let s,n;return e==="finder"?process.platform==="win32"?(s="explorer",n=[t]):process.platform==="linux"?(s="xdg-open",n=[t]):(s="open",n=[t]):e==="terminal"?process.platform==="win32"?(s="cmd",n=["/c","start","cmd","/k",`cd /d "${t}"`]):process.platform==="linux"?(s="xdg-open",n=[t]):(s="open",n=["-a","Terminal",t]):(s=r.command,n=[t]),Bi(s,n,{detached:!0,stdio:"ignore"}).unref(),{ok:!0}}catch(r){return{ok:!1,error:r instanceof Error?r.message:String(r)}}}},gr=new mr;function Vs(){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=Ot.homedir(),r=e.path||t;r==="~"?r=t:r.startsWith("~/")&&(r=P.join(t,r.slice(2))),r=P.resolve(r);try{let s=te.readdirSync(r),n=[];for(let i of s){if(!e.showHidden&&i.startsWith("."))continue;let o=P.join(r,i);try{te.statSync(o).isDirectory()&&n.push({name:i,path:o})}catch{}}return n.sort((i,o)=>i.name.localeCompare(o.name)),{current:r,parent:P.dirname(r),home:t,dirs:n}}catch(s){return{current:r,parent:P.dirname(r),home:t,dirs:[],error:s.message}}},"system.createDir":a=>{let t=a.path,r=Ot.homedir();t.startsWith("~/")&&(t=P.join(r,t.slice(2))),t=P.resolve(t);try{return te.mkdirSync(t,{recursive:!0}),{ok:!0,path:t}}catch(s){return{ok:!1,error:s.message}}},"system.homeDir":()=>{let a=Ot.homedir(),e=[{name:"Home",path:a},{name:"Desktop",path:P.join(a,"Desktop")},{name:"Documents",path:P.join(a,"Documents")},{name:"Downloads",path:P.join(a,"Downloads")},{name:"Development",path:P.join(a,"Development")},{name:"Development",path:P.join(a,"Documents","Development")},{name:"Projects",path:P.join(a,"Projects")},{name:"/",path:"/"}],t=[],r=new Set;for(let s of e){if(r.has(s.name)){if(!t.find(n=>n.name===s.name))try{te.statSync(s.path),t.push(s),r.add(s.name)}catch{}continue}try{te.statSync(s.path),t.push(s),r.add(s.name)}catch{}}return t.find(s=>s.path==="/")||t.push({name:"/",path:"/"}),{home:a,shortcuts:t}},"system.detect-clis":async(a,e)=>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:gr.detectInstalledEditors()}),"ide.open":a=>{let e=a;return gr.openInEditor(e.editor,e.cwd)},ping:()=>({ok:!0,ts:Date.now()})}}function zs(){return{"wireframe.list":(a,e)=>{let t=a;return e.services.wireframeManager.list(t.projectDir)},"wireframe.get":(a,e)=>{let t=a;return e.services.wireframeManager.get(t.projectDir,t.id)},"wireframe.create":(a,e)=>{let t=a;return e.services.wireframeManager.create(t.projectDir,{name:t.name,content:t.content,description:t.description})},"wireframe.update":(a,e)=>{let t=a;return e.services.wireframeManager.update(t.projectDir,t.id,t.content)},"wireframe.delete":(a,e)=>{let t=a;return e.services.wireframeManager.delete(t.projectDir,t.id),{ok:!0}},"wireframe.generate":(a,e)=>{let t=a;return e.services.wireframeManager.generate(t.projectDir,t.id,t.description)},"template.list":(a,e)=>e.services.templateManager.list(),"template.create":(a,e)=>{let t=a;return e.services.templateManager.create(t)},"template.update":(a,e)=>{let t=a;return e.services.templateManager.update(t)},"template.delete":(a,e)=>{let t=a;return{deleted:e.services.templateManager.delete(t.id)}},"promptTemplate.list":(a,e)=>e.services.promptTemplateManager.list(),"promptTemplate.create":(a,e)=>{let t=a;return e.services.promptTemplateManager.create(t)},"promptTemplate.update":(a,e)=>{let t=a;return e.services.promptTemplateManager.update(t)},"promptTemplate.delete":(a,e)=>{let t=a;return{deleted:e.services.promptTemplateManager.delete(t.id)}},"workspaceTemplate.list":(a,e)=>e.services.workspaceTemplateManager.list(),"workspaceTemplate.create":(a,e)=>{let t=a;return e.services.workspaceTemplateManager.create(t)},"workspaceTemplate.update":(a,e)=>{let t=a;return e.services.workspaceTemplateManager.update(t)},"workspaceTemplate.delete":(a,e)=>{let t=a;return{deleted:e.services.workspaceTemplateManager.delete(t.id)}},"stack.list":(a,e)=>e.services.stackManager.list(),"stack.create":(a,e)=>{let t=a;return e.services.stackManager.create(t)},"stack.update":(a,e)=>{let t=a;return e.services.stackManager.update(t)},"stack.delete":(a,e)=>{let t=a;return{deleted:e.services.stackManager.delete(t.id)}},"stack.apply":async(a,e)=>{let t=a,{services:r}=e,s=r.stackManager.get(t.stackId);if(!s)throw new Error(`Stack not found: ${t.stackId}`);let n=r.workspaceManager.create({name:t.workspaceName,color:t.workspaceColor,rootDirectory:t.rootDirectory,initGit:t.initGit,terminalCount:1,stackId:s.id}),i=r.areaManager.getDefaultArea(n.id);if(!i)throw new Error("Default area not created for workspace");return e.respond({workspace:n,areaId:i.id}),r.stackOrchestrator.applyStack({stack:s,workspaceId:n.id,defaultAreaId:i.id,broadcast:r.broadcast},r).catch(o=>{console.error("[stack.apply] Orchestration error:",o)}),null},"layout.list":(a,e)=>{let t=a;return e.services.layoutManager.list(t.workspaceId,t.areaId)},"layout.save":(a,e)=>{let t=a;return e.services.layoutManager.save(t)},"layout.update":(a,e)=>{let t=a;return e.services.layoutManager.update(t.id,t)},"layout.delete":(a,e)=>{let t=a;return{ok:e.services.layoutManager.delete(t.id)}},"layout.setDefault":(a,e)=>{let t=a;return e.services.layoutManager.setDefault(t.workspaceId,t.layoutId,t.areaId),{ok:!0}}}}import{readdir as Qs,stat as Oe,readFile as Nt,writeFile as hr,mkdir as Ne,access as Zs,rm as qi,rename as Hi}from"node:fs/promises";import{join as Dt,resolve as L,relative as Xi,dirname as en,sep as re}from"node:path";function tn(){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 Qs(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 g=Dt(u,m.name);if(m.isDirectory())await d(g);else if(m.isFile()){let f="."+(m.name.split(".").pop()?.toLowerCase()||"");if(i.has(f))continue;let h=Xi(s,g);if(c&&!h.toLowerCase().includes(c)&&!m.name.toLowerCase().includes(c))continue;try{let w=await Oe(g);l.push({path:h,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)+re)&&i!==L(s))return e.respondError("Path traversal not allowed"),null;try{let o=await Oe(i),c=rr(i),l=nr(i),u=l?10485760:n;return o.size>u?(e.respondError(`File too large: ${o.size} bytes (max ${u})`),null):l?{content:(await Nt(i)).toString("base64"),language:c,size:o.size,path:t.filePath,encoding:"base64",mimeType:sr(i)}:{content:await Nt(i,"utf-8"),language:c,size:o.size,path:t.filePath,encoding:"utf-8",mimeType:sr(i)}}catch(o){let c=o instanceof Error?o.message:"Failed to read file";return e.respondError(c),null}},"workspace.file.tree":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=t.path??".",i=t.depth??3,o=L(s,n);if(!o.startsWith(L(s)+re)&&o!==L(s))return e.respondError("Path traversal not allowed"),null;let c=new Set(["node_modules",".git","dist","build","coverage",".next","__pycache__",".cache",".turbo",".DS_Store"]);async function l(d,u,p){if(p<=0)return[];let m;try{m=await Qs(d,{withFileTypes:!0})}catch{return[]}let g=[],f=[],h=[];for(let w of m)c.has(w.name)||w.isSymbolicLink()||(w.isDirectory()?f.push(w):w.isFile()&&h.push(w));f.sort((w,T)=>w.name.toLowerCase().localeCompare(T.name.toLowerCase())),h.sort((w,T)=>w.name.toLowerCase().localeCompare(T.name.toLowerCase()));for(let w of[...f,...h]){let T=Dt(d,w.name),E=u?`${u}/${w.name}`:w.name;if(w.isDirectory()){let U=await l(T,E,p-1);g.push({name:w.name,path:E,type:"directory",children:U})}else{let U;try{U=(await Oe(T)).size}catch{}g.push({name:w.name,path:E,type:"file",size:U})}}return g}try{let d=n==="."?"":n.replace(/^\/+/,"");return{entries:await l(o,d,i)}}catch(d){let u=d instanceof Error?d.message:"Failed to read directory";return e.respondError(u),null}},"workspace.file.write":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=L(s,t.filePath);if(!n.startsWith(L(s)+re)&&n!==L(s))return e.respondError("Path traversal not allowed"),null;let i=5242880;if(t.content.length>i)return e.respondError(`Content too large: ${t.content.length} bytes (max ${i})`),null;try{let o=Dt(n,"..");return await Ne(o,{recursive:!0}),await hr(n,t.content,"utf-8"),{ok:!0,size:t.content.length,path:t.filePath}}catch(o){let c=o instanceof Error?o.message:"Failed to write file";return e.respondError(c),null}},"workspace.file.upload":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;if(t.encoding!=="base64")return e.respondError("Only base64 encoding is supported for uploads"),null;let s=r.rootDirectory,n=L(s,t.filePath);if(!n.startsWith(L(s)+re)&&n!==L(s))return e.respondError("Path traversal not allowed"),null;let i;try{i=Buffer.from(t.content,"base64")}catch{return e.respondError("Invalid base64 content"),null}if(i.length>52428800)return e.respondError(`File too large: ${i.length} bytes (max ${52428800})`),null;if(!t.overwrite)try{return await Zs(n),e.respondError(`File already exists: ${t.filePath}`),null}catch{}try{let o=Dt(n,"..");return await Ne(o,{recursive:!0}),await hr(n,i),{ok:!0,size:i.length,path:t.filePath}}catch(o){let c=o instanceof Error?o.message:"Failed to upload file";return e.respondError(c),null}},"workspace.file.delete":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=L(s,t.filePath),i=L(s);if(!n.startsWith(i+re))return e.respondError("Path traversal not allowed"),null;if(n===i)return e.respondError("Cannot delete workspace root"),null;let o;try{o=(await Oe(n)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.filePath}`),null}let c=t.recursive??!0,l,d;if(o==="file")try{nr(n)?(l=(await Nt(n)).toString("base64"),d="base64"):(l=await Nt(n,"utf-8"),d="utf-8")}catch{}try{return await qi(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+re)||!o.startsWith(n+re))return e.respondError("Path traversal not allowed"),null;let c;try{c=(await Oe(i)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.sourcePath}`),null}try{let l=en(o);return await Ne(l,{recursive:!0}),await Hi(i,o),{ok:!0,sourcePath:t.sourcePath,destinationPath:t.destinationPath,type:c}}catch(l){let d=l instanceof Error?l.message:"Failed to move";return e.respondError(d),null}},"workspace.file.create":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=L(s,t.filePath),i=L(s);if(!n.startsWith(i+re))return e.respondError("Path traversal not allowed"),null;try{return await Zs(n),e.respondError(`Already exists: ${t.filePath}`),null}catch{}try{if(t.type==="directory")await Ne(n,{recursive:!0});else{let o=en(n);await Ne(o,{recursive:!0}),await hr(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 rn(){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 sn(){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 nn(){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 an(){return{"skillStore.list":(a,e)=>e.services.skillStoreManager.list(),"skillStore.get":(a,e)=>{let t=a;return e.services.skillStoreManager.get(t.id)},"skillStore.save":(a,e)=>{let t=a;return e.services.skillStoreManager.save(t)},"skillStore.update":(a,e)=>{let t=a;return e.services.skillStoreManager.update(t)},"skillStore.delete":(a,e)=>{let t=a;return e.services.skillStoreManager.delete(t.id)},"skillStore.saveFile":(a,e)=>{let t=a;return e.services.skillStoreManager.saveFile(t.id,t.content)},"skillStore.readFile":(a,e)=>{let t=a;return e.services.skillStoreManager.readFile(t.id)},"skillStore.openFolder":(a,e)=>{let t=a;return e.services.skillStoreManager.openFolder(t.id)},"skillStore.duplicate":(a,e)=>{let t=a;return e.services.skillStoreManager.duplicate(t.id,t.newName)},"skillStore.merge":(a,e)=>{let t=a;return e.services.skillStoreManager.merge(t.skillIds,t.name,t.displayName,t.description)},"skillStore.browseRemote":(a,e)=>e.services.skillStoreManager.browseRemote(a),"skillStore.fetchContent":(a,e)=>{let t=a;return e.services.skillStoreManager.fetchRemoteContent(t.owner,t.repo,t.skillId)},"skillStore.listFiles":(a,e)=>{let t=a;return e.services.skillStoreManager.listSkillFiles(t.id)},"skillStore.readSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.readSkillFile(t.id,t.relativePath)},"skillStore.writeSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.writeSkillFile(t.id,t.relativePath,t.content)},"skillStore.deleteSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.deleteSkillFile(t.id,t.relativePath)},"skillStore.createSkillFolder":(a,e)=>{let t=a;return e.services.skillStoreManager.createSkillFolder(t.id,t.relativePath)},"skillStore.renameSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.renameSkillFile(t.id,t.oldPath,t.newPath)}}}function on(){return{...Us(),...Fs(),...$s(),...Bs(),...Ws(),...qs(),...Hs(),...Xs(),...js(),...Ks(),...Vs(),...zs(),...tn(),...rn(),...sn(),...nn(),...an()}}var Gi=new Set(["127.0.0.1","::1","::ffff:127.0.0.1","localhost"]);function Yi(a){let e=a.socket.remoteAddress;return e?Gi.has(e):!1}function Vi(a){try{return new URL(a.url||"/",`http://${a.headers.host||"localhost"}`).searchParams.get("token")}catch{return null}}function cn(a,e){let t={fn:()=>{}},r={mgr:null},s=new pt((y,k)=>t.fn(y,k)),n=new ji({server:a,path:"/ws",verifyClient:(y,k)=>{if(Yi(y.req)){k(!0);return}if(s.isActive()){let M=Vi(y.req);s.validateToken(M)?k(!0):k(!1,401,"Unauthorized: invalid or missing token");return}k(!1,403,"Remote connections not allowed without tunnel")}}),i=[],o=new Set,c=new WeakMap,l,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),Cr.dispose()});function p(y,k){let $=JSON.stringify({type:"push",channel:y,data:k});for(let v of o)v.readyState===Ki.OPEN&&v.send($);for(let v of i)try{v($)}catch{}if(y==="terminal.output"){let v=k;x.onTerminalOutput(v.id,v.data)}if(y==="terminal.exited"){let v=k,C=F.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let{allDone:j,hasError:Y}=F.markTerminalExited(C.id,v.id,v.exitCode);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:v.exitCode,allDone:j}),j){let ue=Y?"blocked":"waiting";F.move(C.id,ue)}}}if(y==="ports.update"&&r.mgr)try{let v=k;r.mgr.cleanupStaleTunnels(v.ports.map(C=>C.port))}catch(v){console.error("[PortTunnelManager] cleanup error:",v)}if(y==="terminal.process"){let v=k;if(v.process.isIdle){let C=F.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let Y=F.getTaskTerminals(C.id).find(ue=>ue.terminalId===v.id);if(Y&&Y.status==="running"){let{allDone:ue,hasError:In}=F.markTerminalExited(C.id,v.id,0);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:0,allDone:ue}),ue){let Rn=In?"blocked":"waiting";F.move(C.id,Rn)}}}}}}e.prepare("UPDATE workspace_state SET isRunning = 0").run(),e.prepare("UPDATE area_state SET isRunning = 0").run();let m=new We(p),g=e.prepare("SELECT id FROM terminal_configs").all(),f=new Set(g.map(y=>y.id));try{let y=e.prepare("SELECT data FROM area_runtime_state").all();for(let k of y){let M=JSON.parse(k.data);if(M.terminals)for(let $ of M.terminals)f.add($.id)}}catch{}let h=m.recoverSessions(f);if(h.length>0){let y=e.prepare("SELECT workspaceId, areaId FROM terminal_configs WHERE id = ?"),k=e.prepare("INSERT INTO workspace_state (workspaceId, isRunning) VALUES (?, 1) ON CONFLICT(workspaceId) DO UPDATE SET isRunning = 1"),M=e.prepare("INSERT INTO area_state (areaId, isRunning) VALUES (?, 1) ON CONFLICT(areaId) DO UPDATE SET isRunning = 1"),$=new Map;try{let v=e.prepare("SELECT areaId, data FROM area_runtime_state").all();for(let C of v){let j=JSON.parse(C.data);if(j.terminals)for(let Y of j.terminals)$.set(Y.id,C.areaId)}}catch{}for(let v of h){let C=y.get(v);if(C)k.run(C.workspaceId),C.areaId&&M.run(C.areaId);else{let j=$.get(v);if(j){let Y=e.prepare("SELECT workspaceId FROM areas WHERE id = ?").get(j);Y&&(k.run(Y.workspaceId),M.run(j))}}}console.log("[server] Restored running state for workspaces with recovered terminals")}let w=new He(e),T=new qe(e,w),E=new tt,U=new ot(e),de=new ct(e),x=new Qe(e,m,p,E),R=new Ze,F=new et(e,p),Ir=new at(p),ne=new dt(p),I=new ut(p,y=>{let k=m.getProcessInfo(y);return k&&k.pid>0?k.pid:null});t.fn=p;let H=new mt((y,k)=>t.fn(y,k));r.mgr=H;let G=new ft(p),Ft=new wt(e),be=new Tt(e),X=new Et(e);X.seed();let Q=new yt(e);Q.seed(X);let Rr=new vt({terminalManager:m,areaManager:w,workspaceTemplateManager:X,workspaceManager:T}),yn=new St(e),Ar=new bt(p),Cr=new kt((y,k)=>{if(p(y,k),y==="notification.new"){let M=k;Ar.add(M.type,M.title,M.message,M.source)}}),vn=new It,kn=new Rt(e),bn=new Lt(e);x.setTaskManager(F),x.setSettingsManager(U);let Lr={terminalManager:m,workspaceManager:T,areaManager:w,swarmManager:x,skillsRegistry:R,taskManager:F,providerRegistry:E,prdBuilder:Ir,settingsManager:U,cliToolsManager:de,browserManager:ne,tunnel:s,portTunnelManager:H,wireframeManager:G,templateManager:Ft,promptTemplateManager:be,workspaceTemplateManager:X,stackManager:Q,stackOrchestrator:Rr,layoutManager:yn,healthCheckService:Cr,notificationService:Ar,portMonitor:I,gitManager:vn,gitHubCliManager:kn,relayClient:null,skillStoreManager:bn,broadcast:p},Mr=on();return n.on("connection",(y,k)=>{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",$=>{let v;try{v=JSON.parse($.toString())}catch{return}fr(v,y,Lr,Mr)}),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"),ne.stopAll(),I.dispose(),H.stopAll(),l=void 0},3e4);let $=m.useTmux?1440*60*1e3:14400*1e3;d=setTimeout(()=>{let v=$/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},$)}})}),{wss:n,terminalManager:m,workspaceManager:T,swarmManager:x,settingsManager:U,broadcast:p,externalSenders:i,services:Lr,routes:Mr,getClientCount:()=>o.size}}async function fr(a,e,t,r){let{id:s,method:n,params:i}=a,o=r[n];if(!o){Se(e,{id:s,error:{message:`Unknown method: ${n}`}});return}let c=!1,l={ws:e,id:s,services:t,respond:d=>{c=!0,Se(e,{id:s,result:d})},respondError:d=>{c=!0,Se(e,{id:s,error:{message:d}})}};try{let d=await o(i,l);!c&&d!==null&&d!==void 0&&Se(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";Se(e,{id:s,error:{message:u}})}}}import{DatabaseSync as zi}from"node:sqlite";import{mkdirSync as Ji,existsSync as Qi}from"node:fs";import{join as ln}from"node:path";import{homedir as Zi}from"node:os";import{randomUUID as eo}from"node:crypto";var wr=ln(Zi(),".impactus-swarm"),to=ln(wr,"swarm.db");function dn(){Qi(wr)||Ji(wr,{recursive:!0});let a=new zi(to);a.exec("PRAGMA journal_mode = WAL"),a.exec("PRAGMA foreign_keys = ON"),a.exec(`
305
+ `)}};function qs(){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 x=c.workspaceId?n.get(c.workspaceId):null,R=t.workspaceDir||x?.rootDirectory||process.cwd(),F=[];for(let ne=0;ne<t.terminals.length;ne++){let I=t.terminals[ne],H=`task-${c.id}-${ne}-${Date.now()}`,G;if(I.command)G=I.command;else if(I.cli){let X=await new Me().buildStandaloneContext({task:c,cli:I.cli,prompt:I.prompt,workspaceDir:R}),Q=o.get(I.cli);G=Q?Q.buildCommand({mission:X.prompt,cwd:"",autoApprove:I.autoApprove??!1}):I.cli,I.cli==="claude"&&G.startsWith("claude")&&(G=G.replace(/^claude/,"claude -p"))}else G="bash";if(await s.open({id:H,cwd:R,command:G,env:t.env,cols:120,rows:30}),I.command){let be=I.promptDelay??3e3;if(I.commandSequence&&I.commandSequence.length>0){let X=0;for(let Q of I.commandSequence)X+=Q.delay,setTimeout(()=>{s.write(H,Q.command+"\r")},X);I.prompt&&setTimeout(()=>{s.write(H,I.prompt+"\r")},X+be)}else I.prompt&&setTimeout(()=>{s.write(H,I.prompt+"\r")},be)}let Ft=I.cli||I.command||"shell";r.addTerminal(c.id,H,Ft,I.prompt,I.autoApprove??!1),F.push(H)}return r.move(c.id,"running"),{taskId:c.id,terminalIds:F,workDir:R}}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(x=>x.id===l);if(!u)return e.respondError(`Agent ${l} not found in swarm`),null;let m=t.includeKnowledge!==!1?d.knowledge:void 0,g;t.includeDependencies&&c.dependencies.length>0&&(g=c.dependencies.map(x=>r.get(x)).filter(x=>x!==null));let h=await new Me().buildContext({task:c,agent:u,swarm:d,knowledgeEntries:m,dependencyTasks:g,workspaceDir:d.directory}),w=o.get(u.cli),T=w?w.buildCommand({mission:h.prompt,cwd:"",autoApprove:u.autoApprove||d.autoApprove}):u.cli,E=`task-${c.id}-${l.slice(0,8)}`,U=u.worktreePath||d.directory;return await s.open({id:E,cwd:U,command:T,env:t.env,cols:120,rows:30}),r.update(c.id,{}),r.move(c.id,"running"),r.updateTerminalId(c.id,E),{terminalId:E,terminalIds:[E],taskId:c.id,agentId:l,workDir:d.directory,cwd:U}},"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 Hs(){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 Xs(){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 js(){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 Ks(){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 Gs(){return{"browser.session.open":async(a,e)=>{let t=a;return await e.services.browserManager.openSession(t.url)},"browser.session.close":async(a,e)=>{let t=a;return await e.services.browserManager.closeSession(t.sessionId),{ok:!0}},"browser.tab.open":async(a,e)=>{let t=a;return await e.services.browserManager.openTab(t.sessionId,t.url)},"browser.tab.close":async(a,e)=>{let t=a;return await e.services.browserManager.closeTab(t.sessionId,t.tabId),{ok:!0}},"browser.tab.navigate":async(a,e)=>{let t=a;return await e.services.browserManager.navigateTab(t.sessionId,t.tabId,t.url),{ok:!0}},"browser.tab.activate":async(a,e)=>{let t=a;return await e.services.browserManager.activateTab(t.sessionId,t.tabId),{ok:!0}},"browser.tab.back":async(a,e)=>{let t=a;return await e.services.browserManager.goBack(t.sessionId,t.tabId),{ok:!0}},"browser.tab.forward":async(a,e)=>{let t=a;return await e.services.browserManager.goForward(t.sessionId,t.tabId),{ok:!0}},"browser.tab.refresh":async(a,e)=>{let t=a;return await e.services.browserManager.refresh(t.sessionId,t.tabId),{ok:!0}},"browser.input":async(a,e)=>{let t=a;return await e.services.browserManager.sendInput(t.sessionId,t.tabId,t.event),{ok:!0}},"browser.screencast.ack":async(a,e)=>{let t=a;return await e.services.browserManager.ackFrame(t.sessionId,t.tabId,t.frameNumber),{ok:!0}}}}import*as te from"node:fs";import*as Ot from"node:os";import*as P from"node:path";import Ys from"node:fs";import Vs from"node:path";import{spawn as Wi}from"node:child_process";var qi={"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"},gr=class{detectInstalledEditors(){let e=new Set,t=(process.env.PATH||"").split(Vs.delimiter),r=process.platform==="darwin";for(let s of ar){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(Ys.existsSync(Vs.join(n,s.command))){e.add(s.id);break}}catch{}}if(r)try{let s=Ys.readdirSync("/Applications");for(let n of s){let i=qi[n];i&&!e.has(i)&&e.add(i)}}catch{}return Array.from(e)}openInEditor(e,t){try{let r=ar.find(o=>o.id===e);if(!r)return{ok:!1,error:`Unknown editor: ${e}`};let s,n;return e==="finder"?process.platform==="win32"?(s="explorer",n=[t]):process.platform==="linux"?(s="xdg-open",n=[t]):(s="open",n=[t]):e==="terminal"?process.platform==="win32"?(s="cmd",n=["/c","start","cmd","/k",`cd /d "${t}"`]):process.platform==="linux"?(s="xdg-open",n=[t]):(s="open",n=["-a","Terminal",t]):(s=r.command,n=[t]),Wi(s,n,{detached:!0,stdio:"ignore"}).unref(),{ok:!0}}catch(r){return{ok:!1,error:r instanceof Error?r.message:String(r)}}}},hr=new gr;function zs(){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=Ot.homedir(),r=e.path||t;r==="~"?r=t:r.startsWith("~/")&&(r=P.join(t,r.slice(2))),r=P.resolve(r);try{let s=te.readdirSync(r),n=[];for(let i of s){if(!e.showHidden&&i.startsWith("."))continue;let o=P.join(r,i);try{te.statSync(o).isDirectory()&&n.push({name:i,path:o})}catch{}}return n.sort((i,o)=>i.name.localeCompare(o.name)),{current:r,parent:P.dirname(r),home:t,dirs:n}}catch(s){return{current:r,parent:P.dirname(r),home:t,dirs:[],error:s.message}}},"system.createDir":a=>{let t=a.path,r=Ot.homedir();t.startsWith("~/")&&(t=P.join(r,t.slice(2))),t=P.resolve(t);try{return te.mkdirSync(t,{recursive:!0}),{ok:!0,path:t}}catch(s){return{ok:!1,error:s.message}}},"system.homeDir":()=>{let a=Ot.homedir(),e=[{name:"Home",path:a},{name:"Desktop",path:P.join(a,"Desktop")},{name:"Documents",path:P.join(a,"Documents")},{name:"Downloads",path:P.join(a,"Downloads")},{name:"Development",path:P.join(a,"Development")},{name:"Development",path:P.join(a,"Documents","Development")},{name:"Projects",path:P.join(a,"Projects")},{name:"/",path:"/"}],t=[],r=new Set;for(let s of e){if(r.has(s.name)){if(!t.find(n=>n.name===s.name))try{te.statSync(s.path),t.push(s),r.add(s.name)}catch{}continue}try{te.statSync(s.path),t.push(s),r.add(s.name)}catch{}}return t.find(s=>s.path==="/")||t.push({name:"/",path:"/"}),{home:a,shortcuts:t}},"system.detect-clis":async(a,e)=>{let t=new Map,r=e.services.settingsManager.list();for(let s of r){let n=s.key.match(/^providers\.(.+)\.config$/);if(n)try{let i=JSON.parse(s.value);t.set(n[1],i)}catch{}}return e.services.providerRegistry.setCustomConfigs(t),await e.services.providerRegistry.detectInstalled()},"system.update-provider-config":(a,e)=>{let t=a,r=JSON.stringify({...t.customPath!==void 0?{path:t.customPath}:{},...t.startupCommand!==void 0?{startupCommand:t.startupCommand}:{}});e.services.settingsManager.set({key:`providers.${t.cli}.config`,value:r,category:"general",label:`Provider config for ${t.cli}`});let s=new Map,n=e.services.settingsManager.list();for(let i of n){let o=i.key.match(/^providers\.(.+)\.config$/);if(o)try{let c=JSON.parse(i.value);s.set(o[1],c)}catch{}}return e.services.providerRegistry.setCustomConfigs(s),{ok:!0}},"system.load-provider-configs":(a,e)=>{let t={},r=e.services.settingsManager.list();for(let s of r){let n=s.key.match(/^providers\.(.+)\.config$/);if(n)try{let i=JSON.parse(s.value);t[n[1]]=i}catch{}}return{configs:t}},"system.health-check":async(a,e)=>{let t=a;return t?.cli?{providers:[await e.services.healthCheckService.checkOne(t.cli)],checkedAt:new Date().toISOString()}:await e.services.healthCheckService.checkAll()},"notifications.list":(a,e)=>e.services.notificationService.list(),"notifications.clear":(a,e)=>{let t=a;return e.services.notificationService.clear(t?.id),{ok:!0}},"notifications.mark-read":(a,e)=>{let t=a;return e.services.notificationService.markRead(t.id),{ok:!0}},"ide.list":()=>({editors:hr.detectInstalledEditors()}),"ide.open":a=>{let e=a;return hr.openInEditor(e.editor,e.cwd)},ping:()=>({ok:!0,ts:Date.now()})}}function Js(){return{"wireframe.list":(a,e)=>{let t=a;return e.services.wireframeManager.list(t.projectDir)},"wireframe.get":(a,e)=>{let t=a;return e.services.wireframeManager.get(t.projectDir,t.id)},"wireframe.create":(a,e)=>{let t=a;return e.services.wireframeManager.create(t.projectDir,{name:t.name,content:t.content,description:t.description})},"wireframe.update":(a,e)=>{let t=a;return e.services.wireframeManager.update(t.projectDir,t.id,t.content)},"wireframe.delete":(a,e)=>{let t=a;return e.services.wireframeManager.delete(t.projectDir,t.id),{ok:!0}},"wireframe.generate":(a,e)=>{let t=a;return e.services.wireframeManager.generate(t.projectDir,t.id,t.description)},"template.list":(a,e)=>e.services.templateManager.list(),"template.create":(a,e)=>{let t=a;return e.services.templateManager.create(t)},"template.update":(a,e)=>{let t=a;return e.services.templateManager.update(t)},"template.delete":(a,e)=>{let t=a;return{deleted:e.services.templateManager.delete(t.id)}},"promptTemplate.list":(a,e)=>e.services.promptTemplateManager.list(),"promptTemplate.create":(a,e)=>{let t=a;return e.services.promptTemplateManager.create(t)},"promptTemplate.update":(a,e)=>{let t=a;return e.services.promptTemplateManager.update(t)},"promptTemplate.delete":(a,e)=>{let t=a;return{deleted:e.services.promptTemplateManager.delete(t.id)}},"workspaceTemplate.list":(a,e)=>e.services.workspaceTemplateManager.list(),"workspaceTemplate.create":(a,e)=>{let t=a;return e.services.workspaceTemplateManager.create(t)},"workspaceTemplate.update":(a,e)=>{let t=a;return e.services.workspaceTemplateManager.update(t)},"workspaceTemplate.delete":(a,e)=>{let t=a;return{deleted:e.services.workspaceTemplateManager.delete(t.id)}},"stack.list":(a,e)=>e.services.stackManager.list(),"stack.create":(a,e)=>{let t=a;return e.services.stackManager.create(t)},"stack.update":(a,e)=>{let t=a;return e.services.stackManager.update(t)},"stack.delete":(a,e)=>{let t=a;return{deleted:e.services.stackManager.delete(t.id)}},"stack.apply":async(a,e)=>{let t=a,{services:r}=e,s=r.stackManager.get(t.stackId);if(!s)throw new Error(`Stack not found: ${t.stackId}`);let n=r.workspaceManager.create({name:t.workspaceName,color:t.workspaceColor,rootDirectory:t.rootDirectory,initGit:t.initGit,terminalCount:1,stackId:s.id}),i=r.areaManager.getDefaultArea(n.id);if(!i)throw new Error("Default area not created for workspace");return e.respond({workspace:n,areaId:i.id}),r.stackOrchestrator.applyStack({stack:s,workspaceId:n.id,defaultAreaId:i.id,broadcast:r.broadcast},r).catch(o=>{console.error("[stack.apply] Orchestration error:",o)}),null},"layout.list":(a,e)=>{let t=a;return e.services.layoutManager.list(t.workspaceId,t.areaId)},"layout.save":(a,e)=>{let t=a;return e.services.layoutManager.save(t)},"layout.update":(a,e)=>{let t=a;return e.services.layoutManager.update(t.id,t)},"layout.delete":(a,e)=>{let t=a;return{ok:e.services.layoutManager.delete(t.id)}},"layout.setDefault":(a,e)=>{let t=a;return e.services.layoutManager.setDefault(t.workspaceId,t.layoutId,t.areaId),{ok:!0}}}}import{readdir as Zs,stat as Oe,readFile as Nt,writeFile as fr,mkdir as Ne,access as en,rm as Hi,rename as Xi}from"node:fs/promises";import{join as Dt,resolve as L,relative as ji,dirname as tn,sep as re}from"node:path";function rn(){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 Zs(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 g=Dt(u,m.name);if(m.isDirectory())await d(g);else if(m.isFile()){let f="."+(m.name.split(".").pop()?.toLowerCase()||"");if(i.has(f))continue;let h=ji(s,g);if(c&&!h.toLowerCase().includes(c)&&!m.name.toLowerCase().includes(c))continue;try{let w=await Oe(g);l.push({path:h,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)+re)&&i!==L(s))return e.respondError("Path traversal not allowed"),null;try{let o=await Oe(i),c=rr(i),l=nr(i),u=l?10485760:n;return o.size>u?(e.respondError(`File too large: ${o.size} bytes (max ${u})`),null):l?{content:(await Nt(i)).toString("base64"),language:c,size:o.size,path:t.filePath,encoding:"base64",mimeType:sr(i)}:{content:await Nt(i,"utf-8"),language:c,size:o.size,path:t.filePath,encoding:"utf-8",mimeType:sr(i)}}catch(o){let c=o instanceof Error?o.message:"Failed to read file";return e.respondError(c),null}},"workspace.file.tree":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=t.path??".",i=t.depth??3,o=L(s,n);if(!o.startsWith(L(s)+re)&&o!==L(s))return e.respondError("Path traversal not allowed"),null;let c=new Set(["node_modules",".git","dist","build","coverage",".next","__pycache__",".cache",".turbo",".DS_Store"]);async function l(d,u,p){if(p<=0)return[];let m;try{m=await Zs(d,{withFileTypes:!0})}catch{return[]}let g=[],f=[],h=[];for(let w of m)c.has(w.name)||w.isSymbolicLink()||(w.isDirectory()?f.push(w):w.isFile()&&h.push(w));f.sort((w,T)=>w.name.toLowerCase().localeCompare(T.name.toLowerCase())),h.sort((w,T)=>w.name.toLowerCase().localeCompare(T.name.toLowerCase()));for(let w of[...f,...h]){let T=Dt(d,w.name),E=u?`${u}/${w.name}`:w.name;if(w.isDirectory()){let U=await l(T,E,p-1);g.push({name:w.name,path:E,type:"directory",children:U})}else{let U;try{U=(await Oe(T)).size}catch{}g.push({name:w.name,path:E,type:"file",size:U})}}return g}try{let d=n==="."?"":n.replace(/^\/+/,"");return{entries:await l(o,d,i)}}catch(d){let u=d instanceof Error?d.message:"Failed to read directory";return e.respondError(u),null}},"workspace.file.write":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=L(s,t.filePath);if(!n.startsWith(L(s)+re)&&n!==L(s))return e.respondError("Path traversal not allowed"),null;let i=5242880;if(t.content.length>i)return e.respondError(`Content too large: ${t.content.length} bytes (max ${i})`),null;try{let o=Dt(n,"..");return await Ne(o,{recursive:!0}),await fr(n,t.content,"utf-8"),{ok:!0,size:t.content.length,path:t.filePath}}catch(o){let c=o instanceof Error?o.message:"Failed to write file";return e.respondError(c),null}},"workspace.file.upload":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;if(t.encoding!=="base64")return e.respondError("Only base64 encoding is supported for uploads"),null;let s=r.rootDirectory,n=L(s,t.filePath);if(!n.startsWith(L(s)+re)&&n!==L(s))return e.respondError("Path traversal not allowed"),null;let i;try{i=Buffer.from(t.content,"base64")}catch{return e.respondError("Invalid base64 content"),null}if(i.length>52428800)return e.respondError(`File too large: ${i.length} bytes (max ${52428800})`),null;if(!t.overwrite)try{return await en(n),e.respondError(`File already exists: ${t.filePath}`),null}catch{}try{let o=Dt(n,"..");return await Ne(o,{recursive:!0}),await fr(n,i),{ok:!0,size:i.length,path:t.filePath}}catch(o){let c=o instanceof Error?o.message:"Failed to upload file";return e.respondError(c),null}},"workspace.file.delete":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=L(s,t.filePath),i=L(s);if(!n.startsWith(i+re))return e.respondError("Path traversal not allowed"),null;if(n===i)return e.respondError("Cannot delete workspace root"),null;let o;try{o=(await Oe(n)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.filePath}`),null}let c=t.recursive??!0,l,d;if(o==="file")try{nr(n)?(l=(await Nt(n)).toString("base64"),d="base64"):(l=await Nt(n,"utf-8"),d="utf-8")}catch{}try{return await Hi(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+re)||!o.startsWith(n+re))return e.respondError("Path traversal not allowed"),null;let c;try{c=(await Oe(i)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.sourcePath}`),null}try{let l=tn(o);return await Ne(l,{recursive:!0}),await Xi(i,o),{ok:!0,sourcePath:t.sourcePath,destinationPath:t.destinationPath,type:c}}catch(l){let d=l instanceof Error?l.message:"Failed to move";return e.respondError(d),null}},"workspace.file.create":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=L(s,t.filePath),i=L(s);if(!n.startsWith(i+re))return e.respondError("Path traversal not allowed"),null;try{return await en(n),e.respondError(`Already exists: ${t.filePath}`),null}catch{}try{if(t.type==="directory")await Ne(n,{recursive:!0});else{let o=tn(n);await Ne(o,{recursive:!0}),await fr(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 sn(){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 nn(){return{"browser.design.inspect":async(a,e)=>{let t=a;return await e.services.browserManager.inspectElementAt(t.sessionId,t.tabId,t.x,t.y)},"browser.design.highlight":async(a,e)=>{let t=a;return await e.services.browserManager.highlightElementAt(t.sessionId,t.tabId,t.x,t.y,t.enabled),{ok:!0}},"browser.design.screenshot":async(a,e)=>{let t=a;return await e.services.browserManager.screenshotRegion(t.sessionId,t.tabId,t.clip)}}}function an(){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 on(){return{"skillStore.list":(a,e)=>e.services.skillStoreManager.list(),"skillStore.get":(a,e)=>{let t=a;return e.services.skillStoreManager.get(t.id)},"skillStore.save":(a,e)=>{let t=a;return e.services.skillStoreManager.save(t)},"skillStore.update":(a,e)=>{let t=a;return e.services.skillStoreManager.update(t)},"skillStore.delete":(a,e)=>{let t=a;return e.services.skillStoreManager.delete(t.id)},"skillStore.saveFile":(a,e)=>{let t=a;return e.services.skillStoreManager.saveFile(t.id,t.content)},"skillStore.readFile":(a,e)=>{let t=a;return e.services.skillStoreManager.readFile(t.id)},"skillStore.openFolder":(a,e)=>{let t=a;return e.services.skillStoreManager.openFolder(t.id)},"skillStore.duplicate":(a,e)=>{let t=a;return e.services.skillStoreManager.duplicate(t.id,t.newName)},"skillStore.merge":(a,e)=>{let t=a;return e.services.skillStoreManager.merge(t.skillIds,t.name,t.displayName,t.description)},"skillStore.browseRemote":(a,e)=>e.services.skillStoreManager.browseRemote(a),"skillStore.fetchContent":(a,e)=>{let t=a;return e.services.skillStoreManager.fetchRemoteContent(t.owner,t.repo,t.skillId)},"skillStore.listFiles":(a,e)=>{let t=a;return e.services.skillStoreManager.listSkillFiles(t.id)},"skillStore.readSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.readSkillFile(t.id,t.relativePath)},"skillStore.writeSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.writeSkillFile(t.id,t.relativePath,t.content)},"skillStore.deleteSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.deleteSkillFile(t.id,t.relativePath)},"skillStore.createSkillFolder":(a,e)=>{let t=a;return e.services.skillStoreManager.createSkillFolder(t.id,t.relativePath)},"skillStore.renameSkillFile":(a,e)=>{let t=a;return e.services.skillStoreManager.renameSkillFile(t.id,t.oldPath,t.newPath)}}}function cn(){return{...Fs(),...$s(),...Bs(),...Ws(),...qs(),...Hs(),...Xs(),...js(),...Ks(),...Gs(),...zs(),...Js(),...rn(),...sn(),...nn(),...an(),...on()}}var Yi=new Set(["127.0.0.1","::1","::ffff:127.0.0.1","localhost"]);function Vi(a){let e=a.socket.remoteAddress;return e?Yi.has(e):!1}function zi(a){try{return new URL(a.url||"/",`http://${a.headers.host||"localhost"}`).searchParams.get("token")}catch{return null}}function ln(a,e){let t={fn:()=>{}},r={mgr:null},s=new pt((y,k)=>t.fn(y,k)),n=new Ki({server:a,path:"/ws",verifyClient:(y,k)=>{if(Vi(y.req)){k(!0);return}if(s.isActive()){let M=zi(y.req);s.validateToken(M)?k(!0):k(!1,401,"Unauthorized: invalid or missing token");return}k(!1,403,"Remote connections not allowed without tunnel")}}),i=[],o=new Set,c=new WeakMap,l,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),Lr.dispose()});function p(y,k){let $=JSON.stringify({type:"push",channel:y,data:k});for(let v of o)v.readyState===Gi.OPEN&&v.send($);for(let v of i)try{v($)}catch{}if(y==="terminal.output"){let v=k;x.onTerminalOutput(v.id,v.data)}if(y==="terminal.exited"){let v=k,C=F.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let{allDone:j,hasError:Y}=F.markTerminalExited(C.id,v.id,v.exitCode);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:v.exitCode,allDone:j}),j){let ue=Y?"blocked":"waiting";F.move(C.id,ue)}}}if(y==="ports.update"&&r.mgr)try{let v=k;r.mgr.cleanupStaleTunnels(v.ports.map(C=>C.port))}catch(v){console.error("[PortTunnelManager] cleanup error:",v)}if(y==="terminal.process"){let v=k;if(v.process.isIdle){let C=F.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let Y=F.getTaskTerminals(C.id).find(ue=>ue.terminalId===v.id);if(Y&&Y.status==="running"){let{allDone:ue,hasError:Rn}=F.markTerminalExited(C.id,v.id,0);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:0,allDone:ue}),ue){let An=Rn?"blocked":"waiting";F.move(C.id,An)}}}}}}e.prepare("UPDATE workspace_state SET isRunning = 0").run(),e.prepare("UPDATE area_state SET isRunning = 0").run();let m=new We(p),g=e.prepare("SELECT id FROM terminal_configs").all(),f=new Set(g.map(y=>y.id));try{let y=e.prepare("SELECT data FROM area_runtime_state").all();for(let k of y){let M=JSON.parse(k.data);if(M.terminals)for(let $ of M.terminals)f.add($.id)}}catch{}let h=m.recoverSessions(f);if(h.length>0){let y=e.prepare("SELECT workspaceId, areaId FROM terminal_configs WHERE id = ?"),k=e.prepare("INSERT INTO workspace_state (workspaceId, isRunning) VALUES (?, 1) ON CONFLICT(workspaceId) DO UPDATE SET isRunning = 1"),M=e.prepare("INSERT INTO area_state (areaId, isRunning) VALUES (?, 1) ON CONFLICT(areaId) DO UPDATE SET isRunning = 1"),$=new Map;try{let v=e.prepare("SELECT areaId, data FROM area_runtime_state").all();for(let C of v){let j=JSON.parse(C.data);if(j.terminals)for(let Y of j.terminals)$.set(Y.id,C.areaId)}}catch{}for(let v of h){let C=y.get(v);if(C)k.run(C.workspaceId),C.areaId&&M.run(C.areaId);else{let j=$.get(v);if(j){let Y=e.prepare("SELECT workspaceId FROM areas WHERE id = ?").get(j);Y&&(k.run(Y.workspaceId),M.run(j))}}}console.log("[server] Restored running state for workspaces with recovered terminals")}let w=new He(e),T=new qe(e,w),E=new rt,U=new ot(e),de=new ct(e),x=new Qe(e,m,p,E),R=new Ze,F=new et(e,p),Rr=new at(p),ne=new dt(p),I=new ut(p,y=>{let k=m.getProcessInfo(y);return k&&k.pid>0?k.pid:null});t.fn=p;let H=new mt((y,k)=>t.fn(y,k));r.mgr=H;let G=new ft(p),Ft=new wt(e),be=new Tt(e),X=new Et(e);X.seed();let Q=new yt(e);Q.seed(X);let Ar=new vt({terminalManager:m,areaManager:w,workspaceTemplateManager:X,workspaceManager:T}),vn=new St(e),Cr=new bt(p),Lr=new kt((y,k)=>{if(p(y,k),y==="notification.new"){let M=k;Cr.add(M.type,M.title,M.message,M.source)}}),kn=new It,bn=new Rt(e),In=new Lt(e);x.setTaskManager(F),x.setSettingsManager(U);let Mr={terminalManager:m,workspaceManager:T,areaManager:w,swarmManager:x,skillsRegistry:R,taskManager:F,providerRegistry:E,prdBuilder:Rr,settingsManager:U,cliToolsManager:de,browserManager:ne,tunnel:s,portTunnelManager:H,wireframeManager:G,templateManager:Ft,promptTemplateManager:be,workspaceTemplateManager:X,stackManager:Q,stackOrchestrator:Ar,layoutManager:vn,healthCheckService:Lr,notificationService:Cr,portMonitor:I,gitManager:kn,gitHubCliManager:bn,relayClient:null,skillStoreManager:In,broadcast:p},Or=cn();return n.on("connection",(y,k)=>{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",$=>{let v;try{v=JSON.parse($.toString())}catch{return}wr(v,y,Mr,Or)}),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"),ne.stopAll(),I.dispose(),H.stopAll(),l=void 0},3e4);let $=m.useTmux?1440*60*1e3:14400*1e3;d=setTimeout(()=>{let v=$/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},$)}})}),{wss:n,terminalManager:m,workspaceManager:T,swarmManager:x,settingsManager:U,broadcast:p,externalSenders:i,services:Mr,routes:Or,getClientCount:()=>o.size}}async function wr(a,e,t,r){let{id:s,method:n,params:i}=a,o=r[n];if(!o){Se(e,{id:s,error:{message:`Unknown method: ${n}`}});return}let c=!1,l={ws:e,id:s,services:t,respond:d=>{c=!0,Se(e,{id:s,result:d})},respondError:d=>{c=!0,Se(e,{id:s,error:{message:d}})}};try{let d=await o(i,l);!c&&d!==null&&d!==void 0&&Se(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";Se(e,{id:s,error:{message:u}})}}}import{DatabaseSync as Ji}from"node:sqlite";import{mkdirSync as Qi,existsSync as Zi}from"node:fs";import{join as dn}from"node:path";import{homedir as eo}from"node:os";import{randomUUID as to}from"node:crypto";var Tr=dn(eo(),".impactus-swarm"),ro=dn(Tr,"swarm.db");function un(){Zi(Tr)||Qi(Tr,{recursive:!0});let a=new Ji(ro);a.exec("PRAGMA journal_mode = WAL"),a.exec("PRAGMA foreign_keys = ON"),a.exec(`
306
306
  CREATE TABLE IF NOT EXISTS workspaces (
307
307
  id TEXT PRIMARY KEY,
308
308
  name TEXT NOT NULL,
@@ -646,7 +646,7 @@ _No file content available._`)}let o=i.join(`
646
646
  connectedAt TEXT NOT NULL,
647
647
  FOREIGN KEY (workspaceId) REFERENCES workspaces(id) ON DELETE CASCADE
648
648
  )
649
- `);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 ro(a),a}function ro(a){let t=a.prepare(`
649
+ `);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 so(a),a}function so(a){let t=a.prepare(`
650
650
  SELECT w.id, w.name, w.color, w.defaultCommand, w.terminalCount, w.layout
651
651
  FROM workspaces w
652
652
  LEFT JOIN areas a ON a.workspaceId = w.id
@@ -654,7 +654,7 @@ _No file content available._`)}let o=i.join(`
654
654
  `).all();if(t.length===0)return;let r=new Date().toISOString(),s=a.prepare(`
655
655
  INSERT INTO areas (id, workspaceId, name, color, directory, useWorktree, defaultCommand, terminalCount, layout, "order", isDefault, createdAt, updatedAt)
656
656
  VALUES (?, ?, ?, ?, '', 0, ?, ?, ?, 0, 1, ?, ?)
657
- `),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=eo();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 ce from"ws";var un={debug:0,info:1,warn:2,error:3},so=process.env.LOG_LEVEL?.toLowerCase()??"info";function no(a){return!a||Object.keys(a).length===0?"":` | ${Object.entries(a).map(([t,r])=>`${t}=${r}`).join(" ")}`}var Tr=class{constructor(e){this.module=e}log(e,t,r){if(un[e]<un[so])return;let s=new Date().toISOString(),n=e.toUpperCase().padEnd(5),i=`[${s}] [${n}] [${this.module}] ${t}${no(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 pn(a){return new Tr(a)}var _=pn("relay"),ao=15e3,io=15e3,oo=480*60*1e3,Pt=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===ce.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 ce(r);let s=!1,n=null,i=()=>{n&&(clearTimeout(n),n=null)};n=setTimeout(()=>{if(!s){s=!0,i(),_.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(),_.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),_.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(),_.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=>{_.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:ce.OPEN,send(t){e.ws?.readyState===ce.OPEN&&e.ws.send(t)}}}send(e){this.ws?.readyState===ce.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===ce.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===ce.OPEN&&(_.warn("Pong timeout \u2014 forcing reconnect"),this.ws.terminate()),this.pongTimer=null},io)}},ao)}stopPing(){this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=null),this.pongTimer&&(clearTimeout(this.pongTimer),this.pongTimer=null)}startSessionTimer(){this.stopSessionTimer(),this.sessionTimer=setTimeout(()=>{_.info("Session expired (8h) \u2014 reconnecting"),this.reconnect().then(e=>_.info("Session refreshed with new code",{code:e})).catch(()=>_.error("Session refresh failed"))},oo)}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){_.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?_.info("Disconnected, reconnecting",{delay:`${r}ms`,rapidDisconnects:this.rapidDisconnectCount}):this.rapidDisconnectCount%5===0&&_.warn("Rapid disconnect",{count:this.rapidDisconnectCount,delay:`${r}ms`}),setTimeout(async()=>{try{let s=await this.connect();this.rapidDisconnectCount>1?_.info("Reconnected",{code:s,attempts:this.rapidDisconnectCount}):_.info("Reconnected",{code:s})}catch(s){_.error("Reconnection failed",{error:s?.message})}},r),this.reconnectDelay=Math.min(this.reconnectDelay*2,this.maxReconnectDelay)}};function mn(){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 q="\x1B[",S=`${q}0m`,xt=`${q}1m`,A=`${q}2m`,gn=`${q}31m`,ve=`${q}32m`,Er=`${q}33m`,J=`${q}36m`,_t=`${q}37m`,bm=`${q}41m`,co="\x1B[?25l",lo="\x1B[?25h",uo=`${q}2J${q}H`,B={tl:"\u2554",tr:"\u2557",bl:"\u255A",br:"\u255D",h:"\u2550",v:"\u2551",ml:"\u2560",mr:"\u2563",dash:"\u2500"};function se(a,e,t="left"){let r=De(a),s=Math.max(0,e-r.length);return t==="right"?" ".repeat(s)+a:a+" ".repeat(s)}function De(a){return a.replace(/\x1b\[[0-9;]*m/g,"")}function Sr(a,e){return a.length>e?a.slice(0,e-1)+"\u2026":a}function hn(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 po(a){return a<1024*1024?`${(a/1024).toFixed(0)} KB`:`${(a/(1024*1024)).toFixed(1)} MB`}function mo(){let a=new Date;return String(a.getHours()).padStart(2,"0")+":"+String(a.getMinutes()).padStart(2,"0")+":"+String(a.getSeconds()).padStart(2,"0")}var go=15,Ut=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:mo(),message:e,level:t}),this.logBuffer.length>go&&this.logBuffer.shift()}start(e=3e3){this.disabled||(process.stdout.write(co),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(lo)}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(`${J}${xt} 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=uo+r.join(`
657
+ `),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=to();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 ce from"ws";var pn={debug:0,info:1,warn:2,error:3},no=process.env.LOG_LEVEL?.toLowerCase()??"info";function ao(a){return!a||Object.keys(a).length===0?"":` | ${Object.entries(a).map(([t,r])=>`${t}=${r}`).join(" ")}`}var Er=class{constructor(e){this.module=e}log(e,t,r){if(pn[e]<pn[no])return;let s=new Date().toISOString(),n=e.toUpperCase().padEnd(5),i=`[${s}] [${n}] [${this.module}] ${t}${ao(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 mn(a){return new Er(a)}var _=mn("relay"),io=15e3,oo=15e3,co=480*60*1e3,Pt=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===ce.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 ce(r);let s=!1,n=null,i=()=>{n&&(clearTimeout(n),n=null)};n=setTimeout(()=>{if(!s){s=!0,i(),_.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(),_.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),_.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(),_.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=>{_.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:ce.OPEN,send(t){e.ws?.readyState===ce.OPEN&&e.ws.send(t)}}}send(e){this.ws?.readyState===ce.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===ce.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===ce.OPEN&&(_.warn("Pong timeout \u2014 forcing reconnect"),this.ws.terminate()),this.pongTimer=null},oo)}},io)}stopPing(){this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=null),this.pongTimer&&(clearTimeout(this.pongTimer),this.pongTimer=null)}startSessionTimer(){this.stopSessionTimer(),this.sessionTimer=setTimeout(()=>{_.info("Session expired (8h) \u2014 reconnecting"),this.reconnect().then(e=>_.info("Session refreshed with new code",{code:e})).catch(()=>_.error("Session refresh failed"))},co)}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){_.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?_.info("Disconnected, reconnecting",{delay:`${r}ms`,rapidDisconnects:this.rapidDisconnectCount}):this.rapidDisconnectCount%5===0&&_.warn("Rapid disconnect",{count:this.rapidDisconnectCount,delay:`${r}ms`}),setTimeout(async()=>{try{let s=await this.connect();this.rapidDisconnectCount>1?_.info("Reconnected",{code:s,attempts:this.rapidDisconnectCount}):_.info("Reconnected",{code:s})}catch(s){_.error("Reconnection failed",{error:s?.message})}},r),this.reconnectDelay=Math.min(this.reconnectDelay*2,this.maxReconnectDelay)}};function gn(){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 q="\x1B[",S=`${q}0m`,xt=`${q}1m`,A=`${q}2m`,hn=`${q}31m`,ve=`${q}32m`,Sr=`${q}33m`,J=`${q}36m`,_t=`${q}37m`,Rm=`${q}41m`,lo="\x1B[?25l",uo="\x1B[?25h",po=`${q}2J${q}H`,B={tl:"\u2554",tr:"\u2557",bl:"\u255A",br:"\u255D",h:"\u2550",v:"\u2551",ml:"\u2560",mr:"\u2563",dash:"\u2500"};function se(a,e,t="left"){let r=De(a),s=Math.max(0,e-r.length);return t==="right"?" ".repeat(s)+a:a+" ".repeat(s)}function De(a){return a.replace(/\x1b\[[0-9;]*m/g,"")}function yr(a,e){return a.length>e?a.slice(0,e-1)+"\u2026":a}function fn(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 mo(a){return a<1024*1024?`${(a/1024).toFixed(0)} KB`:`${(a/(1024*1024)).toFixed(1)} MB`}function go(){let a=new Date;return String(a.getHours()).padStart(2,"0")+":"+String(a.getMinutes()).padStart(2,"0")+":"+String(a.getSeconds()).padStart(2,"0")}var ho=15,Ut=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:go(),message:e,level:t}),this.logBuffer.length>ho&&this.logBuffer.shift()}start(e=3e3){this.disabled||(process.stdout.write(lo),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(uo)}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(`${J}${xt} 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=po+r.join(`
658
658
  `)+`
659
- `;process.stdout.write(o)}catch{}}renderHeader(e){let t=hn(Date.now()-this.startTime),r=po(process.memoryUsage().rss),s=`${J}${xt} IMPACTUS SWARM${S}`,n=`${A}uptime ${_t}${t}${S} ${A}rss ${_t}${r}${S}`,i=De(s).length,o=De(n).length,c=Math.max(1,e-i-o);return s+" ".repeat(c)+n}renderSessions(e){let t=[];t.push(`${J}${xt} SESSIONS${S}`),t.push("");let r=[];try{let c=b.listSessions();for(let l of c){let d=b.getTerminalId(l);if(!d)continue;let u=d.slice(0,8),p=b.getCreatedAt(l),m=p?hn(Date.now()-p):"?",g="-";try{let h=this.db.prepare("SELECT w.name FROM terminal_configs tc JOIN workspaces w ON w.id = tc.workspaceId WHERE tc.id = ?").get(d);h&&(g=h.name)}catch{}let f=`${A}idle${S}`;if(this.services){let h=this.services.terminalManager.getProcessInfo(d);h?.foregroundProcess&&(f=`${ve}${h.foregroundProcess}${S}`)}r.push({id:u,workspace:Sr(g,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}${se("ID",s)}${se("WORKSPACE",n)}${se("UPTIME",i)}${se("PROCESS",o)}${S}`);for(let c of r)t.push(` ${_t}${se(c.id,s)}${S}${se(c.workspace,n)}${A}${se(c.uptime,i)}${S}${se(c.process,o)}`);return t}renderStatus(e){let t=[];t.push(`${J}${xt} STATUS${S}`),t.push("");let r=[],s=this.getClientCount();r.push(`${A}clients${S} ${s>0?`${ve}${s}${S}`:`${A}0${S}`}`);let n=this.services?.terminalManager.size??0;r.push(`${A}terminals${S} ${_t}${n}${S}`);let i=this.services?.relayClient;if(i){let p=i.connected,m=i.code;p&&m?r.push(`${A}relay${S} ${ve}${m}${S}`):p?r.push(`${A}relay${S} ${ve}connected${S}`):r.push(`${A}relay${S} ${gn}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(g=>`${g.status==="active"?ve:Er}${Sr(g.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"?`${ve}${m.cli}${S}`:m.installed?`${Er}${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=De(r[p]).length,g=p===0?m:u+m;l+g>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=gn:r.level==="warn"&&(s=Er);let n=Sr(r.message,t);return` ${A}[${r.time}]${S} ${s}${n}${S}`})}boxTop(e){return`${J}${B.tl}${B.h.repeat(e-2)}${B.tr}${S}`}boxBottom(e){return`${J}${B.bl}${B.h.repeat(e-2)}${B.br}${S}`}boxSep(e){return`${J}${B.ml}${B.h.repeat(e-2)}${B.mr}${S}`}boxLine(e,t){let r=De(e).length,s=Math.max(0,t-2-r);return`${J}${B.v}${S}${e}${" ".repeat(s)}${J}${B.v}${S}`}};var wo={".html":"text/html",".js":"application/javascript",".css":"text/css",".json":"application/json",".png":"image/png",".svg":"image/svg+xml",".ico":"image/x-icon"},Pe=mn(),Tn=process.env.IMPACTUS_WEB_DIR||yr(import.meta.dirname,"../../web/dist"),vr=ho((a,e)=>{let t=a.url||"/",r=yr(Tn,t==="/"?"index.html":t);if(wn(r)||(r=yr(Tn,"index.html")),!wn(r)){e.writeHead(404),e.end("Not found");return}if(r.endsWith("index.html")){try{let i=fn(r,"utf-8"),o=JSON.stringify({relayUrl:process.env.RELAY_URL||null}),c=i.replace("</head>",`<script>window.__IMPACTUS_CONFIG__=${o}</script>
660
- </head>`);e.writeHead(200,{"Content-Type":"text/html"}),e.end(c)}catch{e.writeHead(500),e.end("Internal server error")}return}let s=fo(r),n=wo[s]||"application/octet-stream";try{let i=fn(r);e.writeHead(200,{"Content-Type":n}),e.end(i)}catch{e.writeHead(500),e.end("Internal server error")}}),br=dn(),ke=new Ut(br,()=>0);ke.interceptLogs();var{terminalManager:To,broadcast:Eo,externalSenders:So,services:kr,routes:yo,getClientCount:vo}=cn(vr,br);ke.setServices(kr);ke.getClientCount=vo;var En=process.env.RELAY_URL,ko=process.env.RELAY_ALLOWED_IPS?process.env.RELAY_ALLOWED_IPS.split(",").map(a=>a.trim()):[],le=null;En&&(le=new Pt(En,ko),kr.relayClient=le,So.push(a=>le.send(a)),le.onMessage=(a,e)=>{let t;try{t=JSON.parse(a)}catch{return}fr(t,e,kr,yo)},le.onCodeChange=a=>{Eo("relay.codeChange",{code:a})},le.connect().then(a=>console.log(`[relay] Code: ${a}`)).catch(a=>console.error("[relay] Failed to connect:",a)));function Sn(){ke.stop(),le?.close(),To.detachAll(),br.close(),process.exit(0)}process.on("SIGINT",Sn);process.on("SIGTERM",Sn);var bo=process.argv.includes("--open");typeof Pe=="number"?vr.listen(Pe,async()=>{let a=`http://localhost:${Pe}`;console.log(`Impactus Swarm server running on ${a}`),ke.start(),bo&&(await import("open")).default(a)}):vr.listen(Pe,()=>{console.log(`Impactus Swarm server running on ${Pe}`),ke.start()});
659
+ `;process.stdout.write(o)}catch{}}renderHeader(e){let t=fn(Date.now()-this.startTime),r=mo(process.memoryUsage().rss),s=`${J}${xt} IMPACTUS SWARM${S}`,n=`${A}uptime ${_t}${t}${S} ${A}rss ${_t}${r}${S}`,i=De(s).length,o=De(n).length,c=Math.max(1,e-i-o);return s+" ".repeat(c)+n}renderSessions(e){let t=[];t.push(`${J}${xt} SESSIONS${S}`),t.push("");let r=[];try{let c=b.listSessions();for(let l of c){let d=b.getTerminalId(l);if(!d)continue;let u=d.slice(0,8),p=b.getCreatedAt(l),m=p?fn(Date.now()-p):"?",g="-";try{let h=this.db.prepare("SELECT w.name FROM terminal_configs tc JOIN workspaces w ON w.id = tc.workspaceId WHERE tc.id = ?").get(d);h&&(g=h.name)}catch{}let f=`${A}idle${S}`;if(this.services){let h=this.services.terminalManager.getProcessInfo(d);h?.foregroundProcess&&(f=`${ve}${h.foregroundProcess}${S}`)}r.push({id:u,workspace:yr(g,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}${se("ID",s)}${se("WORKSPACE",n)}${se("UPTIME",i)}${se("PROCESS",o)}${S}`);for(let c of r)t.push(` ${_t}${se(c.id,s)}${S}${se(c.workspace,n)}${A}${se(c.uptime,i)}${S}${se(c.process,o)}`);return t}renderStatus(e){let t=[];t.push(`${J}${xt} STATUS${S}`),t.push("");let r=[],s=this.getClientCount();r.push(`${A}clients${S} ${s>0?`${ve}${s}${S}`:`${A}0${S}`}`);let n=this.services?.terminalManager.size??0;r.push(`${A}terminals${S} ${_t}${n}${S}`);let i=this.services?.relayClient;if(i){let p=i.connected,m=i.code;p&&m?r.push(`${A}relay${S} ${ve}${m}${S}`):p?r.push(`${A}relay${S} ${ve}connected${S}`):r.push(`${A}relay${S} ${hn}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(g=>`${g.status==="active"?ve:Sr}${yr(g.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"?`${ve}${m.cli}${S}`:m.installed?`${Sr}${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=De(r[p]).length,g=p===0?m:u+m;l+g>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=hn:r.level==="warn"&&(s=Sr);let n=yr(r.message,t);return` ${A}[${r.time}]${S} ${s}${n}${S}`})}boxTop(e){return`${J}${B.tl}${B.h.repeat(e-2)}${B.tr}${S}`}boxBottom(e){return`${J}${B.bl}${B.h.repeat(e-2)}${B.br}${S}`}boxSep(e){return`${J}${B.ml}${B.h.repeat(e-2)}${B.mr}${S}`}boxLine(e,t){let r=De(e).length,s=Math.max(0,t-2-r);return`${J}${B.v}${S}${e}${" ".repeat(s)}${J}${B.v}${S}`}};var To={".html":"text/html",".js":"application/javascript",".css":"text/css",".json":"application/json",".png":"image/png",".svg":"image/svg+xml",".ico":"image/x-icon"},Pe=gn(),En=process.env.IMPACTUS_WEB_DIR||vr(import.meta.dirname,"../../web/dist"),kr=fo((a,e)=>{let t=a.url||"/",r=vr(En,t==="/"?"index.html":t);if(Tn(r)||(r=vr(En,"index.html")),!Tn(r)){e.writeHead(404),e.end("Not found");return}if(r.endsWith("index.html")){try{let i=wn(r,"utf-8"),o=JSON.stringify({relayUrl:process.env.RELAY_URL||null}),c=i.replace("</head>",`<script>window.__IMPACTUS_CONFIG__=${o}</script>
660
+ </head>`);e.writeHead(200,{"Content-Type":"text/html"}),e.end(c)}catch{e.writeHead(500),e.end("Internal server error")}return}let s=wo(r),n=To[s]||"application/octet-stream";try{let i=wn(r);e.writeHead(200,{"Content-Type":n}),e.end(i)}catch{e.writeHead(500),e.end("Internal server error")}}),Ir=un(),ke=new Ut(Ir,()=>0);ke.interceptLogs();var{terminalManager:Eo,broadcast:So,externalSenders:yo,services:br,routes:vo,getClientCount:ko}=ln(kr,Ir);ke.setServices(br);ke.getClientCount=ko;var Sn=process.env.RELAY_URL,bo=process.env.RELAY_ALLOWED_IPS?process.env.RELAY_ALLOWED_IPS.split(",").map(a=>a.trim()):[],le=null;Sn&&(le=new Pt(Sn,bo),br.relayClient=le,yo.push(a=>le.send(a)),le.onMessage=(a,e)=>{let t;try{t=JSON.parse(a)}catch{return}wr(t,e,br,vo)},le.onCodeChange=a=>{So("relay.codeChange",{code:a})},le.connect().then(a=>console.log(`[relay] Code: ${a}`)).catch(a=>console.error("[relay] Failed to connect:",a)));function yn(){ke.stop(),le?.close(),Eo.detachAll(),Ir.close(),process.exit(0)}process.on("SIGINT",yn);process.on("SIGTERM",yn);var Io=process.argv.includes("--open");typeof Pe=="number"?kr.listen(Pe,async()=>{let a=`http://localhost:${Pe}`;console.log(`Impactus Swarm server running on ${a}`),ke.start(),Io&&(await import("open")).default(a)}):kr.listen(Pe,()=>{console.log(`Impactus Swarm server running on ${Pe}`),ke.start()});