impactus-swarm 0.0.19 → 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.
- package/package.json +1 -1
- package/server/main.js +106 -78
- package/web/assets/index-BDY7_Fkj.js +2049 -0
- package/web/assets/index-BFA1PRSk.css +32 -0
- package/web/assets/index-BPxY5xnM.css +32 -0
- package/web/assets/index-BUQLE-0w.js +2049 -0
- package/web/assets/index-BeE19zMk.js +2049 -0
- package/web/assets/index-Bgq6hlM5.js +2043 -0
- package/web/assets/index-BjErQotw.js +2049 -0
- package/web/assets/index-CKZkEFiF.js +2043 -0
- package/web/assets/index-D2Wv6d6i.js +2049 -0
- package/web/assets/index-D4GpWsXg.js +2035 -0
- package/web/assets/index-DJjMLR3G.js +2047 -0
- package/web/assets/index-DVt0StnJ.js +2047 -0
- package/web/assets/index-QvP4jVwH.css +32 -0
- package/web/assets/index-bIhe0YnP.css +32 -0
- package/web/assets/index-k1HwM00R.css +32 -0
- package/web/assets/index-nwKAWJH1.css +32 -0
- package/web/assets/index-z9txzeDm.css +32 -0
- package/web/index.html +2 -2
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
|
|
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,81 +30,81 @@ 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=
|
|
34
|
-
`);await
|
|
35
|
-
`);return await
|
|
36
|
-
`),n=
|
|
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
|
+
`);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
|
+
`);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 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
|
-
`),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
|
|
39
|
-
`).filter(t=>t.startsWith(
|
|
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
|
+
`).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 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
|
|
42
|
-
`))return a.split("\r").filter(s=>s.length>0).every(s=>
|
|
43
|
-
`).filter(r=>
|
|
44
|
-
`).includes(e)}};var
|
|
45
|
-
`)){let n=s.trim();if(n.length!==0&&!
|
|
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<
|
|
47
|
-
`);for(let s of r){let n=s.trim();if(n.length===0)continue;let i=
|
|
48
|
-
`).map(i=>i.replace(/^Name=/,"").trim()).filter(i=>i&&!
|
|
49
|
-
`).map(o=>{let c=o.trim();return c.split("/").pop()||c}).filter(o=>o&&!
|
|
50
|
-
`);for(let i of n)if(i.startsWith("n"))return i.slice(1)}else if(process.platform==="linux")return
|
|
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
|
+
`).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==="~"?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
|
|
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
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);for(let u=0;u<o;u++){let p=e.terminals?.[u],m=
|
|
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||
|
|
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
|
|
64
|
-
`)}getCommandForCli(e,t,r){let s=this.registry.get(e);return s?s.buildCommand({mission:t,cwd:"",autoApprove:r}):e}};import{randomUUID as
|
|
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
|
-
${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
|
|
68
|
-
${
|
|
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}:
|
|
68
|
+
${h.result}`)}}let m=p.length>0?`
|
|
69
69
|
|
|
70
70
|
Context from previous agents:
|
|
71
71
|
${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=
|
|
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:
|
|
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
|
|
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
|
|
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=
|
|
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
|
|
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
|
|
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
|
|
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=
|
|
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=Y(t.directory,".swarm");de(Y(s,"agents"),{recursive:!0}),de(Y(s,"registry"),{recursive:!0}),de(Y(s,"progress"),{recursive:!0});let n=this.settingsManager?.getEnvVarsForWorkspace(t.workspaceId)??{};for(let c of t.agents){this.db.prepare("UPDATE swarm_agents SET status = 'booting' WHERE id = ?").run(c.id);let l=this.buildSwarm(e),d=await this.agentSession.boot(c,l,this.terminalManager,Object.keys(n).length>0?n:void 0,this.worktreeManager),{terminalId:u,worktreePath:p,worktreeBranch:m}=d,h=this.agentTerminals.get(c.id)??[];h.push(u),this.agentTerminals.set(c.id,h),this.db.prepare("UPDATE swarm_agents SET status = 'running', worktreePath = ?, worktreeBranch = ? WHERE id = ?").run(p??null,m??null,c.id),this.consoleManager.addMessage({swarmId:e,agentId:c.id,agentName:c.name,agentRole:c.role,message:`Agent "${c.name}" (${c.role}) started on terminal ${u}`,source:"system"});let f=this.coordinatorLoops.get(e);if(f?.isRunning&&f.registerAgentTerminal(c.id,u,c),c.role==="coordinator"){let g=new qe;g.start(c.id,e,this,this.terminalManager,this.broadcast,this.taskManager??void 0),this.coordinatorLoops.set(e,g);for(let w of t.agents){let T=this.agentTerminals.get(w.id)??[];for(let E of T)g.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(Sa(Y(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=Y(t.directory,".swarm");de(Y(s,"agents"),{recursive:!0}),de(Y(s,"registry"),{recursive:!0}),de(Y(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 He({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 Kr}from"node:crypto";import V from"node:fs";import Q from"node:path";import Yr from"node:os";var Vr={"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"}},zr=[{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"}],Ve=class{projectSkillsDir(e){return Q.join(e,".swarm","registry","skills")}projectMcpsDir(e){return Q.join(e,".swarm","registry","mcps")}globalSkillsDir(){return Q.join(Yr.homedir(),".swarm","registry","skills")}globalMcpsDir(){return Q.join(Yr.homedir(),".swarm","registry","mcps")}readJsonFiles(e){return V.existsSync(e)?V.readdirSync(e).filter(r=>r.endsWith(".json")).map(r=>JSON.parse(V.readFileSync(Q.join(e,r),"utf-8"))):[]}listSkills(e){let t=this.readJsonFiles(this.globalSkillsDir());return e?[...this.readJsonFiles(this.projectSkillsDir(e)),...t]:t}searchSkills(e){let t=e.toLowerCase();return Object.entries(Vr).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);V.mkdirSync(r,{recursive:!0});let s=Vr[e],n={id:Kr(),name:e,description:s?.description??`Custom skill: ${e}`,source:s?"skills.sh":"custom",installedAt:new Date().toISOString()};return V.writeFileSync(Q.join(r,`${e}.json`),JSON.stringify(n,null,2)),n}removeSkill(e,t){let r=Q.join(this.projectSkillsDir(t),`${e}.json`);return V.existsSync(r)?(V.unlinkSync(r),!0):!1}listBundles(){return zr}installBundle(e,t){let r=zr.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);V.mkdirSync(t,{recursive:!0});let r={id:Kr(),name:e.name,command:e.command,args:e.args,env:e.env,enabled:!0};return V.writeFileSync(Q.join(t,`${e.name}.json`),JSON.stringify(r,null,2)),r}};import{randomUUID as Jr}from"node:crypto";import{execSync as Qr}from"node:child_process";var ze=class{db;broadcast;constructor(e,t){this.db=e,this.broadcast=t}create(e){let t=Jr(),r=new Date().toISOString();if(this.db.prepare(`INSERT INTO tasks (id, swarmId, workspaceId, title, description, assignedAgentId, useWorktree, status, approvalMode, createdAt, updatedAt)
|
|
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
|
+
`))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 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
|
+
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
|
+
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(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(
|
|
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
|
|
93
|
-
`)[0]}catch{return null}}var Zr={id:"claude",name:"Claude Code",command:"claude",buildCommand({mission:a,autoApprove:e,claudeMdPath:t}){let r=a.replace(/'/g,"'\\''"),s=["claude"];return e&&s.push("--dangerously-skip-permissions"),t&&s.push(`--project ${t}`),s.push(`'${r}'`),s.join(" ")}};var es={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 ts={id:"gemini",name:"Gemini",command:"gemini",buildCommand({mission:a}){return`gemini '${a.replace(/'/g,"'\\''")}'`}};var rs={id:"opencode",name:"OpenCode",command:"opencode",buildCommand(){return"opencode"}};var ss={id:"cursor",name:"Cursor",command:"cursor",buildCommand(){return"cursor"}};var Je=class{providers=new Map;constructor(){this.register(Zr),this.register(es),this.register(ts),this.register(rs),this.register(ss)}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=Yt(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=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:Yt("claude")??"claude"}};import{randomUUID as cs}from"node:crypto";import{mkdirSync as Ia,writeFileSync as et}from"node:fs";import{join as ke}from"node:path";var Qe=[{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 be=[{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"}],ns=[{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 as=[{name:"Claude Code",category:"ai_coding",command:"claude",healthCommand:"claude --version",healthSuccessKeywords:["claude"],versionCommand:"claude --version",authCommand:"claude auth status",authSuccessKeywords:["logged in","authenticated","isloggedin"],docsUrl:"https://docs.anthropic.com/en/docs/claude-code",enabled:!0,isBuiltIn:!0},{name:"Codex",category:"ai_coding",command:"codex",healthCommand:"codex --version",healthSuccessKeywords:["codex"],versionCommand:"codex --version",authCommand:"codex login status",authSuccessKeywords:["logged in"],docsUrl:"https://github.com/openai/codex",enabled:!0,isBuiltIn:!0},{name:"Gemini CLI",category:"ai_coding",command:"gemini",healthCommand:"gemini --version 2>&1",healthSuccessKeywords:["0.","1.","2."],versionCommand:"gemini --version",authCommand:"gemini --prompt exit 2>&1",authSuccessKeywords:["cached credentials","signed in with google"],docsUrl:"https://github.com/google-gemini/gemini-cli",enabled:!0,isBuiltIn:!0},{name:"OpenCode",category:"ai_coding",command:"opencode",healthCommand:"opencode --version",healthSuccessKeywords:["opencode"],versionCommand:"opencode --version",enabled:!0,isBuiltIn:!0},{name:"Cursor",category:"ai_coding",command:"cursor",healthCommand:"cursor --version",healthSuccessKeywords:["0.","1.","2.","3."],versionCommand:"cursor --version",docsUrl:"https://docs.cursor.com",enabled:!0,isBuiltIn:!0},{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:"tb info 2>&1",authSuccessKeywords:["Workspace"],docsUrl:"https://www.tinybird.co/docs/forward/get-started/install-tinybird-cli",enabled:!0,isBuiltIn:!0}];function Vt(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 zt(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 Jt(a){let e=Vt(a);return["image","pdf","audio","video","archive","font"].includes(e)}var Qt=[{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 is={engine:"Qual motor de PRD voce gostaria de usar? (impactus-native / bmad / aiox / custom)",overview:"Descreva seu projeto em 2-3 frases. O que ele faz? Qual problema resolve?",features:"Liste as funcionalidades principais do seu projeto (uma por linha):",stack:"Selecione as tecnologias que serao usadas no projeto. (Use o seletor de stack no frontend)",screens:"Descreva as telas principais do seu aplicativo (nome e breve descricao de cada uma):",review:"",done:"PRD gerado com sucesso! Os arquivos foram salvos no diretorio .swarm/prd/"};function pe(a,e){return a==="review"&&e?ka(e):is[a]}function Ze(a){let e=["engine","overview","features","stack","screens","review","done"],t=e.indexOf(a);return t===-1||t===e.length-1?"done":e[t+1]}function ka(a){let e=ue(a,"overview"),t=ue(a,"features"),r=ue(a,"screens"),s=a.stack.map(n=>Qe.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
|
|
95
|
-
`).map(
|
|
96
|
-
`),o=n.filter(
|
|
97
|
-
`):"- A definir","","## Backend",c.length>0?c.map(
|
|
98
|
-
`):"- A definir","","## Banco de Dados",l.length>0?l.map(
|
|
99
|
-
`):"- A definir","","## Autenticacao",d.length>0?d.map(
|
|
100
|
-
`):"- A definir","","## Deploy",u.length>0?u.map(
|
|
101
|
-
`):"- A definir","","## Variaveis de Ambiente Necessarias","",...n.filter(
|
|
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
|
+
`).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
|
+
`),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
|
+
`):"- A definir","","## Backend",c.length>0?c.map(h=>`- ${h}`).join(`
|
|
98
|
+
`):"- A definir","","## Banco de Dados",l.length>0?l.map(h=>`- ${h}`).join(`
|
|
99
|
+
`):"- A definir","","## Autenticacao",d.length>0?d.map(h=>`- ${h}`).join(`
|
|
100
|
+
`):"- A definir","","## Deploy",u.length>0?u.map(h=>`- ${h}`).join(`
|
|
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
|
-
`),
|
|
104
|
-
`).map(
|
|
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
|
|
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
|
|
107
|
-
VALUES (?, ?, 0, ?, ?, ?, ?)`),t=new Date().toISOString();for(let r of
|
|
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=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
|
+
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
|
+
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 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
|
|
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 n=Zt(t.healthCommand,{timeout:1e4,encoding:"utf-8",stdio:"pipe",shell:"/bin/sh"}).toLowerCase();s.installed=!0,t.healthSuccessKeywords.length>0?s.healthy=t.healthSuccessKeywords.some(i=>n.includes(i.toLowerCase())):s.healthy=!0}catch(n){return s.installed=!1,s.healthy=!1,s.error=n instanceof Error?n.message:String(n),s}if(t.versionCommand)try{let n=Zt(t.versionCommand,{timeout:5e3,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim();s.version=n}catch{}if(t.authCommand){let n="";try{n=Zt(t.authCommand,{timeout:15e3,encoding:"utf-8",stdio:"pipe",shell:"/bin/sh"}).toLowerCase()}catch(i){if(i&&typeof i=="object"){let o=i;n=((o.stdout??"")+" "+(o.stderr??"")).toLowerCase()}}t.authSuccessKeywords&&t.authSuccessKeywords.length>0?s.authenticated=t.authSuccessKeywords.some(i=>n.includes(i.toLowerCase())):s.authenticated=n.length>0}return s}async healthCheckAll(e){let t=this.list(e).filter(s=>s.enabled),r=[];for(let s of t)r.push(await this.healthCheck(s.id));return r}};import{randomUUID as at}from"node:crypto";var it=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=at(),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=at(),n=at(),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=at(),n=await r.context.newPage(),i=await r.context.newCDPSession(n);t&&await n.goto(t);let o=n.url(),c=await n.title().catch(()=>""),l={page:n,cdpSession:i,url:o,title:c};return r.tabs.set(s,l),await this.setupPageEvents(n,r,s),this.broadcast("browser.tab.created",{sessionId:e,tabId:s,url:o,title:c}),{tabId:s}}async closeTab(e,t){let r=this.getSession(e),s=this.getTab(r,t);r.activeTabId===t&&await this.stopScreencast(s.cdpSession);try{await s.cdpSession.detach()}catch{}try{await s.page.close()}catch{}if(r.tabs.delete(t),this.broadcast("browser.tab.closed",{sessionId:e,tabId:t}),r.activeTabId===t&&r.tabs.size>0){let n=r.tabs.keys().next().value;await this.activateTab(e,n)}}async navigateTab(e,t,r){let s=this.getSession(e),n=this.getTab(s,t),i=r.trim();i&&!i.startsWith("http://")&&!i.startsWith("https://")&&!i.startsWith("about:")&&(i="https://"+i),await n.page.goto(i).catch(o=>{this.broadcast("browser.console",{sessionId:e,tabId:t,type:"error",args:[`Navigation failed: ${o.message}`],text:`Navigation failed: ${o.message}`,timestamp:Date.now()})})}async activateTab(e,t){let r=this.getSession(e),s=this.getTab(r,t);if(r.activeTabId!==t){let i=r.tabs.get(r.activeTabId);i&&await this.stopScreencast(i.cdpSession)}r.activeTabId=t,await this.startScreencast(s.cdpSession,e,t);let n=await this.getNavigationState(s.cdpSession);this.broadcast("browser.tab.updated",{sessionId:e,tabId:t,url:s.url,title:s.title,loading:!1,...n})}async goBack(e,t){let r=this.getSession(e);await this.getTab(r,t).page.goBack()}async goForward(e,t){let r=this.getSession(e);await this.getTab(r,t).page.goForward()}async refresh(e,t){let r=this.getSession(e);await this.getTab(r,t).page.reload()}async sendInput(e,t,r){let s=this.getSession(e),i=this.getTab(s,t).cdpSession,o=["mousePressed","mouseReleased","mouseMoved","mouseWheel"].includes(r.type),c=["keyDown","keyUp","char"].includes(r.type);o?await i.send("Input.dispatchMouseEvent",{type:r.type,x:r.x??0,y:r.y??0,button:r.button||"left",buttons:r.buttons??0,clickCount:r.clickCount||1,deltaX:r.deltaX??0,deltaY:r.deltaY??0,modifiers:r.modifiers||0}):c&&await i.send("Input.dispatchKeyEvent",{type:r.type,key:r.key,code:r.code,text:r.text,windowsVirtualKeyCode:r.windowsVirtualKeyCode||0,nativeVirtualKeyCode:r.windowsVirtualKeyCode||0,modifiers:r.modifiers||0})}async ackFrame(e,t,r){let s=this.getSession(e),n=this.getTab(s,t);try{await n.cdpSession.send("Page.screencastFrameAck",{sessionId:r})}catch{}}async inspectElementAt(e,t,r,s){let n=this.getSession(e),o=this.getTab(n,t).cdpSession;try{await o.send("DOM.enable");let{nodeId:c}=await o.send("DOM.getNodeForLocation",{x:r,y:s,includeUserAgentShadowDOM:!1});if(!c)return{found:!1};let{model:l}=await o.send("DOM.getBoxModel",{nodeId:c}),d=l.border,u={x:d[0],y:d[1],width:d[2]-d[0],height:d[5]-d[1]},{node:p}=await o.send("DOM.describeNode",{nodeId:c}),m=(p.attributes||[]).reduce((f,g,w,T)=>g==="class"&&T[w+1]?T[w+1]:f,""),h=(p.attributes||[]).reduce((f,g,w,T)=>g==="id"&&T[w+1]?T[w+1]:f,"");return{found:!0,boundingBox:u,tagName:p.localName||p.nodeName?.toLowerCase(),className:m,id:h,textContent:(p.nodeValue||"").slice(0,200)}}catch{return{found:!1}}}async highlightElementAt(e,t,r,s,n){let i=this.getSession(e),c=this.getTab(i,t).cdpSession;try{if(!n){await c.send("DOM.hideHighlight");return}await c.send("DOM.enable");let{nodeId:l}=await c.send("DOM.getNodeForLocation",{x:r,y:s,includeUserAgentShadowDOM:!1});if(!l)return;await c.send("DOM.highlightNode",{nodeId:l,highlightConfig:{contentColor:{r:111,g:168,b:220,a:.3},paddingColor:{r:147,g:196,b:125,a:.3},borderColor:{r:255,g:229,b:153,a:.7},marginColor:{r:246,g:178,b:107,a:.3}}})}catch{}}async screenshotRegion(e,t,r){let s=this.getSession(e),i=this.getTab(s,t).cdpSession;try{await i.send("DOM.hideHighlight")}catch{}let o={format:"png"};return r&&(o.clip={x:r.x,y:r.y,width:r.width,height:r.height,scale:1}),{data:(await i.send("Page.captureScreenshot",o)).data,width:r?.width??1280,height:r?.height??720}}async stopAll(){let e=[...this.sessions.keys()];if(await Promise.all(e.map(t=>this.closeSession(t))),this.browser){try{await this.browser.close()}catch{}this.browser=null}}};import{exec as Na}from"node:child_process";import{promisify as Da}from"node:util";var he=Da(Na),ot=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 he("wmic process get ParentProcessId,ProcessId /format:csv",{timeout:5e3});for(let o of i.trim().split(`
|
|
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
|
|
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
|
|
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",
|
|
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
|
+
`)){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
|
+
`)){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
|
+
`);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
|
|
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,40 +257,52 @@ 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
|
|
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
|
-
`,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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=
|
|
272
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`),c=n("Next.js"),l=n("Docker"),d=n("Simple");if(c&&l&&d){let h=W(),f=W(),g=W(),w=[{id:h,templateId:c.id,order:0,targetArea:"new",newAreaName:"App",trigger:{type:"parallel"}},{id:f,templateId:l.id,order:1,targetArea:"new",newAreaName:"Services",trigger:{type:"waitForOutput",dependsOnStepId:h,dependsOnTerminalLabel:"App",waitForText:"Ready",timeoutMs:12e4}},{id:g,templateId:d.id,order:2,targetArea:"current",trigger:{type:"delay",delayMs:2e3,dependsOnStepId:f}}];o.run(W(),"Next Fullstack Pro","Next.js + Docker services + Shadcn UI","#000000","\u{1F680}","1.00",JSON.stringify(w),i,i)}let u=n("Python");if(l&&u){let h=W(),f=W(),g=[{id:h,templateId:l.id,order:0,targetArea:"new",newAreaName:"Database",trigger:{type:"parallel"}},{id:f,templateId:u.id,order:1,targetArea:"new",newAreaName:"API",trigger:{type:"waitForExit",dependsOnStepId:h,dependsOnTerminalLabel:"Docker Up",timeoutMs:6e4}}];o.run(W(),"Python API + DB","Docker DB + Python backend","#CA8A04","\u{1F40D}","1.00",JSON.stringify(g),i,i)}let p=n("Monorepo"),m=n("Multi-Agent");if(p&&m){let h=W(),f=W(),g=[{id:h,templateId:p.id,order:0,targetArea:"new",newAreaName:"Main",trigger:{type:"parallel"}},{id:f,templateId:m.id,order:1,targetArea:"new",newAreaName:"Agents",trigger:{type:"parallel"}}];o.run(W(),"Multi-Agent Monorepo","Monorepo + 4 agentes em paralelo","#7C3AED","\u{1F916}","1.00",JSON.stringify(g),i,i)}}hydrate(e){return{id:e.id,name:e.name,description:e.description,color:e.color,logo:e.logo,version:e.version||"1.00",steps:JSON.parse(e.steps),isBuiltIn:e.isBuiltIn===1,createdAt:e.createdAt,updatedAt:e.updatedAt}}};import{WebSocket as ri}from"ws";function we(a,e){a.readyState===ri.OPEN&&a.send(JSON.stringify(e))}function Es(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 Ie(a,e,t,r){return new Promise(s=>{let n=Date.now(),i=setInterval(()=>{if(a.outputContains(e,t)){clearInterval(i),s();return}Date.now()-n>r&&(clearInterval(i),s())},200)})}async function ne(a,e,t,r){let{terminalManager:s,areaManager:n}=e,i=null;for(let o of a){if(i){let c=!r?.ignoreRunOnce&&o.startRunOnce&&o.hasLaunched;!c&&o.startDelay&&o.startDelay>0&&await new Promise(l=>setTimeout(l,o.startDelay)),!c&&o.startWaitFor&&await Ie(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 si=300*1e3,Tt=class{terminalManager;areaManager;workspaceTemplateManager;workspaceManager;constructor(e){this.terminalManager=e.terminalManager,this.areaManager=e.areaManager,this.workspaceTemplateManager=e.workspaceTemplateManager,this.workspaceManager=e.workspaceManager}async applyStack(e,t){let{stack:r,workspaceId:s,defaultAreaId:n,broadcast:i}=e,o=this.workspaceManager.get(s);if(!o)throw new Error(`Workspace not found: ${s}`);let c=o.rootDirectory,l=[...r.steps].sort((f,g)=>f.order-g.order),d=new Map,u=new Map,p=new Map;for(let f of l){let g,w=new Promise(T=>{g=T});d.set(f.id,w),u.set(f.id,g)}let m=new Promise((f,g)=>setTimeout(()=>g(new Error("Stack orchestration timed out")),si)),h=async()=>{let f=l.map(g=>this.runStep({step:g,stack:r,workspaceId:s,defaultAreaId:n,workspaceRootDir:c,stepStarted:d,stepStartedResolve:u,stepTerminalIds:p,broadcast:i,services:t}));await Promise.all(f)};try{await Promise.race([h(),m])}catch(f){console.error("[StackOrchestrator] Error during stack orchestration:",f)}}async runStep(e){let{step:t,stack:r,workspaceId:s,defaultAreaId:n,workspaceRootDir:i,stepStarted:o,stepStartedResolve:c,stepTerminalIds:l,broadcast:d,services:u}=e,{trigger:p}=t;await this.waitForStartCondition({trigger:p,stepStarted:o,stepTerminalIds:l,services:u});let m=this.workspaceTemplateManager.get(t.templateId);if(!m){console.warn(`[StackOrchestrator] Template not found for step ${t.id}: ${t.templateId}`),c.get(t.id)?.();return}let h;if(t.targetArea==="new"){let 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});h=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})),_=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:""})),oe=[...E,..._];this.areaManager.update({id:n,terminalCount:oe.length,terminals:oe}),h=n;let P=this.areaManager.get(n);d("area.updated",{workspaceId:s,area:P})}c.get(t.id)?.(),d("stack.step.started",{stackId:r.id,stepId:t.id,areaId:h});let f=this.areaManager.get(h);if(!f)return;let g=this.areaManager.resolveForLaunch(f,i),w=t.targetArea==="current"?g.slice(g.length-m.terminals.length):g;l.set(t.id,w.map(T=>T.id));try{await ne(w,u,h)}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 Ie(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 er}from"node:child_process";var ni=300*1e3,ai=2e3,tr=5e3,Ss=[{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)}}],Et=class{interval=null;startupTimer=null;lastResult=null;previousStates=new Map;broadcast;constructor(e){this.broadcast=e,this.startupTimer=setTimeout(()=>{this.checkAll(),this.startupTimer=null},ai),this.interval=setInterval(()=>{this.checkAll()},ni)}async checkAll(){let e=[];for(let r of Ss){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=Ss.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=er(`${c} ${t.command}`,{encoding:"utf8",timeout:tr,stdio:["pipe","pipe","pipe"]}).trim()}catch{return{cli:e,state:"not_installed",installed:!1,authenticated:!1,lastCheckedAt:new Date().toISOString()}}let s;try{s=er(t.versionCommand,{encoding:"utf8",timeout:tr,stdio:["pipe","pipe","pipe"]}).trim()}catch{}let n=!1,i="disconnected",o;try{let c=er(t.authCommand,{encoding:"utf8",timeout:tr,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 ys=100,St=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>ys&&(this.notifications=this.notifications.slice(0,ys)),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 oi}from"node:child_process";import{stat as ci,open as li}from"node:fs/promises";import{join as vs}from"node:path";import{promisify as di}from"node:util";var ui=di(oi),yt=class{async exec(e,t){return ui("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
|
-
`))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],
|
|
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
|
+
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
|
+
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 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
|
+
`))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
|
|
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}
|
|
281
|
-
${
|
|
282
|
-
`;continue}try{let{stdout:
|
|
281
|
+
${g?"Binary file":"File too large to preview"} (untracked)
|
|
282
|
+
`;continue}try{let{stdout:h}=await this.exec(["diff","--no-index","--","/dev/null",m],e);d+=h}catch(h){let w=h;w.stdout&&(d+=w.stdout)}}let u=[r,d].filter(Boolean).join(`
|
|
283
283
|
`);return{...this.parseDiff(u),rawPatch:u}}async commit(e){e.files&&e.files.length>0?await this.exec(["add",...e.files],e.cwd):await this.exec(["add","-A"],e.cwd);let{stdout:t}=await this.exec(["commit","-m",e.message],e.cwd),r=t.match(/\[[\w/.-]+ ([a-f0-9]+)\]/);return{hash:r?r[1]:"",message:e.message}}async push(e){let t=["push"];return e.setUpstream&&e.branch&&t.push("-u","origin",e.branch),await this.exec(t,e.cwd),{ok:!0,remote:"origin",branch:e.branch||"HEAD"}}async branches(e){let{stdout:t}=await this.exec(["branch","-a","--format=%(refname:short) %(HEAD) %(upstream:short)"],e),r=[];for(let s of t.trim().split(`
|
|
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,
|
|
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)}};function bs(){return{"terminal.open":async(a,e)=>{let t=a;return await e.services.terminalManager.open(t),{ok:!0}},"terminal.write":(a,e)=>{let t=a;return e.services.terminalManager.write(t.id,t.data),{ok:!0}},"terminal.resize":(a,e)=>{let t=a;return e.services.terminalManager.resize(t.id,t.cols,t.rows),{ok:!0}},"terminal.close":(a,e)=>{let t=a;return e.services.terminalManager.close(t.id),{ok:!0}},"terminal.list":(a,e)=>({ok:!0,terminals:e.services.terminalManager.listTerminals()}),"terminal.processes":(a,e)=>({ok:!0,processes:e.services.terminalManager.getAllProcessInfo()}),"terminal.replay":(a,e)=>{let t=a;return{ok:!0,data:e.services.terminalManager.getOutputBuffer(t.id)||""}},"terminal.restart":async(a,e)=>{let t=a;return e.services.terminalManager.close(t.id),await e.services.terminalManager.open(t),{ok:!0}},"terminal.upload":async(a,e)=>{let t=a,r=50*1024*1024;if(Math.ceil(t.fileData.length*3/4)>r)return e.respondError("File too large (max 50MB)"),null;let n=e.services.terminalManager.getCwd(t.terminalId);if(!n)return e.respondError(`Terminal ${t.terminalId} not found or CWD unavailable`),null;let i=await import("node:fs"),o=await import("node:path"),c=o.basename(t.fileName);if(!c||c==="."||c==="..")return e.respondError("Invalid file name"),null;let l=o.resolve(n,c);if(!l.startsWith(n+o.sep)&&l!==n)return e.respondError("Invalid file path"),null;if(i.existsSync(l)){let p=o.extname(c),m=c.slice(0,c.length-p.length),h=1;for(;i.existsSync(l);)l=o.resolve(n,`${m} (${h})${p}`),h++}let d=Buffer.from(t.fileData,"base64");i.writeFileSync(l,d);let u="'"+l.replace(/'/g,"'\\''")+"'";return e.services.terminalManager.write(t.terminalId,u+" "),{ok:!0,path:l}},"terminal.set-color":(a,e)=>{let t=a;if(t.areaId)e.services.areaManager.setTerminalColor(t.terminalId,t.areaId,t.color);else if(e.services.workspaceManager.get(t.workspaceId)){let s=e.services.areaManager.getDefaultArea(t.workspaceId);s&&e.services.areaManager.setTerminalColor(t.terminalId,s.id,t.color)}return{ok:!0}}}}function ks(){return{"workspace.list":(a,e)=>e.services.workspaceManager.list(),"workspace.get":(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.id);return r||(e.respondError(`Workspace ${t.id} not found`),null)},"workspace.create":(a,e)=>{let t=a;return e.services.workspaceManager.create(t)},"workspace.update":(a,e)=>{let t=a;return e.services.workspaceManager.update(t)},"workspace.delete":(a,e)=>{let t=a;return{deleted:e.services.workspaceManager.delete(t.id)}},"workspace.launch":async(a,e)=>{let t=a,{workspaceManager:r,areaManager:s,portMonitor:n}=e.services,i=r.get(t.id);if(!i)return e.respondError(`Workspace ${t.id} not found`),null;let o=s.getDefaultArea(i.id);if(!o)return e.respondError(`No default area found for workspace ${t.id}`),null;let c=s.resolveForLaunch(o,i.rootDirectory),l=new Map(o.terminals.map(u=>[u.id,u.color||"default"])),d={ok:!0,terminals:c.map(u=>({id:u.id,label:u.label,cwd:u.cwd,position:u.position,color:l.get(u.id)||"default"}))};return e.respond(d),(async()=>{try{await ne(c,e.services,o.id,{completedStepsProvider:u=>s.getCompletedSteps(u),onStepCompleted:(u,p)=>{s.markStepCompleted(u,p)}}),s.setRunning(o.id,!0),e.services.broadcast("area.status",{id:o.id,workspaceId:t.id,state:"running"}),r.setRunning(t.id,!0),e.services.broadcast("workspace.status",{id:t.id,state:"running"}),n.startMonitoring(t.id,c.map(u=>u.id)).catch(console.error)}catch(u){console.error("[server] workspace.launch async error:",u)}})(),null},"workspace.getSetupConfig":(a,e)=>{let t=a,{workspaceManager:r,areaManager:s}=e.services,n=r.get(t.id);if(!n)return e.respondError(`Workspace ${t.id} not found`),null;let i=s.getDefaultArea(t.id);return{workspace:{id:n.id,name:n.name,color:n.color,rootDirectory:n.rootDirectory,defaultCommand:n.defaultCommand,terminalCount:n.terminalCount,initGit:n.initGit,createdAt:n.createdAt},area:i?{id:i.id,name:i.name,terminalCount:i.terminalCount,layout:i.layout,defaultCommand:i.defaultCommand,ignoreOnLaunchAll:i.ignoreOnLaunchAll??!1}:null,terminals:i?i.terminals.map(o=>({id:o.id,label:o.label,directory:o.directory,command:o.command,commandSequence:o.commandSequence,startDelay:o.startDelay,startWaitFor:o.startWaitFor,startRunOnce:o.startRunOnce,closeAfterCommand:o.closeAfterCommand,closeDelay:o.closeDelay,closeWaitFor:o.closeWaitFor,runOnce:o.runOnce,commandRunOnce:o.commandRunOnce,color:o.color})):[]}},"workspace.relaunch":async(a,e)=>{let t=a,{workspaceManager:r,areaManager:s,terminalManager:n,portMonitor:i}=e.services,o=r.get(t.id);if(!o)return e.respondError(`Workspace ${t.id} not found`),null;let c=s.getDefaultArea(o.id);if(!c)return e.respondError(`No default area found for workspace ${t.id}`),null;let l=s.list(t.id);for(let h of l){for(let f of h.terminals)n.close(f.id);s.setRunning(h.id,!1)}r.setRunning(t.id,!1),i.stopMonitoring(t.id);let u=l.filter(h=>!h.ignoreOnLaunchAll).map(h=>{s.resetAllTerminals(h.id);let f=s.resolveForLaunch(h,o.rootDirectory);return{area:h,resolved:f}});if(u.length===0){s.resetAllTerminals(c.id);let h=s.resolveForLaunch(c,o.rootDirectory);u.push({area:c,resolved:h})}let p=u.find(h=>h.area.id===c.id)??u[0],m=new Map(p.area.terminals.map(h=>[h.id,h.color||"default"]));return e.respond({ok:!0,terminals:p.resolved.map(h=>({id:h.id,label:h.label,cwd:h.cwd,position:h.position,color:m.get(h.id)||"default"}))}),(async()=>{let h=[];await Promise.all(u.map(async({area:f,resolved:g})=>{try{let w=f.trigger;if(w){let T=w.timeoutMs??12e4;w.type==="delay"?await new Promise(E=>setTimeout(E,w.delayMs??0)):w.type==="waitForOutput"&&w.dependsOnTerminalId&&w.waitForText?await Ie(n,w.dependsOnTerminalId,w.waitForText,T):w.type==="waitForExit"&&w.dependsOnTerminalId&&await Es(n,w.dependsOnTerminalId,T)}await ne(g,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 g)h.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"}),h.length>0&&i.startMonitoring(t.id,h).catch(console.error)})(),null},"workspace.stop":(a,e)=>{let t=a,{workspaceManager:r,areaManager:s,terminalManager:n,portMonitor:i}=e.services,o=r.get(t.id);if(!o)return e.respondError(`Workspace ${t.id} not found`),null;let c=s.list(t.id);for(let l of c){for(let d of l.terminals)n.close(d.id);s.setRunning(l.id,!1),e.services.broadcast("area.status",{id:l.id,workspaceId:t.id,state:"stopped"})}for(let l of o.terminals)n.close(l.id);return r.setRunning(t.id,!1),e.services.broadcast("workspace.status",{id:t.id,state:"stopped"}),i.stopMonitoring(t.id),{ok:!0}}}}function Is(){return{"area.list":(a,e)=>{let t=a;return e.services.areaManager.list(t.workspaceId)},"area.create":(a,e)=>{let t=a;return e.services.areaManager.create(t)},"area.update":(a,e)=>{let t=a;return e.services.areaManager.update(t)},"area.delete":(a,e)=>{let t=a;return{deleted:e.services.areaManager.delete(t.id)}},"area.duplicate":(a,e)=>{let t=a;return e.services.areaManager.duplicate(t.id,t.name)},"area.launch":async(a,e)=>{let t=a,{areaManager:r,workspaceManager:s}=e.services,n=r.get(t.areaId);if(!n)return e.respondError(`Area ${t.areaId} not found`),null;let i=s.get(t.workspaceId);if(!i)return e.respondError(`Workspace ${t.workspaceId} not found`),null;let o=r.resolveForLaunch(n,i.rootDirectory),c=new Map(n.terminals.map(d=>[d.id,d.color||"default"])),l={ok:!0,terminals:o.map(d=>({id:d.id,label:d.label,cwd:d.cwd,position:d.position,color:c.get(d.id)||"default"}))};return e.respond(l),(async()=>{try{await ne(o,e.services,t.areaId,{completedStepsProvider:d=>r.getCompletedSteps(d),onStepCompleted:(d,u)=>{r.markStepCompleted(d,u)}}),r.setRunning(t.areaId,!0),s.setRunning(t.workspaceId,!0),e.services.broadcast("area.status",{id:t.areaId,workspaceId:t.workspaceId,state:"running"}),e.services.broadcast("workspace.status",{id:t.workspaceId,state:"running"})}catch(d){console.error("[server] area.launch async error:",d)}})(),null},"area.stop":(a,e)=>{let t=a,{areaManager:r,workspaceManager:s,terminalManager:n}=e.services,i=r.get(t.areaId);if(!i)return e.respondError(`Area ${t.areaId} not found`),null;for(let l of i.terminals)n.close(l.id);return r.setRunning(t.areaId,!1),r.clearRuntimeState(t.areaId),r.list(t.workspaceId).some(l=>l.id!==t.areaId&&r.isRunning(l.id))||(s.setRunning(t.workspaceId,!1),e.services.broadcast("workspace.status",{id:t.workspaceId,state:"stopped"})),e.services.broadcast("area.status",{id:t.areaId,workspaceId:t.workspaceId,state:"stopped"}),{ok:!0}},"area.save-runtime-state":(a,e)=>{let t=a;return e.services.areaManager.saveRuntimeState(t.areaId,t.data),{ok:!0}},"area.get-runtime-state":(a,e)=>{let t=a;return{data:e.services.areaManager.getRuntimeState(t.areaId)}},"area.clear-runtime-state":(a,e)=>{let t=a;return e.services.areaManager.clearRuntimeState(t.areaId),{ok:!0}}}}function Rs(){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 rr,writeFile as bt,cp as hi}from"node:fs/promises";import{basename as fi,join as Z,resolve as wi}from"node:path";var Re=class{async buildContext(e){let{task:t,agent:r,swarm:s,knowledgeEntries:n,dependencyTasks:i,workspaceDir:o}=e,c=Z(o,".swarm","tasks",t.id);await rr(c,{recursive:!0});let l=this.assemblePrompt(t,r,n,i),d=Z(c,"CLAUDE.md"),u=this.generateClaudeMd(t,r,s);await bt(d,u,"utf-8");let p=this.generateTaskMd(t,i);if(await bt(Z(c,"TASK.md"),p,"utf-8"),s?.knowledge&&s.knowledge.length>0){let m=Z(c,"knowledge");await rr(m,{recursive:!0});for(let h of s.knowledge)try{let f=fi(h.name),g=wi(h.path),w=Z(m,f);await hi(g,w)}catch{}}return{contextDir:c,prompt:l,claudeMdPath:d}}assemblePrompt(e,t,r,s){let n=[];if(n.push(`# Task: ${e.title}`,""),n.push(e.description,""),n.push("## Agent",""),n.push(`- **Name:** ${t.name}`),n.push(`- **Role:** ${t.role}`),n.push(""),t.workScope&&t.workScope.length>0){n.push("## Work Scope","");for(let i of t.workScope)n.push(`- ${i}`);n.push("")}if(s&&s.length>0){n.push("## Dependencies","");for(let i of s)n.push(`### ${i.title} (${i.status})`),i.output&&n.push("","Output:","",i.output),n.push("")}if(r&&r.length>0){n.push("## Knowledge Base","");for(let i of r)n.push(`- ${i.name} (${i.type}): \`${i.path}\``);n.push("")}switch(n.push(`## Approval Mode: ${e.approvalMode}`,""),e.approvalMode){case"auto":n.push("You may proceed autonomously without waiting for human approval.");break;case"semi":n.push("Proceed with implementation but pause before destructive or irreversible actions.");break;case"manual":n.push("Wait for explicit human approval before making any changes.");break}return n.push(""),n.join(`
|
|
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
|
+
|
|
293
|
+
${f}`)}else i.push(`# ${m.displayName}
|
|
294
|
+
|
|
295
|
+
_No file content available._`)}let o=i.join(`
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
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(`
|
|
290
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(`
|
|
291
|
-
`)}async buildStandaloneContext(e){let{task:t,prompt:r,workspaceDir:s}=e,n=
|
|
292
|
-
`);return await
|
|
293
|
-
`)}};function As(){return{"task.create":(a,e)=>{let t=a;return e.services.taskManager.create(t)},"task.update":(a,e)=>{let t=a;return e.services.taskManager.update(t.id,t.updates)},"task.delete":(a,e)=>{let t=a;return{deleted:e.services.taskManager.delete(t.id)}},"task.list":(a,e)=>{let t=a;return e.services.taskManager.list(t)},"task.move":(a,e)=>{let t=a;return e.services.taskManager.move(t.id,t.status)},"task.assign":(a,e)=>{let t=a;return e.services.taskManager.assign(t.id,t.agentId)},"task.run":async(a,e)=>{let t=a,{taskManager:r,terminalManager:s,workspaceManager:n,swarmManager:i,providerRegistry:o}=e.services,c=r.get(t.taskId);if(!c)return e.respondError(`Task ${t.taskId} not found`),null;if(t.terminals&&t.terminals.length>0){let P=c.workspaceId?n.get(c.workspaceId):null,R=t.workspaceDir||P?.rootDirectory||process.cwd(),U=[];for(let se=0;se<t.terminals.length;se++){let k=t.terminals[se],H=`task-${c.id}-${se}-${Date.now()}`,G;if(k.command)G=k.command;else if(k.cli){let q=await new Re().buildStandaloneContext({task:c,cli:k.cli,prompt:k.prompt,workspaceDir:R}),J=o.get(k.cli);G=J?J.buildCommand({mission:q.prompt,cwd:"",autoApprove:k.autoApprove??!1}):k.cli,k.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}),k.command){let Se=k.promptDelay??3e3;if(k.commandSequence&&k.commandSequence.length>0){let q=0;for(let J of k.commandSequence)q+=J.delay,setTimeout(()=>{s.write(H,J.command+"\r")},q);k.prompt&&setTimeout(()=>{s.write(H,k.prompt+"\r")},q+Se)}else k.prompt&&setTimeout(()=>{s.write(H,k.prompt+"\r")},Se)}let Ot=k.cli||k.command||"shell";r.addTerminal(c.id,H,Ot,k.prompt,k.autoApprove??!1),U.push(H)}return r.move(c.id,"running"),{taskId:c.id,terminalIds:U,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(P=>P.id===l);if(!u)return e.respondError(`Agent ${l} not found in swarm`),null;let m=t.includeKnowledge!==!1?d.knowledge:void 0,h;t.includeDependencies&&c.dependencies.length>0&&(h=c.dependencies.map(P=>r.get(P)).filter(P=>P!==null));let g=await new Re().buildContext({task:c,agent:u,swarm:d,knowledgeEntries:m,dependencyTasks:h,workspaceDir:d.directory}),w=o.get(u.cli),T=w?w.buildCommand({mission:g.prompt,cwd:"",autoApprove:u.autoApprove||d.autoApprove}):u.cli,E=`task-${c.id}-${l.slice(0,8)}`,_=u.worktreePath||d.directory;return await s.open({id:E,cwd:_,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:_}},"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 Cs(){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 Ls(){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 Ms(){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 Os(){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 Ns(){return{"browser.session.open":async(a,e)=>{let t=a;return await e.services.browserManager.openSession(t.url)},"browser.session.close":async(a,e)=>{let t=a;return await e.services.browserManager.closeSession(t.sessionId),{ok:!0}},"browser.tab.open":async(a,e)=>{let t=a;return await e.services.browserManager.openTab(t.sessionId,t.url)},"browser.tab.close":async(a,e)=>{let t=a;return await e.services.browserManager.closeTab(t.sessionId,t.tabId),{ok:!0}},"browser.tab.navigate":async(a,e)=>{let t=a;return await e.services.browserManager.navigateTab(t.sessionId,t.tabId,t.url),{ok:!0}},"browser.tab.activate":async(a,e)=>{let t=a;return await e.services.browserManager.activateTab(t.sessionId,t.tabId),{ok:!0}},"browser.tab.back":async(a,e)=>{let t=a;return await e.services.browserManager.goBack(t.sessionId,t.tabId),{ok:!0}},"browser.tab.forward":async(a,e)=>{let t=a;return await e.services.browserManager.goForward(t.sessionId,t.tabId),{ok:!0}},"browser.tab.refresh":async(a,e)=>{let t=a;return await e.services.browserManager.refresh(t.sessionId,t.tabId),{ok:!0}},"browser.input":async(a,e)=>{let t=a;return await e.services.browserManager.sendInput(t.sessionId,t.tabId,t.event),{ok:!0}},"browser.screencast.ack":async(a,e)=>{let t=a;return await e.services.browserManager.ackFrame(t.sessionId,t.tabId,t.frameNumber),{ok:!0}}}}import*as ee from"node:fs";import*as kt from"node:os";import*as D from"node:path";import Ds from"node:fs";import Ps from"node:path";import{spawn as Ti}from"node:child_process";var Ei={"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"},sr=class{detectInstalledEditors(){let e=new Set,t=(process.env.PATH||"").split(Ps.delimiter),r=process.platform==="darwin";for(let s of Qt){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(Ds.existsSync(Ps.join(n,s.command))){e.add(s.id);break}}catch{}}if(r)try{let s=Ds.readdirSync("/Applications");for(let n of s){let i=Ei[n];i&&!e.has(i)&&e.add(i)}}catch{}return Array.from(e)}openInEditor(e,t){try{let r=Qt.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]),Ti(s,n,{detached:!0,stdio:"ignore"}).unref(),{ok:!0}}catch(r){return{ok:!1,error:r instanceof Error?r.message:String(r)}}}},nr=new sr;function xs(){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=kt.homedir(),r=e.path||t;r==="~"?r=t:r.startsWith("~/")&&(r=D.join(t,r.slice(2))),r=D.resolve(r);try{let s=ee.readdirSync(r),n=[];for(let i of s){if(!e.showHidden&&i.startsWith("."))continue;let o=D.join(r,i);try{ee.statSync(o).isDirectory()&&n.push({name:i,path:o})}catch{}}return n.sort((i,o)=>i.name.localeCompare(o.name)),{current:r,parent:D.dirname(r),home:t,dirs:n}}catch(s){return{current:r,parent:D.dirname(r),home:t,dirs:[],error:s.message}}},"system.createDir":a=>{let t=a.path,r=kt.homedir();t.startsWith("~/")&&(t=D.join(r,t.slice(2))),t=D.resolve(t);try{return ee.mkdirSync(t,{recursive:!0}),{ok:!0,path:t}}catch(s){return{ok:!1,error:s.message}}},"system.homeDir":()=>{let a=kt.homedir(),e=[{name:"Home",path:a},{name:"Desktop",path:D.join(a,"Desktop")},{name:"Documents",path:D.join(a,"Documents")},{name:"Downloads",path:D.join(a,"Downloads")},{name:"Development",path:D.join(a,"Development")},{name:"Development",path:D.join(a,"Documents","Development")},{name:"Projects",path:D.join(a,"Projects")},{name:"/",path:"/"}],t=[],r=new Set;for(let s of e){if(r.has(s.name)){if(!t.find(n=>n.name===s.name))try{ee.statSync(s.path),t.push(s),r.add(s.name)}catch{}continue}try{ee.statSync(s.path),t.push(s),r.add(s.name)}catch{}}return t.find(s=>s.path==="/")||t.push({name:"/",path:"/"}),{home:a,shortcuts:t}},"system.detect-clis":async(a,e)=>await e.services.providerRegistry.detectInstalled(),"system.health-check":async(a,e)=>{let t=a;return t?.cli?{providers:[await e.services.healthCheckService.checkOne(t.cli)],checkedAt:new Date().toISOString()}:await e.services.healthCheckService.checkAll()},"notifications.list":(a,e)=>e.services.notificationService.list(),"notifications.clear":(a,e)=>{let t=a;return e.services.notificationService.clear(t?.id),{ok:!0}},"notifications.mark-read":(a,e)=>{let t=a;return e.services.notificationService.markRead(t.id),{ok:!0}},"ide.list":()=>({editors:nr.detectInstalledEditors()}),"ide.open":a=>{let e=a;return nr.openInEditor(e.editor,e.cwd)},ping:()=>({ok:!0,ts:Date.now()})}}function _s(){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 Fs,stat as Ae,readFile as It,writeFile as ar,mkdir as Ce,access as Bs,rm as Si,rename as yi}from"node:fs/promises";import{join as Rt,resolve as L,relative as vi,dirname as Ws,sep as te}from"node:path";function $s(){return{"workspace.file.glob":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=new Set(["node_modules",".git","dist","build",".swarm","__pycache__",".next",".turbo"]),i=new Set([".png",".jpg",".jpeg",".gif",".ico",".woff",".woff2",".ttf",".eot",".pdf",".zip",".tar",".gz",".bz2",".mp3",".mp4",".mov",".avi",".webm",".webp",".svg"]),o=t.limit??50,c=t.pattern?.toLowerCase()||"",l=[];async function d(u){if(l.length>=o*5)return;let p;try{p=await Fs(u,{withFileTypes:!0})}catch{return}for(let m of p){if(l.length>=o*5)return;if(n.has(m.name)||m.isSymbolicLink())continue;let h=Rt(u,m.name);if(m.isDirectory())await d(h);else if(m.isFile()){let f="."+(m.name.split(".").pop()?.toLowerCase()||"");if(i.has(f))continue;let g=vi(s,h);if(c&&!g.toLowerCase().includes(c)&&!m.name.toLowerCase().includes(c))continue;try{let w=await Ae(h);l.push({path:g,basename:m.name,size:w.size,modifiedAt:w.mtime.toISOString()})}catch{}}}}return await d(s),l.sort((u,p)=>p.modifiedAt.localeCompare(u.modifiedAt)),{files:l.slice(0,o)}},"workspace.file.read":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=t.maxSize??1048576,i=L(s,t.filePath);if(!i.startsWith(L(s)+te)&&i!==L(s))return e.respondError("Path traversal not allowed"),null;try{let o=await Ae(i),c=Vt(i),l=Jt(i),u=l?10485760:n;return o.size>u?(e.respondError(`File too large: ${o.size} bytes (max ${u})`),null):l?{content:(await It(i)).toString("base64"),language:c,size:o.size,path:t.filePath,encoding:"base64",mimeType:zt(i)}:{content:await It(i,"utf-8"),language:c,size:o.size,path:t.filePath,encoding:"utf-8",mimeType:zt(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)+te)&&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 Fs(d,{withFileTypes:!0})}catch{return[]}let h=[],f=[],g=[];for(let w of m)c.has(w.name)||w.isSymbolicLink()||(w.isDirectory()?f.push(w):w.isFile()&&g.push(w));f.sort((w,T)=>w.name.toLowerCase().localeCompare(T.name.toLowerCase())),g.sort((w,T)=>w.name.toLowerCase().localeCompare(T.name.toLowerCase()));for(let w of[...f,...g]){let T=Rt(d,w.name),E=u?`${u}/${w.name}`:w.name;if(w.isDirectory()){let _=await l(T,E,p-1);h.push({name:w.name,path:E,type:"directory",children:_})}else{let _;try{_=(await Ae(T)).size}catch{}h.push({name:w.name,path:E,type:"file",size:_})}}return h}try{let d=n==="."?"":n.replace(/^\/+/,"");return{entries:await l(o,d,i)}}catch(d){let u=d instanceof Error?d.message:"Failed to read directory";return e.respondError(u),null}},"workspace.file.write":async(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.workspaceId);if(!r)return e.respondError("Workspace not found"),null;let s=r.rootDirectory,n=L(s,t.filePath);if(!n.startsWith(L(s)+te)&&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=Rt(n,"..");return await Ce(o,{recursive:!0}),await ar(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)+te)&&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 Bs(n),e.respondError(`File already exists: ${t.filePath}`),null}catch{}try{let o=Rt(n,"..");return await Ce(o,{recursive:!0}),await ar(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+te))return e.respondError("Path traversal not allowed"),null;if(n===i)return e.respondError("Cannot delete workspace root"),null;let o;try{o=(await Ae(n)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.filePath}`),null}let c=t.recursive??!0,l,d;if(o==="file")try{Jt(n)?(l=(await It(n)).toString("base64"),d="base64"):(l=await It(n,"utf-8"),d="utf-8")}catch{}try{return await Si(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+te)||!o.startsWith(n+te))return e.respondError("Path traversal not allowed"),null;let c;try{c=(await Ae(i)).isDirectory()?"directory":"file"}catch{return e.respondError(`Not found: ${t.sourcePath}`),null}try{let l=Ws(o);return await Ce(l,{recursive:!0}),await yi(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+te))return e.respondError("Path traversal not allowed"),null;try{return await Bs(n),e.respondError(`Already exists: ${t.filePath}`),null}catch{}try{if(t.type==="directory")await Ce(n,{recursive:!0});else{let o=Ws(n);await Ce(o,{recursive:!0}),await ar(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 Hs(){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 qs(){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 Xs(){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 js(){return{...bs(),...ks(),...Is(),...Rs(),...As(),...Cs(),...Ls(),...Ms(),...Os(),...Ns(),...xs(),..._s(),...$s(),...Hs(),...qs(),...Xs()}}var Ii=new Set(["127.0.0.1","::1","::ffff:127.0.0.1","localhost"]);function Ri(a){let e=a.socket.remoteAddress;return e?Ii.has(e):!1}function Ai(a){try{return new URL(a.url||"/",`http://${a.headers.host||"localhost"}`).searchParams.get("token")}catch{return null}}function Gs(a,e){let t={fn:()=>{}},r={mgr:null},s=new ct((y,b)=>t.fn(y,b)),n=new bi({server:a,path:"/ws",verifyClient:(y,b)=>{if(Ri(y.req)){b(!0);return}if(s.isActive()){let M=Ai(y.req);s.validateToken(M)?b(!0):b(!1,401,"Unauthorized: invalid or missing token");return}b(!1,403,"Remote connections not allowed without tunnel")}}),i=[],o=new Set,c=new WeakMap,l,d,u=setInterval(()=>{for(let y of o){if(!c.get(y)){y.terminate();continue}c.set(y,!1),y.ping()}},3e4);n.on("close",()=>{clearInterval(u),Tr.dispose()});function p(y,b){let F=JSON.stringify({type:"push",channel:y,data:b});for(let v of o)v.readyState===ki.OPEN&&v.send(F);for(let v of i)try{v(F)}catch{}if(y==="terminal.output"){let v=b;P.onTerminalOutput(v.id,v.data)}if(y==="terminal.exited"){let v=b,C=U.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let{allDone:X,hasError:K}=U.markTerminalExited(C.id,v.id,v.exitCode);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:v.exitCode,allDone:X}),X){let ce=K?"blocked":"waiting";U.move(C.id,ce)}}}if(y==="ports.update"&&r.mgr)try{let v=b;r.mgr.cleanupStaleTunnels(v.ports.map(C=>C.port))}catch(v){console.error("[PortTunnelManager] cleanup error:",v)}if(y==="terminal.process"){let v=b;if(v.process.isIdle){let C=U.getTaskByTerminalId(v.id);if(C&&C.status==="running"){let K=U.getTaskTerminals(C.id).find(ce=>ce.terminalId===v.id);if(K&&K.status==="running"){let{allDone:ce,hasError:ln}=U.markTerminalExited(C.id,v.id,0);if(p("task.terminal.exited",{taskId:C.id,terminalId:v.id,exitCode:0,allDone:ce}),ce){let dn=ln?"blocked":"waiting";U.move(C.id,dn)}}}}}}e.prepare("UPDATE workspace_state SET isRunning = 0").run(),e.prepare("UPDATE area_state SET isRunning = 0").run();let m=new Ue(p),h=e.prepare("SELECT id FROM terminal_configs").all(),f=new Set(h.map(y=>y.id));try{let y=e.prepare("SELECT data FROM area_runtime_state").all();for(let b of y){let M=JSON.parse(b.data);if(M.terminals)for(let F of M.terminals)f.add(F.id)}}catch{}let g=m.recoverSessions(f);if(g.length>0){let y=e.prepare("SELECT workspaceId, areaId FROM terminal_configs WHERE id = ?"),b=e.prepare("INSERT INTO workspace_state (workspaceId, isRunning) VALUES (?, 1) ON CONFLICT(workspaceId) DO UPDATE SET isRunning = 1"),M=e.prepare("INSERT INTO area_state (areaId, isRunning) VALUES (?, 1) ON CONFLICT(areaId) DO UPDATE SET isRunning = 1"),F=new Map;try{let v=e.prepare("SELECT areaId, data FROM area_runtime_state").all();for(let C of v){let X=JSON.parse(C.data);if(X.terminals)for(let K of X.terminals)F.set(K.id,C.areaId)}}catch{}for(let v of g){let C=y.get(v);if(C)b.run(C.workspaceId),C.areaId&&M.run(C.areaId);else{let X=F.get(v);if(X){let K=e.prepare("SELECT workspaceId FROM areas WHERE id = ?").get(X);K&&(b.run(K.workspaceId),M.run(X))}}}console.log("[server] Restored running state for workspaces with recovered terminals")}let w=new Be(e),T=new Fe(e,w),E=new Je,_=new st(e),oe=new nt(e),P=new Ye(e,m,p,E),R=new Ve,U=new ze(e,p),hr=new tt(p),se=new it(p),k=new ot(p,y=>{let b=m.getProcessInfo(y);return b&&b.pid>0?b.pid:null});t.fn=p;let H=new lt((y,b)=>t.fn(y,b));r.mgr=H;let G=new pt(p),Ot=new mt(e),Se=new gt(e),q=new ht(e);q.seed();let J=new wt(e);J.seed(q);let fr=new Tt({terminalManager:m,areaManager:w,workspaceTemplateManager:q,workspaceManager:T}),an=new ft(e),wr=new St(p),Tr=new Et((y,b)=>{if(p(y,b),y==="notification.new"){let M=b;wr.add(M.type,M.title,M.message,M.source)}}),on=new yt,cn=new vt(e);P.setTaskManager(U),P.setSettingsManager(_);let Er={terminalManager:m,workspaceManager:T,areaManager:w,swarmManager:P,skillsRegistry:R,taskManager:U,providerRegistry:E,prdBuilder:hr,settingsManager:_,cliToolsManager:oe,browserManager:se,tunnel:s,portTunnelManager:H,wireframeManager:G,templateManager:Ot,promptTemplateManager:Se,workspaceTemplateManager:q,stackManager:J,stackOrchestrator:fr,layoutManager:an,healthCheckService:Tr,notificationService:wr,portMonitor:k,gitManager:on,gitHubCliManager:cn,relayClient:null,broadcast:p},Sr=js();return n.on("connection",(y,b)=>{o.add(y),c.set(y,!0),y.on("pong",()=>{c.set(y,!0)});let M=!1;l&&(clearTimeout(l),l=void 0,M=!0),d&&(clearTimeout(d),d=void 0,M=!0),M&&console.log("[server] Client reconnected \u2014 cancelling cleanup timers"),y.on("message",F=>{let v;try{v=JSON.parse(F.toString())}catch{return}ir(v,y,Er,Sr)}),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"),se.stopAll(),k.dispose(),H.stopAll(),l=void 0},3e4);let F=m.useTmux?1440*60*1e3:14400*1e3;d=setTimeout(()=>{let v=F/36e5;console.log(`[server] ${v}h timeout \u2014 closing all terminals`),m.closeAll(),e.prepare("UPDATE workspace_state SET isRunning = 0").run(),e.prepare("UPDATE area_state SET isRunning = 0").run(),e.prepare("DELETE FROM area_runtime_state").run(),d=void 0},F)}})}),{wss:n,terminalManager:m,workspaceManager:T,swarmManager:P,settingsManager:_,broadcast:p,externalSenders:i,services:Er,routes:Sr,getClientCount:()=>o.size}}async function ir(a,e,t,r){let{id:s,method:n,params:i}=a,o=r[n];if(!o){we(e,{id:s,error:{message:`Unknown method: ${n}`}});return}let c=!1,l={ws:e,id:s,services:t,respond:d=>{c=!0,we(e,{id:s,result:d})},respondError:d=>{c=!0,we(e,{id:s,error:{message:d}})}};try{let d=await o(i,l);!c&&d!==null&&d!==void 0&&we(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";we(e,{id:s,error:{message:u}})}}}import{DatabaseSync as Ci}from"node:sqlite";import{mkdirSync as Li,existsSync as Mi}from"node:fs";import{join as Ks}from"node:path";import{homedir as Oi}from"node:os";import{randomUUID as Ni}from"node:crypto";var or=Ks(Oi(),".impactus-swarm"),Di=Ks(or,"swarm.db");function Ys(){Mi(or)||Li(or,{recursive:!0});let a=new Ci(Di);a.exec("PRAGMA journal_mode = WAL"),a.exec("PRAGMA foreign_keys = ON"),a.exec(`
|
|
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
|
+
`);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 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(`
|
|
294
306
|
CREATE TABLE IF NOT EXISTS workspaces (
|
|
295
307
|
id TEXT PRIMARY KEY,
|
|
296
308
|
name TEXT NOT NULL,
|
|
@@ -370,6 +382,22 @@ ${h?"Binary file":"File too large to preview"} (untracked)
|
|
|
370
382
|
createdAt TEXT NOT NULL,
|
|
371
383
|
updatedAt TEXT NOT NULL
|
|
372
384
|
)
|
|
385
|
+
`),a.exec(`
|
|
386
|
+
CREATE TABLE IF NOT EXISTS saved_skills (
|
|
387
|
+
id TEXT PRIMARY KEY,
|
|
388
|
+
name TEXT NOT NULL,
|
|
389
|
+
displayName TEXT NOT NULL,
|
|
390
|
+
description TEXT NOT NULL DEFAULT '',
|
|
391
|
+
source TEXT NOT NULL DEFAULT 'local',
|
|
392
|
+
skillId TEXT NOT NULL DEFAULT '',
|
|
393
|
+
command TEXT NOT NULL DEFAULT '',
|
|
394
|
+
hasFile INTEGER NOT NULL DEFAULT 0,
|
|
395
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
396
|
+
isCustom INTEGER NOT NULL DEFAULT 0,
|
|
397
|
+
parentSkillIds TEXT NOT NULL DEFAULT '[]',
|
|
398
|
+
createdAt TEXT NOT NULL,
|
|
399
|
+
updatedAt TEXT NOT NULL
|
|
400
|
+
)
|
|
373
401
|
`),a.exec(`
|
|
374
402
|
CREATE TABLE IF NOT EXISTS swarms (
|
|
375
403
|
id TEXT PRIMARY KEY,
|
|
@@ -618,7 +646,7 @@ ${h?"Binary file":"File too large to preview"} (untracked)
|
|
|
618
646
|
connectedAt TEXT NOT NULL,
|
|
619
647
|
FOREIGN KEY (workspaceId) REFERENCES workspaces(id) ON DELETE CASCADE
|
|
620
648
|
)
|
|
621
|
-
`);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
|
|
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(`
|
|
622
650
|
SELECT w.id, w.name, w.color, w.defaultCommand, w.terminalCount, w.layout
|
|
623
651
|
FROM workspaces w
|
|
624
652
|
LEFT JOIN areas a ON a.workspaceId = w.id
|
|
@@ -626,7 +654,7 @@ ${h?"Binary file":"File too large to preview"} (untracked)
|
|
|
626
654
|
`).all();if(t.length===0)return;let r=new Date().toISOString(),s=a.prepare(`
|
|
627
655
|
INSERT INTO areas (id, workspaceId, name, color, directory, useWorktree, defaultCommand, terminalCount, layout, "order", isDefault, createdAt, updatedAt)
|
|
628
656
|
VALUES (?, ?, ?, ?, '', 0, ?, ?, ?, 0, 1, ?, ?)
|
|
629
|
-
`),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=
|
|
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(`
|
|
630
658
|
`)+`
|
|
631
|
-
`;process.stdout.write(o)}catch{}}renderHeader(e){let t=
|
|
632
|
-
</head>`);e.writeHead(200,{"Content-Type":"text/html"}),e.end(c)}catch{e.writeHead(500),e.end("Internal server error")}return}let s=
|
|
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()});
|