impactus-swarm 0.0.21 → 0.0.22

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "impactus-swarm",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "description": "AI-powered terminal swarm orchestration platform",
5
5
  "type": "module",
6
6
  "bin": {
package/server/main.js CHANGED
@@ -36,7 +36,7 @@ set -gx TERM_PROGRAM impactus-swarm
36
36
  `),n=pe(r,".bashrc_impactus");return await Bt(n,s,"utf-8"),{...a.getEnvVars("bash"),BASH_ENV:n}}}catch{}return a.getEnvVars(e)}};var Nn=Mn(import.meta.url),Nr=Nn("node-pty");function Dr(){return process.platform==="win32"?process.env.COMSPEC||"cmd.exe":process.env.SHELL||"/bin/zsh"}async function Wt(){let a=Dr(),e=Ie.detectShell(a);return Ie.createInjectionEnv(e)}async function qt(a){let e=Dr(),t=[],r=await Wt(),{PORT:s,IMPACTUS_WEB_DIR:n,RELAY_URL:i,RELAY_ALLOWED_IPS:o,CLAUDECODE:c,...l}=process.env;return Nr.spawn(e,t,{name:"xterm-256color",cols:a.cols,rows:a.rows,cwd:a.cwd,env:{...l,...r,TERM_PROGRAM:"ghostty",TERM_PROGRAM_VERSION:"3.0.0",KITTY_WINDOW_ID:"1",COLORTERM:"truecolor",...a.env}})}function Ht(a,e,t){return Nr.spawn("tmux",a,{name:"xterm-256color",cols:e,rows:t,cwd:On()})}import{execFileSync as O}from"node:child_process";import{existsSync as Dn,writeFileSync as Pn,mkdirSync as xn}from"node:fs";import{join as Pr}from"node:path";import{homedir as _n}from"node:os";var N="impactus",xe="impactus-",b=class{static _available=null;static _configPath=null;static isAvailable(){if(this._available!==null)return this._available;if(process.platform==="win32")return this._available=!1,!1;try{O("tmux",["-V"],{stdio:"pipe"}),this._available=!0}catch{this._available=!1}return this._available}static ensureConfig(){if(this._configPath)return this._configPath;let e=Pr(_n(),".impactus-swarm");Dn(e)||xn(e,{recursive:!0});let t=Pr(e,"tmux.conf");return Pn(t,["# IMPACTUS Swarm tmux config \u2014 auto-generated, do not edit","set -g status off","set -g history-limit 50000",'set -g default-terminal "xterm-256color"',"set -g escape-time 10","set -g focus-events on","set -g mouse off","# Suppress DA queries \u2014 tell tmux the outer terminal capabilities","# Disable smcup/rmcup so tmux does NOT enter alternate screen in","# xterm.js \u2014 this allows xterm.js scrollback to accumulate normally.","# TUI apps inside tmux still use tmux's internal alternate screen.",'set -as terminal-overrides ",xterm*:Tc:smcup@:rmcup@"'].join(`
37
37
  `)+`
38
38
  `),this._configPath=t,t}static enablePassthrough(){try{O("tmux",["-L",N,"set-option","-g","allow-passthrough","on"],{stdio:"pipe"})}catch{}try{O("tmux",["-L",N,"set-option","-g","escape-time","10"],{stdio:"pipe"})}catch{}}static sessionName(e){return xe+e.replace(/[^a-zA-Z0-9_-]/g,"_")}static createSession(e,t,r,s,n,i){let o=this.sessionName(e),c=this.ensureConfig(),l=["-L",N,"-f",c,"new-session","-d","-s",o,"-x",String(t),"-y",String(r),"-c",s];for(let[f,h]of Object.entries(n))h!==void 0&&h!==""&&l.push("-e",`${f}=${h}`);if(i)for(let[f,h]of Object.entries(i))h!==void 0&&l.push("-e",`${f}=${h}`);let{PORT:d,IMPACTUS_WEB_DIR:u,RELAY_URL:p,RELAY_ALLOWED_IPS:m,...g}=process.env;O("tmux",l,{stdio:"pipe",env:g});try{O("tmux",["-L",N,"set-environment","-t",o,"IMPACTUS_TERMINAL_ID",e],{stdio:"pipe"}),O("tmux",["-L",N,"set-environment","-t",o,"IMPACTUS_CREATED_AT",String(Date.now())],{stdio:"pipe"})}catch{}return this.enablePassthrough(),o}static getAttachArgs(e){return["-L",N,"attach-session","-t",e]}static killSession(e){try{O("tmux",["-L",N,"kill-session","-t",e],{stdio:"pipe"})}catch{}}static listSessions(){try{let e=O("tmux",["-L",N,"list-sessions","-F","#{session_name}"],{stdio:"pipe"}).toString().trim();return e?e.split(`
39
- `).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+$/,`
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"],{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
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
42
  `))return a.split("\r").filter(s=>s.length>0).every(s=>Ur(s));let t=a.split(`
@@ -46,7 +46,7 @@ set -gx TERM_PROGRAM impactus-swarm
46
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
47
  `);for(let s of r){let n=s.trim();if(n.length===0)continue;let i=Vr(n);for(let o of i)if(this.pushHandler("terminal.output-event",{terminalId:e,type:o.type,data:o.data}),o.type==="api-error"){let c=this.terminals.get(e);c&&!c.questionEmitted&&(c.questionEmitted=!0,c.questionEmittedAt=Date.now(),this.pushHandler("terminal.awaiting-input",{terminalId:e,type:"error",confident:!0,promptText:o.data.message||"API Error"}))}}}};var va=process.platform==="win32",Vt=new Set(["zsh","bash","sh","fish","dash","ksh","tcsh","csh","ps","grep","rg","cmd.exe","powershell.exe","pwsh.exe","conhost.exe","cmd","powershell","pwsh","conhost"]),We=class a{terminals=new Map;pushHandler;commandBlockParser=new Re;outputEventParser;processDetectionInterval;useTmux;constructor(e){this.pushHandler=e,this.outputEventParser=new $e(e),this.useTmux=b.isAvailable(),this.useTmux?console.log("[terminal] tmux available \u2014 persistent sessions enabled"):console.log("[terminal] tmux not available \u2014 sessions will not persist across restarts"),this.processDetectionInterval=setInterval(()=>{this.detectProcesses()},3e3)}detectProcesses(){for(let[,e]of this.terminals){let t=this.detectProcessForTerminal(e),r=e.lastProcessInfo;(!r||r.foregroundProcess!==t.foregroundProcess||r.isIdle!==t.isIdle)&&(e.lastProcessInfo=t,this.pushHandler("terminal.process",{id:e.id,process:t}))}}getEffectivePid(e){if(e.tmuxSession){let t=b.getShellPid(e.tmuxSession);if(t)return t}return e.pty.pid}detectProcessForTerminal(e){let t=this.getEffectivePid(e),r;try{if(va){let n=Be(`wmic process where (ParentProcessId=${t}) get Name /format:list`,{stdio:"pipe",timeout:2e3}).toString().trim().split(`
48
48
  `).map(i=>i.replace(/^Name=/,"").trim()).filter(i=>i&&!Vt.has(i)&&!Vt.has(i.replace(/\.exe$/i,"")));n.length>0&&(r=n[0].replace(/\.exe$/i,""))}else{let s=Be(`ps -p ${t} -o tty= 2>/dev/null`,{stdio:"pipe",timeout:2e3}).toString().trim();if(s&&s!=="?"){let i=Be(`ps -o comm= -t ${s} 2>/dev/null`,{stdio:"pipe",timeout:2e3}).toString().trim().split(`
49
- `).map(o=>{let c=o.trim();return c.split("/").pop()||c}).filter(o=>o&&!Vt.has(o));i.length>0&&(r=i[0])}}}catch{}return{id:e.id,pid:t,foregroundProcess:r,isIdle:r===void 0}}dispose(){clearInterval(this.processDetectionInterval),this.outputEventParser.dispose()}getProcessInfo(e){let t=this.terminals.get(e);return t?t.lastProcessInfo??this.detectProcessForTerminal(t):null}getAllProcessInfo(){return Array.from(this.terminals.values()).map(e=>e.lastProcessInfo??this.detectProcessForTerminal(e))}async open(e,t){this.terminals.has(e.id)&&this.close(e.id);let r=e.cwd==="~"?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(`
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.getSessionSize(t.tmuxSession),s=b.capturePane(t.tmuxSession);if(s){let n=b.getCursorPosition(t.tmuxSession);return{data:n?s+`\x1B[${n.y+1};${n.x+1}H`:s,cols:r?.cols,rows:r?.rows}}}return t.outputBuffer?{data:t.outputBuffer}:{data:""}}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
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 = ?,
@@ -89,7 +89,7 @@ You can document your own discoveries for teammates to benefit from.`),s.push(""
89
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
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(`
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",startupCommand:"claude",defaultPaths:{darwin:["~/.local/bin/claude","/usr/local/bin/claude","/opt/homebrew/bin/claude"],linux:["~/.local/bin/claude","/usr/local/bin/claude"],win32:["%APPDATA%\\npm\\claude.cmd","%USERPROFILE%\\.local\\bin\\claude.exe"]}},{id:"codex",label:"Codex",command:"codex",startupCommand:"codex",defaultPaths:{darwin:["/opt/homebrew/bin/codex","/usr/local/bin/codex","~/.local/bin/codex"],linux:["/usr/local/bin/codex","~/.local/bin/codex"],win32:["%APPDATA%\\npm\\codex.cmd"]}},{id:"gemini",label:"Gemini",command:"gemini",startupCommand:"gemini",defaultPaths:{darwin:["/opt/homebrew/bin/gemini","/usr/local/bin/gemini","~/.local/bin/gemini"],linux:["/usr/local/bin/gemini","~/.local/bin/gemini"],win32:["%APPDATA%\\npm\\gemini.cmd"]}},{id:"opencode",label:"OpenCode",command:"opencode",startupCommand:"opencode",defaultPaths:{darwin:["/opt/homebrew/bin/opencode","/usr/local/bin/opencode"],linux:["/usr/local/bin/opencode","~/.local/bin/opencode"],win32:["%LOCALAPPDATA%\\opencode\\opencode.exe"]}},{id:"cursor",label:"Cursor",command:"cursor",startupCommand:"cursor",defaultPaths:{darwin:["/usr/local/bin/cursor","/Applications/Cursor.app/Contents/MacOS/Cursor"],linux:["/usr/local/bin/cursor","/usr/bin/cursor"],win32:["%LOCALAPPDATA%\\Programs\\Cursor\\cursor.exe"]}}];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
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
94
  `)}function ge(a,e){let r=["engine","overview","features","stack","screens","review","done"].indexOf(e),s=ws[e],n=!1;for(let i of a.conversation){if(i.role==="system"&&i.content===s){n=!0;continue}if(n&&i.role==="user")return i.content}}function Ts(a){let e=ge(a,"overview")??"",t=ge(a,"features")??"",r=ge(a,"screens")??"",s=a.stack.map(h=>tt.find(w=>w.id===h)?.name??h),n=a.stack.map(h=>tt.find(w=>w.id===h)).filter(Boolean),i=["# PRD - Product Requirements Document","","## Visao Geral","",e,"","## Funcionalidades","",...t.split(`
95
95
  `).map(h=>{let w=h.trim();return w?w.startsWith("-")?w:`- ${w}`:""}),"","## Stack Tecnologica","",...s.map(h=>`- ${h}`),"","## Telas","",r,"","---",`Gerado em ${new Date().toISOString()}`].join(`
@@ -298,7 +298,7 @@ _No file content available._`)}let o=i.join(`
298
298
 
299
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
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(`
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,r=e.services.terminalManager.getOutputBuffer(t.id);return{ok:!0,data:r?.data||"",cols:r?.cols,rows:r?.rows}},"terminal.restart":async(a,e)=>{let t=a;return e.services.terminalManager.close(t.id),await e.services.terminalManager.open(t),{ok:!0}},"terminal.upload":async(a,e)=>{let t=a,r=50*1024*1024;if(Math.ceil(t.fileData.length*3/4)>r)return e.respondError("File too large (max 50MB)"),null;let n=e.services.terminalManager.getCwd(t.terminalId);if(!n)return e.respondError(`Terminal ${t.terminalId} not found or CWD unavailable`),null;let i=await import("node:fs"),o=await import("node:path"),c=o.basename(t.fileName);if(!c||c==="."||c==="..")return e.respondError("Invalid file name"),null;let l=o.resolve(n,c);if(!l.startsWith(n+o.sep)&&l!==n)return e.respondError("Invalid file path"),null;if(i.existsSync(l)){let p=o.extname(c),m=c.slice(0,c.length-p.length),g=1;for(;i.existsSync(l);)l=o.resolve(n,`${m} (${g})${p}`),g++}let d=Buffer.from(t.fileData,"base64");i.writeFileSync(l,d);let u="'"+l.replace(/'/g,"'\\''")+"'";return e.services.terminalManager.write(t.terminalId,u+" "),{ok:!0,path:l}},"terminal.set-color":(a,e)=>{let t=a;if(t.areaId)e.services.areaManager.setTerminalColor(t.terminalId,t.areaId,t.color);else if(e.services.workspaceManager.get(t.workspaceId)){let s=e.services.areaManager.getDefaultArea(t.workspaceId);s&&e.services.areaManager.setTerminalColor(t.terminalId,s.id,t.color)}return{ok:!0}}}}function $s(){return{"workspace.list":(a,e)=>e.services.workspaceManager.list(),"workspace.get":(a,e)=>{let t=a,r=e.services.workspaceManager.get(t.id);return r||(e.respondError(`Workspace ${t.id} not found`),null)},"workspace.create":(a,e)=>{let t=a;return e.services.workspaceManager.create(t)},"workspace.update":(a,e)=>{let t=a;return e.services.workspaceManager.update(t)},"workspace.delete":(a,e)=>{let t=a;return{deleted:e.services.workspaceManager.delete(t.id)}},"workspace.launch":async(a,e)=>{let t=a,{workspaceManager:r,areaManager:s,portMonitor:n}=e.services,i=r.get(t.id);if(!i)return e.respondError(`Workspace ${t.id} not found`),null;let o=s.getDefaultArea(i.id);if(!o)return e.respondError(`No default area found for workspace ${t.id}`),null;let c=s.resolveForLaunch(o,i.rootDirectory),l=new Map(o.terminals.map(u=>[u.id,u.color||"default"])),d={ok:!0,terminals:c.map(u=>({id:u.id,label:u.label,cwd:u.cwd,position:u.position,color:l.get(u.id)||"default"}))};return e.respond(d),(async()=>{try{await ae(c,e.services,o.id,{completedStepsProvider:u=>s.getCompletedSteps(u),onStepCompleted:(u,p)=>{s.markStepCompleted(u,p)}}),s.setRunning(o.id,!0),e.services.broadcast("area.status",{id:o.id,workspaceId:t.id,state:"running"}),r.setRunning(t.id,!0),e.services.broadcast("workspace.status",{id:t.id,state:"running"}),n.startMonitoring(t.id,c.map(u=>u.id)).catch(console.error)}catch(u){console.error("[server] workspace.launch async error:",u)}})(),null},"workspace.getSetupConfig":(a,e)=>{let t=a,{workspaceManager:r,areaManager:s}=e.services,n=r.get(t.id);if(!n)return e.respondError(`Workspace ${t.id} not found`),null;let i=s.getDefaultArea(t.id);return{workspace:{id:n.id,name:n.name,color:n.color,rootDirectory:n.rootDirectory,defaultCommand:n.defaultCommand,terminalCount:n.terminalCount,initGit:n.initGit,createdAt:n.createdAt},area:i?{id:i.id,name:i.name,terminalCount:i.terminalCount,layout:i.layout,defaultCommand:i.defaultCommand,ignoreOnLaunchAll:i.ignoreOnLaunchAll??!1}:null,terminals:i?i.terminals.map(o=>({id:o.id,label:o.label,directory:o.directory,command:o.command,commandSequence:o.commandSequence,startDelay:o.startDelay,startWaitFor:o.startWaitFor,startRunOnce:o.startRunOnce,closeAfterCommand:o.closeAfterCommand,closeDelay:o.closeDelay,closeWaitFor:o.closeWaitFor,runOnce:o.runOnce,commandRunOnce:o.commandRunOnce,color:o.color})):[]}},"workspace.relaunch":async(a,e)=>{let t=a,{workspaceManager:r,areaManager:s,terminalManager:n,portMonitor:i}=e.services,o=r.get(t.id);if(!o)return e.respondError(`Workspace ${t.id} not found`),null;let c=s.getDefaultArea(o.id);if(!c)return e.respondError(`No default area found for workspace ${t.id}`),null;let l=s.list(t.id);for(let g of l){for(let f of g.terminals)n.close(f.id);s.setRunning(g.id,!1)}r.setRunning(t.id,!1),i.stopMonitoring(t.id);let u=l.filter(g=>!g.ignoreOnLaunchAll).map(g=>{s.resetAllTerminals(g.id);let f=s.resolveForLaunch(g,o.rootDirectory);return{area:g,resolved:f}});if(u.length===0){s.resetAllTerminals(c.id);let g=s.resolveForLaunch(c,o.rootDirectory);u.push({area:c,resolved:g})}let p=u.find(g=>g.area.id===c.id)??u[0],m=new Map(p.area.terminals.map(g=>[g.id,g.color||"default"]));return e.respond({ok:!0,terminals:p.resolved.map(g=>({id:g.id,label:g.label,cwd:g.cwd,position:g.position,color:m.get(g.id)||"default"}))}),(async()=>{let g=[];await Promise.all(u.map(async({area:f,resolved:h})=>{try{let w=f.trigger;if(w){let T=w.timeoutMs??12e4;w.type==="delay"?await new Promise(E=>setTimeout(E,w.delayMs??0)):w.type==="waitForOutput"&&w.dependsOnTerminalId&&w.waitForText?await Le(n,w.dependsOnTerminalId,w.waitForText,T):w.type==="waitForExit"&&w.dependsOnTerminalId&&await Ms(n,w.dependsOnTerminalId,T)}await ae(h,e.services,f.id,{ignoreRunOnce:!0,completedStepsProvider:T=>s.getCompletedSteps(T),onStepCompleted:(T,E)=>{s.markStepCompleted(T,E)}}),s.setRunning(f.id,!0),e.services.broadcast("area.status",{id:f.id,workspaceId:t.id,state:"running"});for(let T of h)g.push(T.id)}catch(w){console.error(`[server] workspace.relaunch error for area ${f.id}:`,w)}})),r.setRunning(t.id,!0),e.services.broadcast("workspace.status",{id:t.id,state:"running"}),g.length>0&&i.startMonitoring(t.id,g).catch(console.error)})(),null},"workspace.stop":(a,e)=>{let t=a,{workspaceManager:r,areaManager:s,terminalManager:n,portMonitor:i}=e.services,o=r.get(t.id);if(!o)return e.respondError(`Workspace ${t.id} not found`),null;let c=s.list(t.id);for(let l of c){for(let d of l.terminals)n.close(d.id);s.setRunning(l.id,!1),e.services.broadcast("area.status",{id:l.id,workspaceId:t.id,state:"stopped"})}for(let l of o.terminals)n.close(l.id);return r.setRunning(t.id,!1),e.services.broadcast("workspace.status",{id:t.id,state:"stopped"}),i.stopMonitoring(t.id),{ok:!0}}}}function Bs(){return{"area.list":(a,e)=>{let t=a;return e.services.areaManager.list(t.workspaceId)},"area.create":(a,e)=>{let t=a;return e.services.areaManager.create(t)},"area.update":(a,e)=>{let t=a;return e.services.areaManager.update(t)},"area.delete":(a,e)=>{let t=a;return{deleted:e.services.areaManager.delete(t.id)}},"area.duplicate":(a,e)=>{let t=a;return e.services.areaManager.duplicate(t.id,t.name)},"area.launch":async(a,e)=>{let t=a,{areaManager:r,workspaceManager:s}=e.services,n=r.get(t.areaId);if(!n)return e.respondError(`Area ${t.areaId} not found`),null;let i=s.get(t.workspaceId);if(!i)return e.respondError(`Workspace ${t.workspaceId} not found`),null;let o=r.resolveForLaunch(n,i.rootDirectory),c=new Map(n.terminals.map(d=>[d.id,d.color||"default"])),l={ok:!0,terminals:o.map(d=>({id:d.id,label:d.label,cwd:d.cwd,position:d.position,color:c.get(d.id)||"default"}))};return e.respond(l),(async()=>{try{await ae(o,e.services,t.areaId,{completedStepsProvider:d=>r.getCompletedSteps(d),onStepCompleted:(d,u)=>{r.markStepCompleted(d,u)}}),r.setRunning(t.areaId,!0),s.setRunning(t.workspaceId,!0),e.services.broadcast("area.status",{id:t.areaId,workspaceId:t.workspaceId,state:"running"}),e.services.broadcast("workspace.status",{id:t.workspaceId,state:"running"})}catch(d){console.error("[server] area.launch async error:",d)}})(),null},"area.stop":(a,e)=>{let t=a,{areaManager:r,workspaceManager:s,terminalManager:n}=e.services,i=r.get(t.areaId);if(!i)return e.respondError(`Area ${t.areaId} not found`),null;for(let l of i.terminals)n.close(l.id);return r.setRunning(t.areaId,!1),r.clearRuntimeState(t.areaId),r.list(t.workspaceId).some(l=>l.id!==t.areaId&&r.isRunning(l.id))||(s.setRunning(t.workspaceId,!1),e.services.broadcast("workspace.status",{id:t.workspaceId,state:"stopped"})),e.services.broadcast("area.status",{id:t.areaId,workspaceId:t.workspaceId,state:"stopped"}),{ok:!0}},"area.save-runtime-state":(a,e)=>{let t=a;return e.services.areaManager.saveRuntimeState(t.areaId,t.data),{ok:!0}},"area.get-runtime-state":(a,e)=>{let t=a;return{data:e.services.areaManager.getRuntimeState(t.areaId)}},"area.clear-runtime-state":(a,e)=>{let t=a;return e.services.areaManager.clearRuntimeState(t.areaId),{ok:!0}}}}function Ws(){return{"swarm.create":(a,e)=>{let t=a;return e.services.swarmManager.create(t)},"swarm.launch":async(a,e)=>{let t=a;return await e.services.swarmManager.launch(t.id),{ok:!0}},"swarm.stop":(a,e)=>{let t=a;return e.services.swarmManager.stop(t.id),{ok:!0}},"swarm.pause":(a,e)=>{let t=a;return e.services.swarmManager.pause(t.id),{ok:!0}},"swarm.resume":(a,e)=>{let t=a;return e.services.swarmManager.resume(t.id),{ok:!0}},"swarm.status":(a,e)=>{let t=a,r=e.services.swarmManager.get(t.id);return r?{...r,stats:e.services.swarmManager.getStats(t.id)}:(e.respondError(`Swarm ${t.id} not found`),null)},"swarm.list":(a,e)=>{let t=a;return e.services.swarmManager.list(t.workspaceId)},"swarm.delete":(a,e)=>{let t=a;return{deleted:e.services.swarmManager.delete(t.id)}},"swarm.message":(a,e)=>{let t=a;return e.services.swarmManager.message(t.swarmId,t.agentId,t.message),{ok:!0}},"swarm.agent.add":(a,e)=>{let t=a;return e.services.swarmManager.addAgent(t)},"swarm.agent.remove":(a,e)=>{let t=a;return{removed:e.services.swarmManager.removeAgent(t)}},"swarm.agent.update":(a,e)=>{let t=a;return e.services.swarmManager.updateAgent(t)},"orchestrator.topology.set":(a,e)=>{let t=a;return e.services.swarmManager.setTopology(t.swarmId,t.topology),{ok:!0}},"orchestrator.spawn-cli":async(a,e)=>{let t=a;return await e.services.swarmManager.spawnCLI(t.swarmId,t.agentId,t.config)},"orchestrator.escalation.respond":(a,e)=>{let t=a;return e.services.swarmManager.respondToEscalation(t.escalationId,t.response),{ok:!0}}}}import{mkdir as mr,writeFile as Mt,cp as Fi}from"node:fs/promises";import{basename as $i,join as ee,resolve as Bi}from"node:path";var Me=class{async buildContext(e){let{task:t,agent:r,swarm:s,knowledgeEntries:n,dependencyTasks:i,workspaceDir:o}=e,c=ee(o,".swarm","tasks",t.id);await mr(c,{recursive:!0});let l=this.assemblePrompt(t,r,n,i),d=ee(c,"CLAUDE.md"),u=this.generateClaudeMd(t,r,s);await Mt(d,u,"utf-8");let p=this.generateTaskMd(t,i);if(await Mt(ee(c,"TASK.md"),p,"utf-8"),s?.knowledge&&s.knowledge.length>0){let m=ee(c,"knowledge");await mr(m,{recursive:!0});for(let g of s.knowledge)try{let f=$i(g.name),h=Bi(g.path),w=ee(m,f);await Fi(h,w)}catch{}}return{contextDir:c,prompt:l,claudeMdPath:d}}assemblePrompt(e,t,r,s){let n=[];if(n.push(`# Task: ${e.title}`,""),n.push(e.description,""),n.push("## Agent",""),n.push(`- **Name:** ${t.name}`),n.push(`- **Role:** ${t.role}`),n.push(""),t.workScope&&t.workScope.length>0){n.push("## Work Scope","");for(let i of t.workScope)n.push(`- ${i}`);n.push("")}if(s&&s.length>0){n.push("## Dependencies","");for(let i of s)n.push(`### ${i.title} (${i.status})`),i.output&&n.push("","Output:","",i.output),n.push("")}if(r&&r.length>0){n.push("## Knowledge Base","");for(let i of r)n.push(`- ${i.name} (${i.type}): \`${i.path}\``);n.push("")}switch(n.push(`## Approval Mode: ${e.approvalMode}`,""),e.approvalMode){case"auto":n.push("You may proceed autonomously without waiting for human approval.");break;case"semi":n.push("Proceed with implementation but pause before destructive or irreversible actions.");break;case"manual":n.push("Wait for explicit human approval before making any changes.");break}return n.push(""),n.join(`
302
302
  `)}generateClaudeMd(e,t,r){let s=[`# Agent: ${t.name}`,`## Role: ${t.role}`,"","## Mission",e.description,""];return r&&s.push("## Working Directory",r.directory,""),t.systemPrompt&&s.push("## System Prompt",t.systemPrompt,""),t.workScope&&t.workScope.length>0&&s.push("## Work Scope",...t.workScope.map(n=>`- ${n}`),""),s.push("## Current Task",""),s.push(`- **ID:** ${e.id}`),s.push(`- **Title:** ${e.title}`),s.push(`- **Approval Mode:** ${e.approvalMode}`),s.push(""),t.role==="coordinator"&&r&&s.push("## Coordinator Instructions",`You are the coordinator of a swarm of ${r.agents.length} agents.`,"Your job is to orchestrate the other agents to complete the mission.","Monitor their outputs, delegate tasks, and ensure quality.","","## Agents in this Swarm",...r.agents.map(n=>`- ${n.name} (${n.role}): ${n.systemPrompt||"No specific prompt"}`),""),s.join(`
303
303
  `)}async buildStandaloneContext(e){let{task:t,prompt:r,workspaceDir:s}=e,n=ee(s,".swarm","tasks",t.id);await mr(n,{recursive:!0});let i=this.generateTaskMd(t);await Mt(ee(n,"TASK.md"),i,"utf-8");let o=ee(n,"CLAUDE.md"),c=[`# Task: ${t.title}`,"","## Mission",r,"","## Current Task",`- **ID:** ${t.id}`,`- **Title:** ${t.title}`,`- **Approval Mode:** ${t.approvalMode}`,""].join(`
304
304
  `);return await Mt(o,c,"utf-8"),{contextDir:n,prompt:r,claudeMdPath:o}}generateTaskMd(e,t){let r=[`# Task: ${e.title}`,"",`- **ID:** ${e.id}`,`- **Status:** ${e.status}`,`- **Approval Mode:** ${e.approvalMode}`,`- **Created:** ${e.createdAt}`,"","## Description","",e.description,""];if(t&&t.length>0){r.push("## Dependencies","");for(let s of t){if(r.push(`### ${s.title}`),r.push(`- **ID:** ${s.id}`),r.push(`- **Status:** ${s.status}`),s.output&&r.push("- **Output:**","",s.output),s.filesChanged&&s.filesChanged.length>0){r.push("- **Files Changed:**");for(let n of s.filesChanged)r.push(` - ${n}`)}r.push("")}}return r.join(`